Commit 69cb3955 authored by frtabu's avatar frtabu

fix phy simulators build Pb: move snr_dB global to simulation code, add a...

fix phy simulators build Pb: move snr_dB global to simulation code, add a channel mode section in configuration for snr_dB ,add a parameter flag in the config module to allow omitting prefix when modifying a parameter (for compatibility of -s option)
parent d59833fe
...@@ -1833,7 +1833,7 @@ ${OPENAIR1_DIR}/SIMULATION/TOOLS/channel_sim.c ...@@ -1833,7 +1833,7 @@ ${OPENAIR1_DIR}/SIMULATION/TOOLS/channel_sim.c
${OPENAIR1_DIR}/SIMULATION/RF/rf.c ${OPENAIR1_DIR}/SIMULATION/RF/rf.c
${OPENAIR1_DIR}/SIMULATION/RF/dac.c ${OPENAIR1_DIR}/SIMULATION/RF/dac.c
${OPENAIR1_DIR}/SIMULATION/RF/adc.c ${OPENAIR1_DIR}/SIMULATION/RF/adc.c
${OPENAIR_DIR}/targets/ARCH/rfsimulator/channelmod.c ${OPENAIR_DIR}/targets/ARCH/rfsimulator/apply_channelmod.c
#${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c #${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
) )
......
## config module management
```c ```c
configmodule_interface_t *load_configmodule(int argc, char **argv, uint32_t initflags) configmodule_interface_t *load_configmodule(int argc, char **argv, uint32_t initflags)
``` ```
...@@ -14,23 +16,17 @@ void End_configmodule(void) ...@@ -14,23 +16,17 @@ void End_configmodule(void)
* Free memory which has been allocated by the configuration module since its initialization. * Free memory which has been allocated by the configuration module since its initialization.
* Possibly calls the `config_<config source>_end` function * Possibly calls the `config_<config source>_end` function
## Retrieving parameter's values
```c ```c
int config_get(paramdef_t *params,int numparams, char *prefix) int config_get(paramdef_t *params,int numparams, char *prefix)
``` ```
* Reads as many parameters as described in params, they must all be in the same configuration file section * Reads as many parameters as described in params, they must all be in the same configuration file section
* Calls the `config_<config source>_get` function * Calls the `config_<config source>_get` function
* Calls the `config_process_cmdline` function * Calls the `config_process_cmdline` function
* `params` points to an array of `paramdef_t` structures which describes the parameters to be read, possibly including a pointer to a checking function. The following bits can possibly be set in the `paramflags` mask before calling * `params` points to an array of `paramdef_t` structures which describes the parameters to be read, possibly including a pointer to a checking function.The `paramflags` bit mask can be used to modify how a specific parameter is processed and the same mask is also used by the configuration module to return information about how the parameter has been processed. Bits definitions are described in the [`paramdef_t` structure description](./struct.md)
- `PARAMFLAG_MANDATORY`: -1 is returned if the parameter is not explicitly defined in the config source.
- `PARAMFLAG_DISABLECMDLINE`: parameter cannot be modified via the command line
- `PARAMFLAG_DONOTREAD`: ignore the parameter, can be used at run-time, to alter a pre-defined `paramdef_t` array which is used in several `config_get` or/and `config_getlist` calls.
- `PARAMFLAG_NOFREE`: do not free the memory possibly allocated by the config module to store the value of the parameter. Default behavior is for the config module to free the memory it has allocated when the `config_end` function is called.
- `PARAMFLAG_BOOL`: Only relevant for integer types. tell the config module that when processing the command line, the corresponding option can be specified without any arggument and that in this case it must set the value to 1.
* `params` is also used as an output parameter, `< XXX >ptr >` field is used by the config module to store the value it has read. The following bits can possibly be set in the `paramflags` mask after the call:
- `PARAMFLAG_MALLOCINCONFIG`: memory has been allocated for the ` < XXX >ptr > ` field
- `PARAMFLAG_PARAMSET`: parameter has been found in the config source, it is not set to default value.
- `PARAMFLAG_PARAMSET`: parameter has been set to its default value
* `numparams` is the number of entries in the params array * `numparams` is the number of entries in the params array
* `prefix` is a character string to be appended to the parameters name, it defines the parameters position in the configuration file hierarchy (the section name in libconfig terminology). * `prefix` is a character string to be appended to the parameters name, it defines the parameters position in the configuration file hierarchy (the section name in libconfig terminology).
* The returned value is the number of parameters which have been assigned a value or -1 if a severe error occured * The returned value is the number of parameters which have been assigned a value or -1 if a severe error occured
...@@ -44,6 +40,9 @@ int config_libconfig_getlist(paramlist_def_t *ParamList, paramdef_t *params, int ...@@ -44,6 +40,9 @@ int config_libconfig_getlist(paramlist_def_t *ParamList, paramdef_t *params, int
* `ParamList` points to a structure, where `paramarray` field points to an array of `paramdef_t` structure, allocated by the function. It is used to return the values of the parameters. * `ParamList` points to a structure, where `paramarray` field points to an array of `paramdef_t` structure, allocated by the function. It is used to return the values of the parameters.
* The returned value is the number of occurrences in the list or -1 in case of severe error * The returned value is the number of occurrences in the list or -1 in case of severe error
## utility functions and macros
The configuration module also defines APIs to access the `paramdef_t` and `configmodule_interface_t` fields. They are listed in the configuration module [include file `common/config/config_userapi.h`](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_userapi.h)
[Configuration module developer main page](../../config/devusage.md) [Configuration module developer main page](../../config/devusage.md)
[Configuration module home](../../config.md) [Configuration module home](../../config.md)
...@@ -5,6 +5,7 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla ...@@ -5,6 +5,7 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla
|:-----------|:------------------------------------------------------------------|----:| |:-----------|:------------------------------------------------------------------|----:|
| `optname` | parameter name, as used when looking for it in the config source, 63 bytes max (64 with trailing \0) | I | | `optname` | parameter name, as used when looking for it in the config source, 63 bytes max (64 with trailing \0) | I |
| `helstr` | pointer to a C string printed when using --help on the command line | I | | `helstr` | pointer to a C string printed when using --help on the command line | I |
| `paramflags` | bit mask, used to modify how the parameter is processed, or to return to the API caller how the parameter has been set, see list in the next table | IO |
| `strptr` `strlistptr` `u8ptr` `i8ptr` `u16ptr` `i16ptr` `uptr` `iptr` `u64ptr` `i64ptr` `dblptr` `voidptr` | a pointer to a variable where the parameter value(s) will be returned. This field is an anonymous union, the supported pointer types have been built to avoid type mismatch warnings at compile time. | O | | `strptr` `strlistptr` `u8ptr` `i8ptr` `u16ptr` `i16ptr` `uptr` `iptr` `u64ptr` `i64ptr` `dblptr` `voidptr` | a pointer to a variable where the parameter value(s) will be returned. This field is an anonymous union, the supported pointer types have been built to avoid type mismatch warnings at compile time. | O |
| `defstrval` `defstrlistval` `defuintval` `defintval` `defint64val` `defintarrayval` `defdblval` | this field is an anonymous union, it can be used to define the default value for the parameter. It is ignored if `PARAMFLAG_MANDATORY` is set in the `paramflags` field.| I | | `defstrval` `defstrlistval` `defuintval` `defintval` `defint64val` `defintarrayval` `defdblval` | this field is an anonymous union, it can be used to define the default value for the parameter. It is ignored if `PARAMFLAG_MANDATORY` is set in the `paramflags` field.| I |
| `type` | Supported parameter types are defined as integer macros. Supported simple types are `TYPE_STRING`, parameter value is returned in `strptr` field, `TYPE_INT8` `TYPE_UINT8` `TYPE_INT16` `TYPE_UINT16` `TYPE_INT32` `TYPE_UINT32` `TYPE_INT64` `TYPE_UINT64`, parameter value is returned in the corresponding uXptr or iXptr, `TYPE_MASK`, value is returned in `u32ptr`, `TYPE_DOUBLE` value is returned in `dblptr`, `TYPE_IPV4ADDR` value is returned in binary, network bytes order in `u32ptr` field. `TYPE_STRINGLIST`, `TYPE_INTARRAY` and `TYPE_UINTARRAY` are multiple values types. Multiple values are returned in respectively, `strlistptr`, `iptr` and `uptr` fields which then point to arrays. The `numelt` field gives the number of item in the array. | I | | `type` | Supported parameter types are defined as integer macros. Supported simple types are `TYPE_STRING`, parameter value is returned in `strptr` field, `TYPE_INT8` `TYPE_UINT8` `TYPE_INT16` `TYPE_UINT16` `TYPE_INT32` `TYPE_UINT32` `TYPE_INT64` `TYPE_UINT64`, parameter value is returned in the corresponding uXptr or iXptr, `TYPE_MASK`, value is returned in `u32ptr`, `TYPE_DOUBLE` value is returned in `dblptr`, `TYPE_IPV4ADDR` value is returned in binary, network bytes order in `u32ptr` field. `TYPE_STRINGLIST`, `TYPE_INTARRAY` and `TYPE_UINTARRAY` are multiple values types. Multiple values are returned in respectively, `strlistptr`, `iptr` and `uptr` fields which then point to arrays. The `numelt` field gives the number of item in the array. | I |
...@@ -12,6 +13,22 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla ...@@ -12,6 +13,22 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla
| `chkPptr` | possible pointer to the structure containing the info used to check parameter values | I | | `chkPptr` | possible pointer to the structure containing the info used to check parameter values | I |
| `processedvalue` | When `chkPptr` is not `ǸULL`, is used to return a value, computed from the original parameter, as read from the configuration source. | O | | `processedvalue` | When `chkPptr` is not `ǸULL`, is used to return a value, computed from the original parameter, as read from the configuration source. | O |
## `paramflags` bits definition
| C macro bit definition | usage | I/O |
|:-------------------------------------|:---------------------------------------------------------------------------------------------------------------------|----:|
| `PARAMFLAG_MANDATORY` | parameter is mandatory, comfiguration module will stop the process if it is not specified. Default value is ignored | I |
| `PARAMFLAG_DISABLECMDLINE` | parameter cannot be specified on the command line | I |
| `PARAMFLAG_DONOTREAD` | ignore the parameter, usefull when a parameter group is used in different context | I |
| `PARAMFLAG_NOFREE` | The end_configmodule API won't free the memory which has been possibly allocated to store the value of the parameter.| I |
| `PARAMFLAG_BOOL` | Parameter is a boolean, it can be specified without a value to set it to true | I |
| `PARAMFLAG_CMDLINE_NOPREFIXENABLED` | parameter can be specified without the prefix on the command line. Must be used with care, carefuly checking unicity, especially for short parameter names | I |
| `PARAMFLAG_MALLOCINCONFIG` | Memory for the parameter value has been allocated by the configuration module |O |
| `PARAMFLAG_PARAMSET` | Parameter value has been explicitely set, as the parameter was specified either on the command line or the config source | O |
| `PARAMFLAG_PARAMSETDEF` | Parameter value has been set to it's default | O |
# `paramlist_def_t`structure # `paramlist_def_t`structure
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L160). It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L160).
It is used as an argument to `config_getlist` calls, to get values of multiple occurrences of group of parameters. It is used as an argument to `config_getlist` calls, to get values of multiple occurrences of group of parameters.
......
...@@ -167,8 +167,8 @@ int config_check_unknown_cmdlineopt(char *prefix) { ...@@ -167,8 +167,8 @@ int config_check_unknown_cmdlineopt(char *prefix) {
char testprefix[CONFIG_MAXOPTLENGTH]; char testprefix[CONFIG_MAXOPTLENGTH];
int finalcheck = 0; int finalcheck = 0;
memset(testprefix,0,sizeof(testprefix)); memset(testprefix,0,sizeof(testprefix));
memset(testprefix,0,sizeof(testprefix)); memset(testprefix,0,sizeof(testprefix));
if (prefix != NULL) { if (prefix != NULL) {
if (strcmp(prefix,CONFIG_CHECKALLSECTIONS) == 0) if (strcmp(prefix,CONFIG_CHECKALLSECTIONS) == 0)
finalcheck = 1; finalcheck = 1;
...@@ -253,7 +253,9 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix) ...@@ -253,7 +253,9 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix)
} }
if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */ if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) ) { ((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) || /* long option beginning with "--" */
((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgoptions[n].optname) == 0) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ||
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 ) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ) {
char *valptr=NULL; char *valptr=NULL;
int ret; int ret;
config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED;
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define PARAMFLAG_DONOTREAD (1 << 2) // parameter must be ignored in get function #define PARAMFLAG_DONOTREAD (1 << 2) // parameter must be ignored in get function
#define PARAMFLAG_NOFREE (1 << 3) // don't free parameter in end function #define PARAMFLAG_NOFREE (1 << 3) // don't free parameter in end function
#define PARAMFLAG_BOOL (1 << 4) // integer param can be 0 or 1 #define PARAMFLAG_BOOL (1 << 4) // integer param can be 0 or 1
#define PARAMFLAG_CMDLINE_NOPREFIXENABLED (1 << 5) // on the command line, allow a parameter to be specified without the prefix
/* Flags used by config modules to return info to calling modules and/or to for internal usage*/ /* Flags used by config modules to return info to calling modules and/or to for internal usage*/
#define PARAMFLAG_MALLOCINCONFIG (1 << 15) // parameter allocated in config module #define PARAMFLAG_MALLOCINCONFIG (1 << 15) // parameter allocated in config module
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
#include "sim.h" #include "sim.h"
#include "scm_corrmat.h" #include "scm_corrmat.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "common/utils/load_module_shlib.h" #include "common/config/config_userapi.h"
#include "common/utils/telnetsrv/telnetsrv.h" #include "common/utils/telnetsrv/telnetsrv.h"
#include "common/utils/load_module_shlib.h"
//#define DEBUG_CH //#define DEBUG_CH
...@@ -54,6 +54,9 @@ static telnetshell_vardef_t channelmod_vardef[] = { ...@@ -54,6 +54,9 @@ static telnetshell_vardef_t channelmod_vardef[] = {
{"",0,NULL} {"",0,NULL}
}; };
static double snr_dB=25;
static double sinr_dB=0;
void fill_channel_desc(channel_desc_t *chan_desc, void fill_channel_desc(channel_desc_t *chan_desc,
uint8_t nb_tx, uint8_t nb_tx,
uint8_t nb_rx, uint8_t nb_rx,
...@@ -1497,18 +1500,31 @@ static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) { ...@@ -1497,18 +1500,31 @@ static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
return 0; return 0;
} }
int init_channelmod(char *modelname) { int modelid_fromname(char *modelname) {
int modelid=map_str_to_int(channelmod_names,modelname); int modelid=map_str_to_int(channelmod_names,modelname);
AssertFatal(modelid>0, AssertFatal(modelid>0,
"random_channel.c: Error channel model %s unknown\n",modelname); "random_channel.c: Error channel model %s unknown\n",modelname);
/* look for telnet server, if it is loaded, add the coding commands to it */ return modelid;
}
double channelmod_get_snr_dB(void) {
return snr_dB;
}
double channelmod_get_sinr_dB(void) {
return sinr_dB;
}
void init_channelmod(void) {
paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC;
int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed");
/* look for telnet server, if it is loaded, add the channel modeling commands to it */
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
if (addcmd != NULL) { if (addcmd != NULL) {
addcmd("channelmod",channelmod_vardef,channelmod_cmdarray); addcmd("channelmod",channelmod_vardef,channelmod_cmdarray);
} }
return modelid;
} }
#ifdef RANDOM_CHANNEL_MAIN #ifdef RANDOM_CHANNEL_MAIN
......
...@@ -211,6 +211,13 @@ typedef enum { ...@@ -211,6 +211,13 @@ typedef enum {
{"EPA_high",EPA_high},\ {"EPA_high",EPA_high},\
{NULL, -1} {NULL, -1}
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
#define CHANNELMOD_SECTION "channelmod"
#define CHANNELMOD_PARAMS_DESC { \
{"s" ,CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED , dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\
{"sinr_dB" ,NULL, 0 , dblptr:&sinr_dB, defdblval:0, TYPE_DOUBLE, 0},\
}
#include "platform_constants.h" #include "platform_constants.h"
typedef struct { typedef struct {
...@@ -432,7 +439,11 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si ...@@ -432,7 +439,11 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si
uint64_t TS, uint64_t TS,
uint32_t CirSize uint32_t CirSize
); );
int init_channelmod(char *channelname) ;
int modelid_fromname(char *modelname);
double channelmod_get_snr_dB(void);
double channelmod_get_sinr_dB(void);
void init_channelmod(void) ;
double N_RB2sampling_rate(uint16_t N_RB); double N_RB2sampling_rate(uint16_t N_RB);
double N_RB2channel_bandwidth(uint16_t N_RB); double N_RB2channel_bandwidth(uint16_t N_RB);
......
...@@ -52,7 +52,7 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si ...@@ -52,7 +52,7 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ? // 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 // 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) // −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; const double rxGain= 132.24 - channelmod_get_snr_dB();
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts) // sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
// fixme: the last constant is pure trial results to make decent noise // 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; const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
// Fixme: datamodel, external variables in .h files, ... // Fixme: datamodel, external variables in .h files, ...
#include <common/ran_context.h> #include <common/ran_context.h>
extern double snr_dB;
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
// //
...@@ -91,7 +91,7 @@ typedef struct { ...@@ -91,7 +91,7 @@ typedef struct {
int tx_num_channels; int tx_num_channels;
double sample_rate; double sample_rate;
double tx_bw; double tx_bw;
bool enable_channelmod; int channelmod;
} rfsimulator_state_t; } rfsimulator_state_t;
...@@ -112,7 +112,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -112,7 +112,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
ev.data.fd = sock; ev.data.fd = sock;
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
if ( bridge->enable_channelmod==true) { if ( bridge->channelmod > 0) {
// create channel simulation model for this mode reception // create channel simulation model for this mode reception
// snr_dB is pure global, coming from configuration paramter "-s" // snr_dB is pure global, coming from configuration paramter "-s"
// Fixme: referenceSignalPower should come from the right place // Fixme: referenceSignalPower should come from the right place
...@@ -126,7 +126,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -126,7 +126,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
// Legacy changes directlty the variable channel_model->path_loss_dB place to place // Legacy changes directlty the variable channel_model->path_loss_dB place to place
// while calling new_channel_desc_scm() with path losses = 0 // 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, ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
AWGN, bridge->channelmod,
bridge->sample_rate, bridge->sample_rate,
bridge->tx_bw, bridge->tx_bw,
0.0, // forgetting_factor 0.0, // forgetting_factor
...@@ -239,8 +239,8 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { ...@@ -239,8 +239,8 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
break; break;
} else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) {
init_channelmod(modelname); init_channelmod();
rfsimulator->enable_channelmod=true; rfsimulator->channelmod=modelid_fromname(modelname);
} else { } else {
fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]); fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]);
exit(-1); exit(-1);
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
static softmodem_params_t softmodem_params; static softmodem_params_t softmodem_params;
char *parallel_config=NULL; char *parallel_config=NULL;
char *worker_config=NULL; char *worker_config=NULL;
double snr_dB=25;
uint64_t get_softmodem_optmask(void) { uint64_t get_softmodem_optmask(void) {
return softmodem_params.optmask; return softmodem_params.optmask;
......
...@@ -78,7 +78,6 @@ ...@@ -78,7 +78,6 @@
#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\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_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_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_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" #define CONFIG_HLP_TPORT "tracer port\n"
...@@ -200,7 +199,6 @@ ...@@ -200,7 +199,6 @@
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 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}, \ {"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_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}, \ {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
...@@ -285,8 +283,6 @@ uint64_t get_pdcp_optmask(void); ...@@ -285,8 +283,6 @@ uint64_t get_pdcp_optmask(void);
extern pthread_cond_t sync_cond; extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex; extern pthread_mutex_t sync_mutex;
extern int sync_var; extern int sync_var;
extern double snr_dB;
extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
...@@ -311,7 +307,7 @@ extern void stop_eNB(int); ...@@ -311,7 +307,7 @@ extern void stop_eNB(int);
extern void kill_eNB_proc(int inst); extern void kill_eNB_proc(int inst);
// In lte-ru.c // In lte-ru.c
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);
extern void stop_ru(RU_t *ru); extern void stop_ru(RU_t *ru);
extern void init_ru_vnf(void); extern void init_ru_vnf(void);
extern void init_RU_proc(RU_t *ru); extern void init_RU_proc(RU_t *ru);
...@@ -337,7 +333,7 @@ extern void kill_td_thread(PHY_VARS_eNB *); ...@@ -337,7 +333,7 @@ extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *); extern void kill_te_thread(PHY_VARS_eNB *);
extern void RCConfig_sim(void); extern void RCConfig_sim(void);
extern void init_ocm(double,double); extern void init_ocm(void);
extern void init_ue_devices(PHY_VARS_UE *); extern void init_ue_devices(PHY_VARS_UE *);
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
......
...@@ -811,7 +811,7 @@ int main( int argc, char **argv ) { ...@@ -811,7 +811,7 @@ int main( int argc, char **argv ) {
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
if (IS_SOFTMODEM_SIML1 ) { if (IS_SOFTMODEM_SIML1 ) {
init_ocm(snr_dB,0); init_ocm();
PHY_vars_UE_g[0][0]->no_timing_correction = 1; PHY_vars_UE_g[0][0]->no_timing_correction = 1;
} }
......
...@@ -63,14 +63,12 @@ sim_t sim; ...@@ -63,14 +63,12 @@ sim_t sim;
void init_ru_devices(void); 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 *rfsim_top(void *n_frames);
void wait_RUs(void) void wait_RUs(void) {
{
int i; int i;
// wait for all RUs to be configured over fronthaul // wait for all RUs to be configured over fronthaul
pthread_mutex_lock(&RC.ru_mutex); pthread_mutex_lock(&RC.ru_mutex);
...@@ -81,47 +79,36 @@ void wait_RUs(void) ...@@ -81,47 +79,36 @@ void wait_RUs(void)
pthread_mutex_unlock(&RC.ru_mutex); pthread_mutex_unlock(&RC.ru_mutex);
// copy frame parameters from RU to UEs // 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; 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"); printf("RUs are ready, let's go\n");
} }
void wait_eNBs(void) void wait_eNBs(void) {
{
return; return;
} }
void RCConfig_sim(void) { void RCConfig_sim(void) {
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
// Get num RU instances // Get num RU instances
config_getlist( &RUParamList,NULL,0, NULL); config_getlist( &RUParamList,NULL,0, NULL);
RC.nb_RU = RUParamList.numelt; RC.nb_RU = RUParamList.numelt;
AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n"); AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n");
printf("returned with %d rus\n",RC.nb_RU); printf("returned with %d rus\n",RC.nb_RU);
init_RU(NULL,internal,internal,0); 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(); wait_RUs();
init_ru_devices(); init_ru_devices();
static int nframes = 100000; static int nframes = 100000;
AssertFatal(0 == pthread_create(&sim.rfsim_thread, AssertFatal(0 == pthread_create(&sim.rfsim_thread,
NULL, NULL,
rfsim_top, rfsim_top,
(void*)&nframes), ""); (void *)&nframes), "");
} }
...@@ -164,16 +151,11 @@ extern int subframe_ru_mask,subframe_UE_mask; ...@@ -164,16 +151,11 @@ 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_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int ru_id = device->Mod_id; int ru_id = device->Mod_id;
int CC_id = device->CC_id; int CC_id = device->CC_id;
int subframe; int subframe;
int sample_count=0; int sample_count=0;
*ptimestamp = sim.last_ru_rx_timestamp[ru_id][CC_id]; *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, 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.current_ru_rx_timestamp[ru_id][CC_id],
(unsigned long long)sim.last_ru_rx_timestamp[ru_id][CC_id], (unsigned long long)sim.last_ru_rx_timestamp[ru_id][CC_id],
...@@ -187,9 +169,8 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -187,9 +169,8 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
usleep(500); usleep(500);
} }
subframe = (sim.last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms.samples_per_tti)%10; 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) { 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", LOG_D(SIM,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
subframe,(unsigned long long)*ptimestamp, subframe,(unsigned long long)*ptimestamp,
...@@ -204,27 +185,23 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -204,27 +185,23 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
CC_id); CC_id);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,0); 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; 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; sample_count += RC.ru[ru_id]->frame_parms.samples_per_tti;
} }
return(nsamps); 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,1);
int UE_id = device->Mod_id; int UE_id = device->Mod_id;
int CC_id = device->CC_id; int CC_id = device->CC_id;
int subframe; int subframe;
int sample_count=0; int sample_count=0;
int read_size; int read_size;
int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti; 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]; *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", LOG_D(PHY,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n",
UE_id, UE_id,
nsamps, nsamps,
...@@ -233,7 +210,6 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -233,7 +210,6 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti), (int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti),
cc); cc);
if (nsamps < sptti) if (nsamps < sptti)
read_size = nsamps; read_size = nsamps;
else else
...@@ -241,33 +217,28 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -241,33 +217,28 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
while (sample_count<nsamps) { 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]); 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] < while (sim.current_UE_rx_timestamp[UE_id][CC_id] <
(sim.last_UE_rx_timestamp[UE_id][CC_id]+read_size)) { (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]); 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); 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 // if we cross a subframe-boundary
subframe = (sim.last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10; 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); pthread_mutex_lock(&sim.subframe_mutex);
sim.subframe_UE_mask|=(1<<UE_id); 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); LOG_D(SIM,"Setting UE_id %d mask to busy (%d)\n",UE_id,sim.subframe_UE_mask);
pthread_mutex_unlock(&sim.subframe_mutex); 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", 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, UE_id,subframe,(unsigned long long)*ptimestamp,
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id], (unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
nsamps); nsamps);
LOG_D(SIM,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n", 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, UE_id,nsamps,subframe,
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti)); (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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,1);
do_DL_sig(&sim, do_DL_sig(&sim,
subframe, subframe,
...@@ -283,13 +254,8 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -283,13 +254,8 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
sim.last_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), (int)((sim.last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
subframe); subframe);
sim.last_UE_rx_timestamp[UE_id][CC_id] += read_size; sim.last_UE_rx_timestamp[UE_id][CC_id] += read_size;
sample_count += read_size; sample_count += read_size;
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,0);
...@@ -298,51 +264,45 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -298,51 +264,45 @@ 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_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
int ru_id = device->Mod_id; int ru_id = device->Mod_id;
LTE_DL_FRAME_PARMS *frame_parms = &RC.ru[ru_id]->frame_parms; LTE_DL_FRAME_PARMS *frame_parms = &RC.ru[ru_id]->frame_parms;
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
LOG_D(SIM,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,sim.subframe_ru_mask); 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 // 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; sim.ru_amp[ru_id] = 0;
for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) { 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] += (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))); 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 // tell top-level we are done
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
sim.subframe_ru_mask|=(1<<ru_id); sim.subframe_ru_mask|=(1<<ru_id);
LOG_D(SIM,"Setting RU %d to busy\n",ru_id); LOG_D(SIM,"Setting RU %d to busy\n",ru_id);
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
return(nsamps); return(nsamps);
} }
int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
return(nsamps); return(nsamps);
} }
void init_ru_devices(){ void init_ru_devices() {
module_id_t ru_id; module_id_t ru_id;
RU_t *ru; RU_t *ru;
// allocate memory for RU if not already done // 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); 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));
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t *)malloc(sizeof(RU_t));
ru = RC.ru[ru_id]; ru = RC.ru[ru_id];
ru->rfdevice.Mod_id = ru_id; ru->rfdevice.Mod_id = ru_id;
ru->rfdevice.CC_id = 0; ru->rfdevice.CC_id = 0;
...@@ -354,12 +314,10 @@ void init_ru_devices(){ ...@@ -354,12 +314,10 @@ void init_ru_devices(){
ru->rfdevice.trx_set_freq_func = ru_trx_set_freq; ru->rfdevice.trx_set_freq_func = ru_trx_set_freq;
ru->rfdevice.trx_set_gains_func = ru_trx_set_gains; ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
sim.last_ru_rx_timestamp[ru_id][0] = 0; sim.last_ru_rx_timestamp[ru_id][0] = 0;
} }
} }
void init_ue_devices(PHY_VARS_UE *UE) { void init_ue_devices(PHY_VARS_UE *UE) {
AssertFatal(UE!=NULL,"UE context is not allocated\n"); AssertFatal(UE!=NULL,"UE context is not allocated\n");
printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id); printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id);
UE->rfdevice.Mod_id = UE->Mod_id; UE->rfdevice.Mod_id = UE->Mod_id;
...@@ -374,23 +332,21 @@ void init_ue_devices(PHY_VARS_UE *UE) { ...@@ -374,23 +332,21 @@ void init_ue_devices(PHY_VARS_UE *UE) {
sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0; 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; module_id_t UE_id, ru_id;
int CC_id; int CC_id;
randominit(0); randominit(0);
set_taus_seed(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); init_channel_vars ();//fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0);
// initialize channel descriptors // initialize channel descriptors
LOG_I(PHY,"Initializing channel descriptors (nb_RU %d, nb_UE %d)\n",RC.nb_RU,NB_UE_INST); 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 (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) { for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_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, 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); RC.ru[ru_id]->frame_parms.N_RB_DL);
sim.RU2UE[ru_id][UE_id][CC_id] = sim.RU2UE[ru_id][UE_id][CC_id] =
...@@ -404,8 +360,6 @@ void init_ocm(double snr_dB,double sinr_dB) ...@@ -404,8 +360,6 @@ void init_ocm(double snr_dB,double sinr_dB)
0); 0);
random_channel(sim.RU2UE[ru_id][UE_id][CC_id],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); 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] = 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, new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
RC.ru[ru_id]->nb_rx, RC.ru[ru_id]->nb_rx,
...@@ -415,14 +369,12 @@ void init_ocm(double snr_dB,double sinr_dB) ...@@ -415,14 +369,12 @@ void init_ocm(double snr_dB,double sinr_dB)
0.0, 0.0,
0, 0,
0); 0);
random_channel(sim.UE2RU[UE_id][ru_id][CC_id],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. // 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]; //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.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.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 //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
if (ru_id == (UE_id % RC.nb_RU)) { 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.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
...@@ -435,26 +387,22 @@ void init_ocm(double snr_dB,double sinr_dB) ...@@ -435,26 +387,22 @@ void init_ocm(double snr_dB,double sinr_dB)
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, 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, sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_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; module_id_t UE_id, ru_id;
int CC_id; int CC_id;
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) { for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) { for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_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.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.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 //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
if (ru_id == (UE_id % RC.nb_RU)) { 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.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
...@@ -467,58 +415,50 @@ void update_ocm(double snr_dB,double sinr_dB) ...@@ -467,58 +415,50 @@ void update_ocm(double snr_dB,double sinr_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, 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, sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_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; int i;
memset(sim.RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX); 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); pthread_mutex_init(&sim.RU_output_mutex[i],NULL);
memset(sim.UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX); 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) { void *rfsim_top(void *n_frames) {
wait_sync("rfsim_top"); 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; for (int frame = 0;
frame < *(int*)n_frames; frame < *(int *)n_frames;
frame++) { frame++) {
for (int sf = 0; sf < 10; sf++) { for (int sf = 0; sf < 10; sf++) {
int CC_id=0; int CC_id=0;
int all_done=0; int all_done=0;
while (all_done==0) {
while (all_done==0) {
pthread_mutex_lock(&sim.subframe_mutex); 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_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); 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); 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); 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)) && if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) &&
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1; (subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
else usleep(1500); else usleep(1500);
} }
//clear subframe masks for next round //clear subframe masks for next round
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
sim.subframe_ru_mask=0; sim.subframe_ru_mask=0;
...@@ -526,17 +466,19 @@ void *rfsim_top(void *n_frames) { ...@@ -526,17 +466,19 @@ void *rfsim_top(void *n_frames) {
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
// increment timestamps // increment timestamps
for (int ru_id=0;ru_id<RC.nb_RU;ru_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; 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]); 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++) {
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; 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]); 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 @@ ...@@ -27,7 +27,7 @@
#include "PHY/defs_UE.h" #include "PHY/defs_UE.h"
#include "PHY/defs_eNB.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); void update_ocm(double snr_dB,double sinr_dB);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment