rewrite synchronisation in oaisim/channel simulation
The idea is as follows. oaisim waits for all tasks to be done for a TTI. To do so it waits for last_rx_timestamp == current_rx_timestamp, for all UEs and eNBs. When it's done, it increases current_rx_timestamp by samples_per_tti, to inform UEs and eNBs that a new TTI is ready. In the functions [UE|eNB]_trx_read, we wait for a new TTI to be ready, that is we wait for current_rx_timestamp != last_rx_timestamp. The UE has also to wait for processing threads to be done. In the eNB it's not necessary because the processing is all done in one thread, that is: read subframe, process this subframe, emit subframe+4, and then back to read subframe. The code is not clean. We should not use usleep but semaphores. Also, do_[DL|UL]_sig should not read from rxdata and write to txdata, but use internal buffers. The functions [UE|eNB]_trx_read should call do_[DL|UL]_sig and then copy from the internal buffers of the channel simulator into rxdata. The functions [UE|eNB]_trx_write should write data passed into the internal buffers of the channel simulator.
This commit is contained in:
+24
-20
@@ -457,7 +457,8 @@ l2l1_task_state_t l2l1_state = L2L1_WAITTING;
|
||||
|
||||
extern openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
|
||||
extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
|
||||
|
||||
extern openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
|
||||
extern openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void *
|
||||
@@ -731,38 +732,41 @@ l2l1_task (void *args_p)
|
||||
|
||||
clear_eNB_transport_info (oai_emulation.info.nb_enb_local);
|
||||
|
||||
CC_id=0;
|
||||
int all_done=0;
|
||||
while (all_done==0) {
|
||||
pthread_mutex_lock(&subframe_mutex);
|
||||
int subframe_eNB_mask_local = subframe_eNB_mask;
|
||||
int subframe_UE_mask_local = subframe_UE_mask;
|
||||
pthread_mutex_unlock(&subframe_mutex);
|
||||
LOG_D(EMU,"Frame %d, Subframe %d: Checking masks %x,%x\n",frame,sf,subframe_eNB_mask,subframe_UE_mask);
|
||||
if ((subframe_eNB_mask_local == ((1<<NB_eNB_INST)-1)) &&
|
||||
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1)))
|
||||
all_done=1;
|
||||
else
|
||||
int i;
|
||||
all_done = 1;
|
||||
for (i = oai_emulation.info.first_enb_local;
|
||||
i < oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local;
|
||||
i++)
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
|
||||
if (last_eNB_rx_timestamp[i][CC_id] != current_eNB_rx_timestamp[i][CC_id]) {
|
||||
all_done = 0;
|
||||
break;
|
||||
}
|
||||
if (all_done == 1)
|
||||
for (i = 0; i < NB_UE_INST; i++)
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
|
||||
if (last_UE_rx_timestamp[i][CC_id] != current_UE_rx_timestamp[i][CC_id]) {
|
||||
all_done = 0;
|
||||
break;
|
||||
}
|
||||
if (all_done == 0)
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
//clear subframe masks for next round
|
||||
pthread_mutex_lock(&subframe_mutex);
|
||||
subframe_eNB_mask=0;
|
||||
subframe_UE_mask=0;
|
||||
pthread_mutex_unlock(&subframe_mutex);
|
||||
|
||||
// increment timestamps
|
||||
for (eNB_inst = oai_emulation.info.first_enb_local;
|
||||
(eNB_inst
|
||||
< (oai_emulation.info.first_enb_local
|
||||
+ oai_emulation.info.nb_enb_local));
|
||||
eNB_inst++) {
|
||||
|
||||
current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
|
||||
current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
}
|
||||
for (UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
|
||||
current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
|
||||
current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
}
|
||||
|
||||
for (eNB_inst = oai_emulation.info.first_enb_local;
|
||||
|
||||
@@ -998,13 +998,15 @@ int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
extern pthread_mutex_t subframe_mutex;
|
||||
extern int subframe_eNB_mask,subframe_UE_mask;
|
||||
|
||||
int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
|
||||
{
|
||||
int ret = nsamps;
|
||||
int eNB_id = device->Mod_id;
|
||||
int CC_id = device->CC_id;
|
||||
|
||||
int subframe;
|
||||
int sample_count=0;
|
||||
int read_samples, max_samples;
|
||||
openair0_timestamp last = last_eNB_rx_timestamp[eNB_id][CC_id];
|
||||
|
||||
*ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id];
|
||||
|
||||
@@ -1014,49 +1016,55 @@ int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void *
|
||||
(*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10);
|
||||
// if we're at a subframe boundary generate UL signals for this eNB
|
||||
|
||||
while (sample_count<nsamps) {
|
||||
while (current_eNB_rx_timestamp[eNB_id][CC_id]<
|
||||
(nsamps+last_eNB_rx_timestamp[eNB_id][CC_id])) {
|
||||
while (nsamps) {
|
||||
while (current_eNB_rx_timestamp[eNB_id][CC_id] == last) {
|
||||
LOG_D(EMU,"eNB: current TS %llu, last TS %llu, sleeping\n",current_eNB_rx_timestamp[eNB_id][CC_id],last_eNB_rx_timestamp[eNB_id][CC_id]);
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
// tell top-level we are busy
|
||||
pthread_mutex_lock(&subframe_mutex);
|
||||
subframe_eNB_mask|=(1<<eNB_id);
|
||||
pthread_mutex_unlock(&subframe_mutex);
|
||||
read_samples = nsamps;
|
||||
max_samples = current_eNB_rx_timestamp[eNB_id][CC_id]-last;
|
||||
if (read_samples > max_samples)
|
||||
read_samples = max_samples;
|
||||
|
||||
last += read_samples;
|
||||
nsamps -= read_samples;
|
||||
|
||||
if (current_eNB_rx_timestamp[eNB_id][CC_id] == last) {
|
||||
subframe = (last/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
|
||||
//subframe = (subframe+9) % 10;
|
||||
|
||||
LOG_D(PHY,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]);
|
||||
|
||||
subframe = (last_eNB_rx_timestamp[eNB_id][CC_id]/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
|
||||
LOG_D(PHY,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]);
|
||||
|
||||
do_UL_sig(UE2eNB,
|
||||
enb_data,
|
||||
ue_data,
|
||||
subframe,
|
||||
0, // abstraction_flag
|
||||
&PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
|
||||
0, // frame is only used for abstraction
|
||||
eNB_id,
|
||||
CC_id);
|
||||
|
||||
last_eNB_rx_timestamp[eNB_id][CC_id] += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
|
||||
sample_count += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
|
||||
do_UL_sig(UE2eNB,
|
||||
enb_data,
|
||||
ue_data,
|
||||
subframe,
|
||||
0, // abstraction_flag
|
||||
&PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
|
||||
0, // frame is only used for abstraction
|
||||
eNB_id,
|
||||
CC_id);
|
||||
|
||||
last_eNB_rx_timestamp[eNB_id][CC_id] = last;
|
||||
}
|
||||
}
|
||||
|
||||
last_eNB_rx_timestamp[eNB_id][CC_id] = last;
|
||||
|
||||
|
||||
return(nsamps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int ret = nsamps;
|
||||
int UE_id = device->Mod_id;
|
||||
int CC_id = device->CC_id;
|
||||
int subframe;
|
||||
int sample_count=0;
|
||||
int read_size;
|
||||
int read_samples, max_samples;
|
||||
openair0_timestamp last = last_UE_rx_timestamp[UE_id][CC_id];
|
||||
|
||||
*ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];
|
||||
|
||||
@@ -1065,14 +1073,19 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
|
||||
(unsigned long long)last_UE_rx_timestamp[UE_id][CC_id],
|
||||
cc);
|
||||
|
||||
if (nsamps < PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)
|
||||
read_size = nsamps;
|
||||
else
|
||||
read_size = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
|
||||
|
||||
while (sample_count<nsamps) {
|
||||
while (current_UE_rx_timestamp[UE_id][CC_id] <
|
||||
(last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
|
||||
while (nsamps) {
|
||||
/* wait for all processing to be finished */
|
||||
while (1) {
|
||||
PHY_VARS_UE *UE = PHY_vars_UE_g[UE_id][0];
|
||||
int ready = 1;
|
||||
int i;
|
||||
for (i = 0; i < 2; i++)
|
||||
if (UE->proc.proc_rxtx[i].instance_cnt_rxtx >= 0) ready = 0;
|
||||
if (UE->proc.instance_cnt_synch >= 0) ready = 0;
|
||||
if (ready) break;
|
||||
usleep(500);
|
||||
}
|
||||
while (current_UE_rx_timestamp[UE_id][CC_id] == last) {
|
||||
LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
|
||||
usleep(500);
|
||||
@@ -1080,40 +1093,39 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
|
||||
|
||||
LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
|
||||
// tell top-level we are busy
|
||||
pthread_mutex_lock(&subframe_mutex);
|
||||
subframe_UE_mask|=(1<<UE_id);
|
||||
pthread_mutex_unlock(&subframe_mutex);
|
||||
read_samples = nsamps;
|
||||
max_samples = current_UE_rx_timestamp[UE_id][CC_id]-last;
|
||||
if (read_samples > max_samples)
|
||||
read_samples = max_samples;
|
||||
|
||||
last += read_samples;
|
||||
nsamps -= read_samples;
|
||||
|
||||
// otherwise we have one subframe here so generate the received signal
|
||||
subframe = (last_UE_rx_timestamp[UE_id][CC_id]/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10;
|
||||
if ((last_UE_rx_timestamp[UE_id][CC_id]%PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) > 0)
|
||||
subframe++;
|
||||
if (current_UE_rx_timestamp[UE_id][CC_id] == last) {
|
||||
// we have one subframe here so generate the received signal
|
||||
subframe = (last/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10;
|
||||
//subframe = (subframe+9) % 10;
|
||||
|
||||
last_UE_rx_timestamp[UE_id][CC_id] += read_size;
|
||||
sample_count += read_size;
|
||||
|
||||
if (subframe > 9)
|
||||
return(nsamps);
|
||||
|
||||
LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n",
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]);
|
||||
do_DL_sig(eNB2UE,
|
||||
enb_data,
|
||||
ue_data,
|
||||
subframe,
|
||||
0, //abstraction_flag,
|
||||
&PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
|
||||
UE_id,
|
||||
CC_id);
|
||||
LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n",
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]);
|
||||
|
||||
do_DL_sig(eNB2UE,
|
||||
enb_data,
|
||||
ue_data,
|
||||
subframe,
|
||||
0, //abstraction_flag,
|
||||
&PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
|
||||
UE_id,
|
||||
CC_id);
|
||||
|
||||
last_UE_rx_timestamp[UE_id][CC_id] = last;
|
||||
}
|
||||
}
|
||||
|
||||
last_UE_rx_timestamp[UE_id][CC_id] = last;
|
||||
|
||||
return(nsamps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
|
||||
Reference in New Issue
Block a user