Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zzha zzha
OpenXG-RAN
Commits
e2c32228
Commit
e2c32228
authored
May 09, 2016
by
Raymond Knopp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removal of EXPRESSMIMO #ifdef's in lte-ue. move UE-specific code from lte-softmodem.c to lte-ue.c
parent
58ba0089
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
96 additions
and
1570 deletions
+96
-1570
cmake_targets/CMakeLists.txt
cmake_targets/CMakeLists.txt
+0
-13
targets/RT/USER/lte-softmodem.c
targets/RT/USER/lte-softmodem.c
+11
-43
targets/RT/USER/lte-ue.c
targets/RT/USER/lte-ue.c
+85
-584
targets/RT/USER/sched_dlsch.c
targets/RT/USER/sched_dlsch.c
+0
-354
targets/RT/USER/sched_rx_pdsch.c
targets/RT/USER/sched_rx_pdsch.c
+0
-321
targets/RT/USER/sched_ulsch.c
targets/RT/USER/sched_ulsch.c
+0
-255
No files found.
cmake_targets/CMakeLists.txt
View file @
e2c32228
...
...
@@ -259,15 +259,6 @@ if (${ENABLE_ITTI})
endif
(
${
ENABLE_ITTI
}
)
add_boolean_option
(
RTAI False
"Use RTAI"
)
if
(
${
RTAI
}
)
set
(
LOWLATENCY False
)
set
(
CPU_AFFINITY False
)
add_definitions
(
"-DENABLE_RTAI_CLOCK"
)
add_definitions
(
"-DCONFIG_RTAI_LXRT_INLINE"
)
include_directories
(
"/usr/realtime/include"
)
include_directories
(
"/usr/realtime/include/asm"
)
set
(
RTAI_SOURCE sched_dlsch.c sched_rx_pdsch.c rt_wrapper.c vcd_signal_dumper.c log.c
)
endif
(
${
RTAI
}
)
#############################
# ASN.1 grammar C code generation & dependancies
...
...
@@ -1574,8 +1565,6 @@ add_executable(lte-softmodem
${
rrc_h
}
${
s1ap_h
}
${
OPENAIR_BIN_DIR
}
/messages_xml.h
${
OPENAIR_TARGETS
}
/RT/USER/sched_dlsch.c
${
OPENAIR_TARGETS
}
/RT/USER/sched_rx_pdsch.c
${
OPENAIR_TARGETS
}
/RT/USER/rt_wrapper.c
${
OPENAIR_TARGETS
}
/RT/USER/lte-ue.c
${
OPENAIR_TARGETS
}
/RT/USER/lte-softmodem.c
...
...
@@ -1611,8 +1600,6 @@ add_executable(lte-softmodem-nos1
${
rrc_h
}
${
s1ap_h
}
${
OPENAIR_BIN_DIR
}
/messages_xml.h
${
OPENAIR_TARGETS
}
/RT/USER/sched_dlsch.c
${
OPENAIR_TARGETS
}
/RT/USER/sched_rx_pdsch.c
${
OPENAIR_TARGETS
}
/RT/USER/rt_wrapper.c
${
OPENAIR_TARGETS
}
/RT/USER/lte-ue.c
${
OPENAIR_TARGETS
}
/RT/USER/lte-softmodem.c
...
...
targets/RT/USER/lte-softmodem.c
View file @
e2c32228
...
...
@@ -113,12 +113,18 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "stats.h"
#endif
// In lte-enb.c
int
setup_eNB_buffers
(
PHY_VARS_eNB
**
phy_vars_eNB
,
openair0_config_t
*
openair0_cfg
,
openair0_rf_map
rf_map
[
MAX_NUM_CCs
]);
int
setup_ue_buffers
(
PHY_VARS_UE
**
phy_vars_ue
,
openair0_config_t
*
openair0_cfg
,
openair0_rf_map
rf_map
[
MAX_NUM_CCs
]);
extern
void
init_eNB
(
void
);
extern
void
stop_eNB
(
void
);
extern
void
kill_eNB_proc
(
void
);
// In lte-ue.c
int
setup_ue_buffers
(
PHY_VARS_UE
**
phy_vars_ue
,
openair0_config_t
*
openair0_cfg
,
openair0_rf_map
rf_map
[
MAX_NUM_CCs
]);
void
fill_ue_band_info
(
void
);
extern
void
init_UE
(
void
);
#ifdef XFORMS
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
// at eNB 0, an UL scope for every UE
...
...
@@ -130,9 +136,6 @@ unsigned char scope_enb_num_ue = 2;
#endif //XFORMS
pthread_t
main_ue_thread
;
pthread_attr_t
attr_UE_thread
;
...
...
@@ -144,7 +147,6 @@ int sync_var=-1; //!< protected by mutex \ref sync_mutex.
struct
sched_param
sched_param_UE_thread
;
#ifdef XFORMS
...
...
@@ -284,9 +286,8 @@ openair0_config_t openair0_cfg[MAX_CARDS];
double
cpuf
;
char
uecap_xer
[
1024
],
uecap_xer_in
=
0
;
extern
void
*
UE_thread
(
void
*
arg
);
extern
void
init_UE_threads
(
void
);
extern
void
kill_eNB_proc
(
void
);
/*---------------------BMC: timespec helpers -----------------------------*/
...
...
@@ -1120,7 +1121,6 @@ int main( int argc, char **argv )
uint16_t
Nid_cell
=
0
;
uint8_t
cooperation_flag
=
0
,
abstraction_flag
=
0
;
uint8_t
beta_ACK
=
0
,
beta_RI
=
0
,
beta_CQI
=
2
;
int
error_code
;
#if defined (XFORMS)
int
ret
;
...
...
@@ -1752,43 +1752,11 @@ int main( int argc, char **argv )
rt_sleep_ns
(
10
*
100000000ULL
);
pthread_attr_init
(
&
attr_UE_thread
);
pthread_attr_setstacksize
(
&
attr_UE_thread
,
8192
);
//5*PTHREAD_STACK_MIN);
#ifndef LOWLATENCY
sched_param_UE_thread
.
sched_priority
=
sched_get_priority_max
(
SCHED_FIFO
);
pthread_attr_setschedparam
(
&
attr_UE_thread
,
&
sched_param_UE_thread
);
#endif
// start the main thread
if
(
UE_flag
==
1
)
{
printf
(
"Intializing UE Threads ...
\n
"
);
init_UE_threads
();
sleep
(
1
);
error_code
=
pthread_create
(
&
main_ue_thread
,
&
attr_UE_thread
,
UE_thread
,
NULL
);
if
(
error_code
!=
0
)
{
LOG_D
(
HW
,
"[lte-softmodem.c] Could not allocate UE_thread, error %d
\n
"
,
error_code
);
return
(
error_code
);
}
else
{
LOG_D
(
HW
,
"[lte-softmodem.c] Allocate UE_thread successful
\n
"
);
pthread_setname_np
(
main_ue_thread
,
"main UE"
);
}
printf
(
"UE threads created
\n
"
);
#ifdef USE_MME
while
(
start_UE
==
0
)
{
sleep
(
1
);
}
#endif
}
else
{
init_eNB
();
}
if
(
UE_flag
==
1
)
init_UE
();
else
init_eNB
();
// Sleep to allow all threads to setup
sleep
(
1
);
...
...
targets/RT/USER/lte-ue.c
View file @
e2c32228
...
...
@@ -69,11 +69,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
#ifdef EXMIMO
#include "openair0_lib.h"
#else
#include "../../ARCH/COMMON/common_lib.h"
#endif
#include "PHY/extern.h"
#include "SCHED/extern.h"
...
...
@@ -96,10 +92,9 @@ typedef enum {
si
=
2
}
sync_mode_t
;
int
init_dlsch_threads
(
void
);
void
cleanup_dlsch_threads
(
void
);
int32_t
init_rx_pdsch_thread
(
void
);
void
cleanup_rx_pdsch_thread
(
void
);
void
init_UE_threads
(
void
);
void
*
UE_thread
(
void
*
arg
);
void
init_UE
(
void
);
extern
pthread_cond_t
sync_cond
;
extern
pthread_mutex_t
sync_mutex
;
...
...
@@ -125,19 +120,6 @@ extern uint64_t num_missed_slots; // counter for the number of missed slots
extern
void
exit_fun
(
const
char
*
s
);
#ifdef EXMIMO
extern
unsigned
int
rxg_max
[
4
];
extern
unsigned
int
rxg_med
[
4
];
extern
unsigned
int
rxg_byp
[
4
];
extern
unsigned
int
nf_max
[
4
];
extern
unsigned
int
nf_med
[
4
];
extern
unsigned
int
nf_byp
[
4
];
extern
rx_gain_t
rx_gain_mode
[
MAX_NUM_CCs
][
4
];
extern
double
tx_gain
[
MAX_NUM_CCs
][
4
];
extern
double
rx_gain
[
MAX_NUM_CCs
][
4
];
#endif
#define KHz (1000UL)
#define MHz (1000 * KHz)
...
...
@@ -189,6 +171,38 @@ static const eutra_band_t eutra_bands[] = {
{
44
,
703
*
MHz
,
803
*
MHz
,
703
*
MHz
,
803
*
MHz
,
TDD
},
};
pthread_t
main_ue_thread
;
pthread_attr_t
attr_UE_thread
;
struct
sched_param
sched_param_UE_thread
;
void
init_UE
()
{
int
error_code
;
printf
(
"Intializing UE Threads ...
\n
"
);
init_UE_threads
();
sleep
(
1
);
error_code
=
pthread_create
(
&
main_ue_thread
,
&
attr_UE_thread
,
UE_thread
,
NULL
);
if
(
error_code
!=
0
)
{
LOG_D
(
HW
,
"[lte-softmodem.c] Could not allocate UE_thread, error %d
\n
"
,
error_code
);
return
;
}
else
{
LOG_D
(
HW
,
"[lte-softmodem.c] Allocate UE_thread successful
\n
"
);
pthread_setname_np
(
main_ue_thread
,
"main UE"
);
}
printf
(
"UE threads created
\n
"
);
#ifdef USE_MME
while
(
start_UE
==
0
)
{
sleep
(
1
);
}
#endif
}
/*!
* \brief This is the UE synchronize thread.
* It performs band scanning and synchonization.
...
...
@@ -512,15 +526,10 @@ static void *UE_thread_synch(void *arg)
// openair0_cfg[0].rx_gain[0] -= 0;
break
;
}
#ifndef EXMIMO
openair0
.
trx_set_freq_func
(
&
openair0
,
&
openair0_cfg
[
0
],
0
);
//openair0.trx_set_gains_func(&openair0,&openair0_cfg[0]);
//openair0.trx_stop_func(0);
#else
openair0_set_frequencies
(
&
openair0
,
&
openair0_cfg
[
0
],
0
);
openair0_set_gains
(
&
openair0
,
&
openair0_cfg
[
0
]);
openair0_stop
(
0
);
#endif
sleep
(
1
);
init_frame_parms
(
&
UE
->
lte_frame_parms
,
1
);
}
...
...
@@ -550,13 +559,9 @@ static void *UE_thread_synch(void *arg)
}
#ifndef EXMIMO
UE
->
slot_rx
=
0
;
UE
->
slot_tx
=
4
;
#else
UE
->
slot_rx
=
18
;
UE
->
slot_tx
=
2
;
#endif
}
}
else
{
// initial sync failed
...
...
@@ -598,42 +603,13 @@ static void *UE_thread_synch(void *arg)
for
(
i
=
0
;
i
<
openair0_cfg
[
card
].
rx_num_channels
;
i
++
)
{
openair0_cfg
[
card
].
rx_freq
[
i
]
=
downlink_frequency
[
card
][
i
]
+
freq_offset
;
openair0_cfg
[
card
].
tx_freq
[
i
]
=
downlink_frequency
[
card
][
i
]
+
uplink_frequency_offset
[
card
][
i
]
+
freq_offset
;
#ifndef EXMIMO
openair0
.
trx_set_freq_func
(
&
openair0
,
&
openair0_cfg
[
0
],
0
);
#else
openair0_set_frequencies
(
&
openair0
,
&
openair0_cfg
[
0
],
0
);
#endif
#if defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
openair0_cfg
[
card
].
rx_gain
[
i
]
=
UE
->
rx_total_gain_dB
;
//-USRP_GAIN_OFFSET;
#if 0
switch(UE->lte_frame_parms.N_RB_DL) {
case 6:
openair0_cfg[card].rx_gain[i] -= 12;
break;
case 25:
openair0_cfg[card].rx_gain[i] -= 6;
break;
case 50:
openair0_cfg[card].rx_gain[i] -= 0;//3;
break;
case 100:
openair0_cfg[card].rx_gain[i] -= 0;
break;
default:
printf("Unknown number of RBs %d\n",UE->lte_frame_parms.N_RB_DL);
break;
}
#endif
#endif
}
}
if
(
UE
->
UE_scan_carrier
==
1
)
{
...
...
@@ -690,17 +666,6 @@ static void *UE_thread_tx(void *arg)
UE
->
instance_cnt_tx
=-
1
;
#ifdef RTAI
RT_TASK
*
task
=
rt_task_init_schmod
(
nam2num
(
"UE TX Thread"
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][UE] Problem starting UE TX thread!!!!
\n
"
);
return
0
;
}
LOG_D
(
HW
,
"Started UE TX thread (id %p)
\n
"
,
task
);
#else
#ifdef LOWLATENCY
struct
sched_attr
attr
;
unsigned
int
flags
=
0
;
...
...
@@ -745,7 +710,7 @@ static void *UE_thread_tx(void *arg)
exit_fun
(
"Error setting processor affinity"
);
}
}
#endif
#endif
/* Check the actual affinity mask assigned to the thread */
...
...
@@ -790,7 +755,6 @@ static void *UE_thread_tx(void *arg)
(
int
)
sparam
.
sched_priority
,
cpu_affinity
);
#endif
#endif
printf
(
"waiting for sync (UE_thread_tx)
\n
"
);
...
...
@@ -909,17 +873,6 @@ static void *UE_thread_rx(void *arg)
UE
->
instance_cnt_rx
=-
1
;
#ifdef RTAI
RT_TASK
*
task
=
rt_task_init_schmod
(
nam2num
(
"UE RX Thread"
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][UE] Problem starting UE RX thread!!!!
\n
"
);
return
&
UE_thread_rx_retval
;
}
LOG_D
(
HW
,
"Started UE RX thread (id %p)
\n
"
,
task
);
#else
#ifdef LOWLATENCY
struct
sched_attr
attr
;
unsigned
int
flags
=
0
;
...
...
@@ -1008,7 +961,6 @@ static void *UE_thread_rx(void *arg)
(
int
)
sparam
.
sched_priority
,
cpu_affinity
);
#endif
#endif
// Lock memory from swapping. This is a process wide call (not constraint to this thread).
...
...
@@ -1186,7 +1138,7 @@ static void *UE_thread_rx(void *arg)
#ifndef EXMIMO
#define RX_OFF_MAX 10
#define RX_OFF_MIN 5
#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2)
...
...
@@ -1227,16 +1179,6 @@ void *UE_thread(void *arg)
MessageDef
*
message_p
;
#endif
#ifdef RTAI
RT_TASK
*
task
=
rt_task_init_schmod
(
nam2num
(
"UE thread"
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][UE] Problem starting UE thread!!!!
\n
"
);
return
0
;
}
#else
#ifdef LOWLATENCY
struct
sched_attr
attr
;
unsigned
int
flags
=
0
;
...
...
@@ -1264,7 +1206,6 @@ void *UE_thread(void *arg)
struct
sched_param
sp
;
sp
.
sched_priority
=
sched_get_priority_max
(
SCHED_FIFO
);
pthread_setschedparam
(
pthread_self
(),
SCHED_FIFO
,
&
sp
);
#endif
#endif
// Lock memory from swapping. This is a process wide call (not constraint to this thread).
...
...
@@ -1591,409 +1532,8 @@ void *UE_thread(void *arg)
return
&
UE_thread_retval
;
}
#endif
#ifdef EXMIMO
/* This is the main UE thread. Initially it is doing a periodic get_frame. One synchronized it gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */
void
*
UE_thread
(
void
*
arg
)
{
PHY_VARS_UE
*
UE
=
PHY_vars_UE_g
[
0
][
0
];
#ifdef RTAI
RT_TASK
*
task
;
#endif
// RTIME in, out, diff;
int
slot
=
0
,
frame
=
0
,
hw_slot
;
// unsigned int aa;
int
delay_cnt
;
RTIME
time_in
;
int
/* hw_slot_offset=0, */
rx_offset_mbox
=
0
,
mbox_target
=
0
,
mbox_current
=
0
;
int
diff2
;
int
/* i, */
ret
;
int
/* CC_id, */
card
;
volatile
unsigned
int
*
DAQ_MBOX
=
openair0_daq_cnt
();
int
wait_sync_cnt
=
0
;
int
first_synch
=
1
;
#ifdef LOWLATENCY
struct
sched_attr
attr
;
unsigned
int
flags
=
0
;
// unsigned long mask = 1; // processor 0
#endif
int
freq_offset
;
#ifdef RTAI
task
=
rt_task_init_schmod
(
nam2num
(
"UE thread"
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][UE] Problem starting UE thread!!!!
\n
"
);
return
0
;
}
#endif
#ifdef HARD_RT
rt_make_hard_real_time
();
#endif
#ifdef LOWLATENCY
attr
.
size
=
sizeof
(
attr
);
attr
.
sched_flags
=
0
;
attr
.
sched_nice
=
0
;
attr
.
sched_priority
=
0
;
// This creates a .25 ms reservation
attr
.
sched_policy
=
SCHED_DEADLINE
;
attr
.
sched_runtime
=
(
0
.
1
*
100
)
*
10000
;
attr
.
sched_deadline
=
(
0
.
25
*
100
)
*
10000
;
attr
.
sched_period
=
(
0
.
5
*
100
)
*
10000
;
// pin the UE main thread to CPU0
// if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) {
// perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n");
// }
if
(
sched_setattr
(
0
,
&
attr
,
flags
)
<
0
)
{
perror
(
"[SCHED] main UE thread: sched_setattr failed
\n
"
);
exit_fun
(
"Nothing to add"
);
}
else
{
LOG_I
(
HW
,
"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d
\n
"
,
gettid
(),
sched_getcpu
());
}
#endif
mlockall
(
MCL_CURRENT
|
MCL_FUTURE
);
printf
(
"waiting for sync (UE_thread)
\n
"
);
pthread_mutex_lock
(
&
sync_mutex
);
printf
(
"Locked sync_mutex, waiting (UE_thread)
\n
"
);
while
(
sync_var
<
0
)
pthread_cond_wait
(
&
sync_cond
,
&
sync_mutex
);
pthread_mutex_unlock
(
&
sync_mutex
);
printf
(
"unlocked sync_mutex, waiting (UE_thread)
\n
"
);
printf
(
"starting UE thread
\n
"
);
freq_offset
=
0
;
//-7500;
first_synch
=
1
;
while
(
!
oai_exit
)
{
hw_slot
=
(((((
volatile
unsigned
int
*
)
DAQ_MBOX
)[
0
]
+
1
)
%
150
)
<<
1
)
/
15
;
//the slot the hw is about to store
if
(
UE
->
is_synchronized
)
{
if
(
first_synch
==
1
)
{
first_synch
=
0
;
for
(
card
=
0
;
card
<
openair0_num_detected_cards
;
card
++
)
openair0_start_rt_acquisition
(
card
);
rt_sleep_ns
(
FRAME_PERIOD
/
10
);
}
//this is the mbox counter that indicates the start of the frame
rx_offset_mbox
=
(
UE
->
rx_offset
*
150
)
/
(
10
*
UE
->
lte_frame_parms
.
samples_per_tti
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_UE_RX_OFFSET
,
UE
->
rx_offset
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_UE_OFFSET_MBOX
,
rx_offset_mbox
);
//this is the mbox counter where we should be
mbox_target
=
(((((
slot
+
1
)
%
20
)
*
15
+
1
)
>>
1
)
+
rx_offset_mbox
+
1
)
%
150
;
// round up to the next multiple of two (mbox counter from express MIMO gives only even numbers)
mbox_target
=
((
mbox_target
+
1
)
-
((
mbox_target
-
1
)
%
2
))
%
150
;
//this is the mbox counter where we are
mbox_current
=
((
volatile
unsigned
int
*
)
DAQ_MBOX
)[
0
];
//this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD)
if
((
mbox_current
>=
120
)
&&
(
mbox_target
<
30
))
//handle the frame wrap-arround
diff2
=
150
-
mbox_current
+
mbox_target
;
else
if
((
mbox_current
<
30
)
&&
(
mbox_target
>=
120
))
diff2
=
-
150
+
mbox_target
-
mbox_current
;
else
diff2
=
mbox_target
-
mbox_current
;
if
(
diff2
<
(
-
7
))
{
LOG_D
(
HW
,
"UE Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)
\n
"
,
frame
,
slot
,
hw_slot
,
diff2
);
if
(
frame
>
0
)
{
if
(
exit_missed_slots
==
1
)
exit_fun
(
"[HW][UE] missed slot"
);
else
{
num_missed_slots
++
;
LOG_W
(
HW
,
"[UE] just missed slot (total missed slots %ld)
\n
"
,
num_missed_slots
);
}
}
slot
++
;
if
(
slot
==
20
)
{
slot
=
0
;
frame
++
;
}
// update thread slot/frame counters because of skipped slot
UE
->
slot_rx
++
;
UE
->
slot_tx
++
;
if
(
UE
->
slot_rx
==
20
)
{
UE
->
slot_rx
=
0
;
UE
->
frame_rx
++
;
}
if
(
UE
->
slot_tx
==
20
)
{
UE
->
slot_tx
=
0
;
UE
->
frame_tx
++
;
}
continue
;
}
if
(
diff2
>
8
)
LOG_D
(
HW
,
"UE Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)
\n
"
,
frame
,
slot
,
hw_slot
,
mbox_current
,
mbox_target
,
diff2
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX
,
*
DAQ_MBOX
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DIFF
,
diff2
);
// This loop implements the delay of 1 slot to allow for processing
delay_cnt
=
0
;
while
((
diff2
>
0
)
&&
(
!
oai_exit
)
)
{
time_in
=
rt_get_time_ns
();
//LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d (%d), diff %d, time %llu\n",frame,delay_cnt,hw_slot,((volatile unsigned int *)DAQ_MBOX)[0],slot,mbox_target,diff2,time_in);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX
,
*
DAQ_MBOX
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP
,
1
);
ret
=
rt_sleep_ns
(
diff2
*
DAQ_PERIOD
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP
,
0
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX
,
*
DAQ_MBOX
);
if
(
ret
)
LOG_D
(
HW
,
"eNB Frame %d, time %llu: rt_sleep_ns returned %d
\n
"
,
frame
,
time_in
);
hw_slot
=
(((((
volatile
unsigned
int
*
)
DAQ_MBOX
)[
0
]
+
1
)
%
150
)
<<
1
)
/
15
;
//LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns());
delay_cnt
++
;
if
(
delay_cnt
==
30
)
{
LOG_D
(
HW
,
"UE frame %d: HW stopped ...
\n
"
,
frame
);
exit_fun
(
"[HW][UE] HW stopped"
);
}
mbox_current
=
((
volatile
unsigned
int
*
)
DAQ_MBOX
)[
0
];
if
((
mbox_current
>=
135
)
&&
(
mbox_target
<
15
))
//handle the frame wrap-arround
diff2
=
150
-
mbox_current
+
mbox_target
;
else
if
((
mbox_current
<
15
)
&&
(
mbox_target
>=
135
))
diff2
=
-
150
+
mbox_target
-
mbox_current
;
else
diff2
=
mbox_target
-
mbox_current
;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX
,
*
DAQ_MBOX
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DIFF
,
diff2
);
}
// on even slots, schedule processing of entire subframe
if
((
slot
&
1
)
==
0
)
{
if
(
pthread_mutex_lock
(
&
UE
->
mutex_rx
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][UE] error locking mutex for UE RX thread
\n
"
);
exit_fun
(
"nothing to add"
);
}
else
{
int
instance_cnt_rx
=
++
UE
->
instance_cnt_rx
;
pthread_mutex_unlock
(
&
UE
->
mutex_rx
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX
,
instance_cnt_rx
);
if
(
instance_cnt_rx
==
0
)
{
LOG_D
(
HW
,
"Scheduling UE RX for frame %d (hw frame %d), subframe %d (%d), mode %d
\n
"
,
UE
->
frame_rx
,
frame
,
slot
>>
1
,
UE
->
slot_rx
>>
1
,
UE
->
mode
);
if
(
pthread_cond_signal
(
&
UE
->
cond_rx
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][UE] ERROR pthread_cond_signal for UE RX thread
\n
"
);
exit_fun
(
"nothing to add"
);
}
else
{
// printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
}
if
(
UE
->
mode
==
rx_calib_ue
)
{
if
(
frame
==
10
)
{
LOG_D
(
PHY
,
"[SCHED][UE] Found cell with N_RB_DL %d, PHICH CONFIG (%d,%d), Nid_cell %d, NB_ANTENNAS_TX %d, initial frequency offset %d Hz, frequency offset %d Hz, RSSI (digital) %d dB, measured Gain %d dB, total_rx_gain %d dB, USRP rx gain %f dB
\n
"
,
UE
->
lte_frame_parms
.
N_RB_DL
,
UE
->
lte_frame_parms
.
phich_config_common
.
phich_duration
,
UE
->
lte_frame_parms
.
phich_config_common
.
phich_resource
,
UE
->
lte_frame_parms
.
Nid_cell
,
UE
->
lte_frame_parms
.
nb_antennas_tx_eNB
,
freq_offset
,
UE
->
lte_ue_common_vars
.
freq_offset
,
UE
->
PHY_measurements
.
rx_power_avg_dB
[
0
],
UE
->
PHY_measurements
.
rx_power_avg_dB
[
0
]
-
rx_input_level_dBm
,
UE
->
rx_total_gain_dB
,
openair0_cfg
[
0
].
rx_gain
[
0
]
);
exit_fun
(
"[HW][UE] UE in RX calibration mode, exiting"
);
}
}
}
else
{
LOG_E
(
PHY
,
"[SCHED][UE] UE RX thread busy!!
\n
"
);
exit_fun
(
"nothing to add"
);
}
}
if
(
pthread_mutex_lock
(
&
UE
->
mutex_tx
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][UE] error locking mutex for UE TX thread
\n
"
);
exit_fun
(
"nothing to add"
);
}
else
{
int
instance_cnt_tx
=
++
UE
->
instance_cnt_tx
;
pthread_mutex_unlock
(
&
UE
->
mutex_tx
);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX
,
instance_cnt_tx
);
if
(
instance_cnt_tx
==
0
)
{
LOG_D
(
HW
,
"Scheduling UE TX for frame %d (hw frame %d), subframe %d (%d), mode %d
\n
"
,
UE
->
frame_tx
,
frame
,
slot
>>
1
,
UE
->
slot_tx
>>
1
,
UE
->
mode
);
if
(
pthread_cond_signal
(
&
UE
->
cond_tx
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][UE] ERROR pthread_cond_signal for UE TX thread
\n
"
);
exit_fun
(
"nothing to add"
);
}
else
{
// printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
}
}
else
{
LOG_E
(
PHY
,
"[SCHED][UE] UE TX thread busy!!
\n
"
);
exit_fun
(
"nothing to add"
);
}
}
}
/*
if ((slot%2000)<10)
LOG_D(HW,"fun0: doing very hard work\n");
*/
// now increment slot and frame counters
slot
++
;
if
(
slot
==
20
)
{
slot
=
0
;
frame
++
;
}
}
else
if
(
UE
->
is_synchronized
==
0
)
{
// we are not yet synchronized
//hw_slot_offset = 0;
first_synch
=
1
;
slot
=
0
;
// wait until we can lock mutex_synch
//printf("Locking mutex_synch (UE_thread)\n");
if
(
pthread_mutex_lock
(
&
UE
->
mutex_synch
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][UE] error locking mutex for UE initial synch thread
\n
"
);
exit_fun
(
"noting to add"
);
}
else
{
if
(
UE
->
instance_cnt_synch
<
0
)
{
wait_sync_cnt
=
0
;
openair0_config
(
&
openair0_cfg
[
0
],
1
);
// openair0_set_gains(&openair0,&openair0_cfg[0]);
printf
(
"Getting frame
\n
"
);
openair0_get_frame
(
0
);
rt_sleep_ns
(
FRAME_PERIOD
);
// increment instance count for sync thread
UE
->
instance_cnt_synch
++
;
pthread_mutex_unlock
(
&
UE
->
mutex_synch
);
if
(
pthread_cond_signal
(
&
UE
->
cond_synch
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][UE] ERROR pthread_cond_signal for UE sync thread
\n
"
);
exit_fun
(
"nothing to add"
);
}
}
else
{
wait_sync_cnt
++
;
pthread_mutex_unlock
(
&
UE
->
mutex_synch
);
if
(
wait_sync_cnt
>
1000
)
exit_fun
(
"waiting to long for synch thread"
);
else
rt_sleep_ns
(
FRAME_PERIOD
);
}
}
/*
if (initial_sync(UE,mode)==0) {
if (mode == rx_calib_ue) {
exit_fun("[HW][UE] UE in RX calibration mode");
}
else {
is_synchronized = 1;
//start the streaming DMA transfers
for (card=0;card<openair0_num_detected_cards;card++)
openair0_start_rt_acquisition(card);
hw_slot_offset = (UE->rx_offset<<1) / UE->lte_frame_parms.samples_per_tti;
}
}
else {
if (freq_offset >= 0) {
freq_offset += 100;
freq_offset *= -1;
}
else {
freq_offset *= -1;
}
if (abs(freq_offset) > 7500) {
LOG_I(PHY,"[initial_sync] No cell synchronization found, abondoning\n");
mac_xface->macphy_exit("No cell synchronization found, abondoning");
}
else {
// LOG_I(PHY,"[initial_sync] trying carrier off %d Hz\n",freq_offset);
#ifndef USRP
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
for (i=0; i<openair0_cfg[rf_map[CC_id].card].rx_num_channels; i++)
openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+freq_offset;
for (i=0; i<openair0_cfg[rf_map[CC_id].card].tx_num_channels; i++)
openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+freq_offset;
}
openair0_config(&openair0_cfg[0],UE_flag);
#endif
rt_sleep_ns(FRAME_PERIOD);
}
}
*/
}
}
LOG_D
(
HW
,
"UE_thread: finished, ran %d times.
\n
"
,
frame
);
#ifdef HARD_RT
rt_make_soft_real_time
();
#endif
// clean task
#ifdef RTAI
rt_task_delete
(
task
);
#endif
LOG_D
(
HW
,
"Task deleted. returning
\n
"
);
return
0
;
}
#else // This is for USRP or ETHERNET targets
#endif
/*!
...
...
@@ -2008,6 +1548,14 @@ void init_UE_threads(void)
{
PHY_VARS_UE
*
UE
=
PHY_vars_UE_g
[
0
][
0
];
pthread_attr_init
(
&
attr_UE_thread
);
pthread_attr_setstacksize
(
&
attr_UE_thread
,
8192
);
//5*PTHREAD_STACK_MIN);
#ifndef LOWLATENCY
sched_param_UE_thread
.
sched_priority
=
sched_get_priority_max
(
SCHED_FIFO
);
pthread_attr_setschedparam
(
&
attr_UE_thread
,
&
sched_param_UE_thread
);
#endif
// the threads are not yet active, therefore access is allowed without locking
UE
->
instance_cnt_tx
=
-
1
;
UE
->
instance_cnt_rx
=
-
1
;
...
...
@@ -2063,97 +1611,50 @@ void fill_ue_band_info(void)
int
setup_ue_buffers
(
PHY_VARS_UE
**
phy_vars_ue
,
openair0_config_t
*
openair0_cfg
,
openair0_rf_map
rf_map
[
MAX_NUM_CCs
])
{
//#ifndef EXMIMO
// uint16_t N_TA_offset = 0;
//#endif
int
i
,
CC_id
;
LTE_DL_FRAME_PARMS
*
frame_parms
;
for
(
CC_id
=
0
;
CC_id
<
MAX_NUM_CCs
;
CC_id
++
)
{
if
(
phy_vars_ue
[
CC_id
])
{
frame_parms
=
&
(
phy_vars_ue
[
CC_id
]
->
lte_frame_parms
);
}
else
{
printf
(
"phy_vars_UE[%d] not initialized
\n
"
,
CC_id
);
return
(
-
1
);
}
//#ifndef EXMIMO
// if (frame_parms->frame_type == TDD) {
// if (frame_parms->N_RB_DL == 100)
// N_TA_offset = 624;
// else if (frame_parms->N_RB_DL == 50)
// N_TA_offset = 624/2;
// else if (frame_parms->N_RB_DL == 25)
// N_TA_offset = 624/4;
// }
//#endif
#ifdef EXMIMO
openair0_cfg
[
CC_id
].
tx_num_channels
=
0
;
openair0_cfg
[
CC_id
].
rx_num_channels
=
0
;
// replace RX signal buffers with mmaped HW versions
for
(
i
=
0
;
i
<
frame_parms
->
nb_antennas_rx
;
i
++
)
{
printf
(
"Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d
\n
"
,
CC_id
,
i
,
downlink_frequency
[
CC_id
][
i
],
rf_map
[
CC_id
].
card
,
rf_map
[
CC_id
].
chain
+
i
);
free
(
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]);
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]
=
(
int32_t
*
)
openair0_exmimo_pci
[
rf_map
[
CC_id
].
card
].
adc_head
[
rf_map
[
CC_id
].
chain
+
i
];
if
(
openair0_cfg
[
rf_map
[
CC_id
].
card
].
rx_freq
[
rf_map
[
CC_id
].
chain
+
i
])
{
printf
(
"Error with rf_map! A channel has already been allocated!
\n
"
);
return
(
-
1
);
}
else
{
openair0_cfg
[
rf_map
[
CC_id
].
card
].
rx_freq
[
rf_map
[
CC_id
].
chain
+
i
]
=
downlink_frequency
[
CC_id
][
i
];
openair0_cfg
[
rf_map
[
CC_id
].
card
].
rx_gain
[
rf_map
[
CC_id
].
chain
+
i
]
=
rx_gain
[
CC_id
][
i
];
openair0_cfg
[
rf_map
[
CC_id
].
card
].
rxg_mode
[
rf_map
[
CC_id
].
chain
+
i
]
=
rx_gain_mode
[
CC_id
][
i
];
openair0_cfg
[
rf_map
[
CC_id
].
card
].
rx_num_channels
++
;
}
printf
(
"rxdata[%d] @ %p
\n
"
,
i
,
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]);
}
for
(
i
=
0
;
i
<
frame_parms
->
nb_antennas_tx
;
i
++
)
{
printf
(
"Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d
\n
"
,
CC_id
,
i
,
downlink_frequency
[
CC_id
][
i
],
rf_map
[
CC_id
].
card
,
rf_map
[
CC_id
].
chain
+
i
);
free
(
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]);
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]
=
(
int32_t
*
)
openair0_exmimo_pci
[
rf_map
[
CC_id
].
card
].
dac_head
[
rf_map
[
CC_id
].
chain
+
i
];
if
(
phy_vars_ue
[
CC_id
])
{
frame_parms
=
&
(
phy_vars_ue
[
CC_id
]
->
lte_frame_parms
);
}
else
{
printf
(
"phy_vars_UE[%d] not initialized
\n
"
,
CC_id
);
return
(
-
1
);
}
if
(
openair0_cfg
[
rf_map
[
CC_id
].
card
].
tx_freq
[
rf_map
[
CC_id
].
chain
+
i
])
{
printf
(
"Error with rf_map! A channel has already been allocated!
\n
"
);
return
(
-
1
);
}
else
{
openair0_cfg
[
rf_map
[
CC_id
].
card
].
tx_freq
[
rf_map
[
CC_id
].
chain
+
i
]
=
downlink_frequency
[
CC_id
][
i
]
+
uplink_frequency_offset
[
CC_id
][
i
];
openair0_cfg
[
rf_map
[
CC_id
].
card
].
tx_gain
[
rf_map
[
CC_id
].
chain
+
i
]
=
tx_gain
[
CC_id
][
i
];
openair0_cfg
[
rf_map
[
CC_id
].
card
].
tx_num_channels
++
;
}
printf
(
"txdata[%d] @ %p
\n
"
,
i
,
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]);
}
if
(
frame_parms
->
frame_type
==
TDD
)
{
if
(
frame_parms
->
N_RB_DL
==
100
)
N_TA_offset
=
624
;
else
if
(
frame_parms
->
N_RB_DL
==
50
)
N_TA_offset
=
624
/
2
;
else
if
(
frame_parms
->
N_RB_DL
==
25
)
N_TA_offset
=
624
/
4
;
}
#else
// replace RX signal buffers with mmaped HW versions
rxdata
=
(
int32_t
**
)
malloc16
(
frame_parms
->
nb_antennas_rx
*
sizeof
(
int32_t
*
)
);
txdata
=
(
int32_t
**
)
malloc16
(
frame_parms
->
nb_antennas_tx
*
sizeof
(
int32_t
*
)
);
for
(
i
=
0
;
i
<
frame_parms
->
nb_antennas_rx
;
i
++
)
{
printf
(
"Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d
\n
"
,
CC_id
,
i
,
downlink_frequency
[
CC_id
][
i
],
rf_map
[
CC_id
].
card
,
rf_map
[
CC_id
].
chain
+
i
);
free
(
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]
);
rxdata
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
307200
*
sizeof
(
int32_t
)
);
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]
=
rxdata
[
i
];
// what about the "-N_TA_offset" ? // N_TA offset for TDD
}
for
(
i
=
0
;
i
<
frame_parms
->
nb_antennas_tx
;
i
++
)
{
printf
(
"Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d
\n
"
,
CC_id
,
i
,
downlink_frequency
[
CC_id
][
i
],
rf_map
[
CC_id
].
card
,
rf_map
[
CC_id
].
chain
+
i
);
free
(
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]
);
txdata
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
307200
*
sizeof
(
int32_t
)
);
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]
=
txdata
[
i
];
}
// rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[x]
// txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[x]
// be careful when releasing memory!
// because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
#endif
rxdata
=
(
int32_t
**
)
malloc16
(
frame_parms
->
nb_antennas_rx
*
sizeof
(
int32_t
*
)
);
txdata
=
(
int32_t
**
)
malloc16
(
frame_parms
->
nb_antennas_tx
*
sizeof
(
int32_t
*
)
);
for
(
i
=
0
;
i
<
frame_parms
->
nb_antennas_rx
;
i
++
)
{
printf
(
"Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d
\n
"
,
CC_id
,
i
,
downlink_frequency
[
CC_id
][
i
],
rf_map
[
CC_id
].
card
,
rf_map
[
CC_id
].
chain
+
i
);
free
(
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]
);
rxdata
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
307200
*
sizeof
(
int32_t
)
);
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
rxdata
[
i
]
=
rxdata
[
i
];
// what about the "-N_TA_offset" ? // N_TA offset for TDD
}
for
(
i
=
0
;
i
<
frame_parms
->
nb_antennas_tx
;
i
++
)
{
printf
(
"Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d
\n
"
,
CC_id
,
i
,
downlink_frequency
[
CC_id
][
i
],
rf_map
[
CC_id
].
card
,
rf_map
[
CC_id
].
chain
+
i
);
free
(
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]
);
txdata
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
307200
*
sizeof
(
int32_t
)
);
phy_vars_ue
[
CC_id
]
->
lte_ue_common_vars
.
txdata
[
i
]
=
txdata
[
i
];
}
// rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[x]
// txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[x]
// be careful when releasing memory!
// because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
}
...
...
targets/RT/USER/sched_dlsch.c
deleted
100644 → 0
View file @
58ba0089
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file sched_dlsch.c
* \brief DLSCH decoding thread (RTAI)
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include "rt_wrapper.h"
#include <sys/mman.h>
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#define DEBUG_PHY
/// Mutex for instance count on dlsch scheduling
pthread_mutex_t
dlsch_mutex
[
8
];
/// Condition variable for dlsch thread
pthread_cond_t
dlsch_cond
[
8
];
pthread_t
dlsch_threads
[
8
];
pthread_attr_t
attr_dlsch_threads
;
unsigned
char
dlsch_thread_indices
[
8
];
// activity indicators for harq_pid's
int
dlsch_instance_cnt
[
8
];
// process ids for cpu
int
dlsch_cpuid
[
8
];
// subframe number for each harq_pid (needed to store ack in right place for UL)
int
dlsch_subframe
[
8
];
extern
int
oai_exit
;
/*
extern int dlsch_errors;
extern int dlsch_received;
extern int dlsch_errors_last;
extern int dlsch_received_last;
extern int dlsch_fer;
extern int current_dlsch_cqi;
*/
/** DLSCH Decoding Thread */
static
void
*
dlsch_thread
(
void
*
param
)
{
//unsigned long cpuid;
unsigned
char
dlsch_thread_index
=
*
((
unsigned
char
*
)
param
);
unsigned
int
ret
=
0
;
uint8_t
harq_pid
;
#ifdef RTAI
RT_TASK
*
task
;
char
task_name
[
8
];
#endif
int
eNB_id
=
0
,
UE_id
=
0
,
CC_id
=
0
;
PHY_VARS_UE
*
phy_vars_ue
=
PHY_vars_UE_g
[
UE_id
][
CC_id
];
if
((
dlsch_thread_index
<
0
)
||
(
dlsch_thread_index
>
7
))
{
LOG_E
(
PHY
,
"[SCHED][DLSCH] Illegal dlsch_thread_index %d (%p)!!!!
\n
"
,
dlsch_thread_index
,
param
);
return
0
;
}
#ifdef RTAI
sprintf
(
task_name
,
"DLSCH%d"
,
dlsch_thread_index
);
task
=
rt_task_init_schmod
(
nam2num
(
task_name
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][DLSCH] Problem starting dlsch_thread_index %d (%s)!!!!
\n
"
,
dlsch_thread_index
,
task_name
);
return
0
;
}
else
{
LOG_I
(
PHY
,
"[SCHED][DLSCH] dlsch_thread for process %d started with id %p
\n
"
,
dlsch_thread_index
,
task
);
}
#endif
mlockall
(
MCL_CURRENT
|
MCL_FUTURE
);
//rt_set_runnable_on_cpuid(task,1);
//cpuid = rtai_cpuid();
#ifdef HARD_RT
rt_make_hard_real_time
();
#endif
//dlsch_cpuid[dlsch_thread_index] = cpuid;
while
(
!
oai_exit
)
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD0
+
dlsch_thread_index
,
0
);
if
(
pthread_mutex_lock
(
&
dlsch_mutex
[
dlsch_thread_index
])
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][DLSCH] error locking mutex.
\n
"
);
}
else
{
while
(
dlsch_instance_cnt
[
dlsch_thread_index
]
<
0
)
{
pthread_cond_wait
(
&
dlsch_cond
[
dlsch_thread_index
],
&
dlsch_mutex
[
dlsch_thread_index
]);
}
if
(
pthread_mutex_unlock
(
&
dlsch_mutex
[
dlsch_thread_index
])
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][DLSCH] error unlocking mutex.
\n
"
);
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD0
+
dlsch_thread_index
,
1
);
if
(
oai_exit
)
break
;
LOG_I
(
PHY
,
"[SCHED][DLSCH] Frame %d: Calling dlsch_decoding with dlsch_thread_index = %d
\n
"
,
phy_vars_ue
->
frame_rx
,
dlsch_thread_index
);
if
(
phy_vars_ue
->
frame_rx
<
phy_vars_ue
->
dlsch_errors
[
eNB_id
])
{
phy_vars_ue
->
dlsch_errors
[
eNB_id
]
=
0
;
phy_vars_ue
->
dlsch_received
[
eNB_id
]
=
0
;
}
harq_pid
=
dlsch_thread_index
;
if
(
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
])
{
// rt_printk("[SCHED][DLSCH] Frame %d, slot %d, start %llu, end %llu, proc time: %llu ns\n",phy_vars_ue->frame,last_slot,time0,time1,(time1-time0));
dlsch_unscrambling
(
&
phy_vars_ue
->
lte_frame_parms
,
0
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
],
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
G
,
phy_vars_ue
->
lte_ue_pdsch_vars
[
eNB_id
]
->
llr
[
0
],
0
,
dlsch_subframe
[
dlsch_thread_index
]
<<
1
);
LOG_I
(
PHY
,
"[UE %d] PDSCH Calling dlsch_decoding for subframe %d, harq_pid %d, G%d
\n
"
,
phy_vars_ue
->
Mod_id
,
dlsch_subframe
[
dlsch_thread_index
],
harq_pid
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
G
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0
+
dlsch_thread_index
,
1
);
ret
=
dlsch_decoding
(
phy_vars_ue
,
phy_vars_ue
->
lte_ue_pdsch_vars
[
eNB_id
]
->
llr
[
0
],
&
phy_vars_ue
->
lte_frame_parms
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
],
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
],
dlsch_subframe
[
dlsch_thread_index
],
harq_pid
,
1
,
// is_crnti
0
);
// llr8_flag
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0
+
dlsch_thread_index
,
0
);
LOG_D
(
PHY
,
"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)
\n
"
,
phy_vars_ue
->
Mod_id
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
rnti
,
harq_pid
,
phy_vars_ue
->
frame_rx
,
dlsch_subframe
[
dlsch_thread_index
],
ret
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
mcs
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
rvidx
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
TBS
);
if
(
ret
==
(
1
+
MAX_TURBO_ITERATIONS
))
{
phy_vars_ue
->
dlsch_errors
[
eNB_id
]
++
;
#ifdef DEBUG_PHY
LOG_I
(
PHY
,
"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d)
\n
"
,
phy_vars_ue
->
Mod_id
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
rnti
,
harq_pid
,
phy_vars_ue
->
frame_rx
,
dlsch_subframe
[
dlsch_thread_index
],
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
rvidx
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
mcs
);
#endif
}
else
{
LOG_I
(
PHY
,
"[UE %d][PDSCH %x/%d] Frame %d subframe %d: Received DLSCH (rv %d,mcs %d)
\n
"
,
phy_vars_ue
->
Mod_id
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
rnti
,
harq_pid
,
phy_vars_ue
->
frame_rx
,
dlsch_subframe
[
dlsch_thread_index
],
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
rvidx
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
mcs
);
#ifdef OPENAIR2
mac_xface
->
ue_send_sdu
(
phy_vars_ue
->
Mod_id
,
0
,
// CC_id
phy_vars_ue
->
frame_rx
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
b
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
TBS
>>
3
,
eNB_id
);
#endif
phy_vars_ue
->
total_TBS
[
eNB_id
]
=
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
TBS
+
phy_vars_ue
->
total_TBS
[
eNB_id
];
phy_vars_ue
->
total_received_bits
[
eNB_id
]
=
phy_vars_ue
->
total_received_bits
[
eNB_id
]
+
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
TBS
;
}
}
// this is done in main thread
/*
if (phy_vars_ue->frame % 100 == 0) {
if ((phy_vars_ue->dlsch_received[eNB_id] - phy_vars_ue->dlsch_received_last[eNB_id]) != 0)
phy_vars_ue->dlsch_fer[eNB_id] = (100*(phy_vars_ue->dlsch_errors[eNB_id] - phy_vars_ue->dlsch_errors_last[eNB_id]))/(phy_vars_ue->dlsch_received[eNB_id] - phy_vars_ue->dlsch_received_last[eNB_id]);
phy_vars_ue->dlsch_errors_last[eNB_id] = phy_vars_ue->dlsch_errors[eNB_id];
phy_vars_ue->dlsch_received_last[eNB_id] = phy_vars_ue->dlsch_received[eNB_id];
}
*/
#ifdef DEBUG_PHY
if
(
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
])
{
LOG_I
(
PHY
,
"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)
\n
"
,
phy_vars_ue
->
Mod_id
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
rnti
,
harq_pid
,
phy_vars_ue
->
frame_rx
,
dlsch_subframe
[
dlsch_thread_index
],
ret
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
mcs
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
rvidx
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
TBS
);
if
(
phy_vars_ue
->
frame_rx
%
100
==
0
)
{
LOG_D
(
PHY
,
"[UE %d][PDSCH %x] Frame %d subframe %d dlsch_errors %d, dlsch_received %d, dlsch_fer %d, current_dlsch_cqi %d
\n
"
,
phy_vars_ue
->
Mod_id
,
phy_vars_ue
->
dlsch_ue
[
eNB_id
][
0
]
->
rnti
,
phy_vars_ue
->
frame_rx
,
dlsch_subframe
[
dlsch_thread_index
],
phy_vars_ue
->
dlsch_errors
[
eNB_id
],
phy_vars_ue
->
dlsch_received
[
eNB_id
],
phy_vars_ue
->
dlsch_fer
[
eNB_id
],
phy_vars_ue
->
PHY_measurements
.
wideband_cqi_tot
[
eNB_id
]);
}
}
else
{
LOG_I
(
PHY
,
"[UE %d][PDSCH ?/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (phy_vars_ue->dlsch_ue[eNB_id][0] == 0)
\n
"
,
phy_vars_ue
->
Mod_id
,
harq_pid
,
phy_vars_ue
->
frame_rx
,
dlsch_subframe
[
dlsch_thread_index
],
ret
);
}
#endif
if
(
pthread_mutex_lock
(
&
dlsch_mutex
[
dlsch_thread_index
])
!=
0
)
{
msg
(
"[openair][SCHED][DLSCH] error locking mutex.
\n
"
);
}
else
{
dlsch_instance_cnt
[
dlsch_thread_index
]
--
;
if
(
pthread_mutex_unlock
(
&
dlsch_mutex
[
dlsch_thread_index
])
!=
0
)
{
msg
(
"[openair][SCHED][DLSCH] error unlocking mutex.
\n
"
);
}
}
}
#ifdef HARD_RT
rt_make_soft_real_time
();
#endif
msg
(
"[openair][SCHED][DLSCH] DLSCH thread %d exiting
\n
"
,
dlsch_thread_index
);
return
0
;
}
int
init_dlsch_threads
(
void
)
{
int
error_code
;
struct
sched_param
p
;
unsigned
char
dlsch_thread_index
;
pthread_attr_init
(
&
attr_dlsch_threads
);
pthread_attr_setstacksize
(
&
attr_dlsch_threads
,
OPENAIR_THREAD_STACK_SIZE
);
//attr_dlsch_threads.priority = 1;
p
.
sched_priority
=
OPENAIR_THREAD_PRIORITY
;
pthread_attr_setschedparam
(
&
attr_dlsch_threads
,
&
p
);
#ifndef RTAI_ISNT_POSIX
pthread_attr_setschedpolicy
(
&
attr_dlsch_threads
,
SCHED_FIFO
);
#endif
for
(
dlsch_thread_index
=
0
;
dlsch_thread_index
<
8
;
dlsch_thread_index
++
)
{
pthread_mutex_init
(
&
dlsch_mutex
[
dlsch_thread_index
],
NULL
);
pthread_cond_init
(
&
dlsch_cond
[
dlsch_thread_index
],
NULL
);
dlsch_instance_cnt
[
dlsch_thread_index
]
=
-
1
;
dlsch_thread_indices
[
dlsch_thread_index
]
=
dlsch_thread_index
;
rt_printk
(
"[openair][SCHED][DLSCH][INIT] Allocating DLSCH thread for dlsch_thread_index %d (%p)
\n
"
,
dlsch_thread_index
,
&
dlsch_thread_indices
[
dlsch_thread_index
]);
error_code
=
pthread_create
(
&
dlsch_threads
[
dlsch_thread_index
],
&
attr_dlsch_threads
,
dlsch_thread
,
(
void
*
)
&
dlsch_thread_indices
[
dlsch_thread_index
]);
if
(
error_code
!=
0
)
{
rt_printk
(
"[openair][SCHED][DLSCH][INIT] Could not allocate dlsch_thread %d, error %d
\n
"
,
dlsch_thread_index
,
error_code
);
return
(
error_code
);
}
else
{
rt_printk
(
"[openair][SCHED][DLSCH][INIT] Allocate dlsch_thread %d successful
\n
"
,
dlsch_thread_index
);
}
}
return
(
0
);
}
void
cleanup_dlsch_threads
(
void
)
{
unsigned
char
dlsch_thread_index
;
for
(
dlsch_thread_index
=
0
;
dlsch_thread_index
<
8
;
dlsch_thread_index
++
)
{
// pthread_exit(&dlsch_threads[dlsch_thread_index]);
rt_printk
(
"[openair][SCHED][DLSCH] Scheduling dlsch_thread %d to exit
\n
"
,
dlsch_thread_index
);
dlsch_instance_cnt
[
dlsch_thread_index
]
=
0
;
if
(
pthread_cond_signal
(
&
dlsch_cond
[
dlsch_thread_index
])
!=
0
)
rt_printk
(
"[openair][SCHED][DLSCH] ERROR pthread_cond_signal
\n
"
);
else
rt_printk
(
"[openair][SCHED][DLSCH] Signalled dlsch_thread %d to exit
\n
"
,
dlsch_thread_index
);
rt_printk
(
"[openair][SCHED][DLSCH] Exiting ...
\n
"
);
pthread_cond_destroy
(
&
dlsch_cond
[
dlsch_thread_index
]);
pthread_mutex_destroy
(
&
dlsch_mutex
[
dlsch_thread_index
]);
}
}
targets/RT/USER/sched_rx_pdsch.c
deleted
100644 → 0
View file @
58ba0089
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file sched_dlsch.c
* \brief DLSCH decoding thread (RTAI)
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include "rt_wrapper.h"
#include <sys/mman.h>
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
RTIME
time0
,
time1
;
#define DEBUG_PHY
/// Mutex for instance count on rx_pdsch scheduling
pthread_mutex_t
rx_pdsch_mutex
;
/// Condition variable for rx_pdsch thread
pthread_cond_t
rx_pdsch_cond
;
pthread_t
rx_pdsch_thread_var
;
pthread_attr_t
attr_rx_pdsch_thread
;
// activity indicators for harq_pid's
int
rx_pdsch_instance_cnt
;
// process ids for cpu
int
rx_pdsch_cpuid
;
// subframe number for each harq_pid (needed to store ack in right place for UL)
int
rx_pdsch_slot
;
extern
int
oai_exit
;
extern
pthread_mutex_t
dlsch_mutex
[
8
];
extern
int
dlsch_instance_cnt
[
8
];
extern
int
dlsch_subframe
[
8
];
extern
pthread_cond_t
dlsch_cond
[
8
];
/** RX_PDSCH Decoding Thread */
static
void
*
rx_pdsch_thread
(
void
*
param
)
{
//unsigned long cpuid;
uint8_t
dlsch_thread_index
=
0
;
uint8_t
pilot2
,
harq_pid
,
subframe
;
// uint8_t last_slot;
uint8_t
dual_stream_UE
=
0
;
uint8_t
i_mod
=
0
;
#ifdef RTAI
RT_TASK
*
task
;
#endif
int
m
,
eNB_id
=
0
;
int
eNB_id_i
=
1
;
PHY_VARS_UE
*
UE
=
PHY_vars_UE_g
[
0
][
0
];
#ifdef RTAI
task
=
rt_task_init_schmod
(
nam2num
(
"RX_PDSCH_THREAD"
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][RX_PDSCH] Problem starting rx_pdsch thread!!!!
\n
"
);
return
0
;
}
else
{
LOG_I
(
PHY
,
"[SCHED][RX_PDSCH] rx_pdsch_thread started for with id %p
\n
"
,
task
);
}
#endif
mlockall
(
MCL_CURRENT
|
MCL_FUTURE
);
//rt_set_runnable_on_cpuid(task,1);
//cpuid = rtai_cpuid();
#ifdef HARD_RT
rt_make_hard_real_time
();
#endif
if
(
UE
->
lte_frame_parms
.
Ncp
==
NORMAL
)
{
// normal prefix
pilot2
=
7
;
}
else
{
// extended prefix
pilot2
=
6
;
}
while
(
!
oai_exit
)
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD
,
0
);
if
(
pthread_mutex_lock
(
&
rx_pdsch_mutex
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][RX_PDSCH] error locking mutex.
\n
"
);
}
else
{
while
(
rx_pdsch_instance_cnt
<
0
)
{
pthread_cond_wait
(
&
rx_pdsch_cond
,
&
rx_pdsch_mutex
);
}
if
(
pthread_mutex_unlock
(
&
rx_pdsch_mutex
)
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][RX_PDSCH] error unlocking mutex.
\n
"
);
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD
,
1
);
// last_slot = rx_pdsch_slot;
subframe
=
UE
->
slot_rx
>>
1
;
// Important! assumption that PDCCH procedure of next SF is not called yet
harq_pid
=
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
current_harq_pid
;
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
G
=
get_G
(
&
UE
->
lte_frame_parms
,
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
nb_rb
,
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
rb_alloc_even
,
get_Qm
(
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
mcs
),
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
Nl
,
UE
->
lte_ue_pdcch_vars
[
eNB_id
]
->
num_pdcch_symbols
,
UE
->
frame_rx
,
subframe
);
if
((
UE
->
transmission_mode
[
eNB_id
]
==
5
)
&&
(
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
dl_power_off
==
0
)
&&
(
openair_daq_vars
.
use_ia_receiver
>
0
))
{
dual_stream_UE
=
1
;
eNB_id_i
=
UE
->
n_connected_eNB
;
if
(
openair_daq_vars
.
use_ia_receiver
==
2
)
{
i_mod
=
get_Qm
(((
UE
->
frame_rx
%
1024
)
/
3
)
%
28
);
}
else
{
i_mod
=
get_Qm
(
UE
->
dlsch_ue
[
eNB_id
][
0
]
->
harq_processes
[
harq_pid
]
->
mcs
);
}
}
else
{
dual_stream_UE
=
0
;
eNB_id_i
=
eNB_id
+
1
;
i_mod
=
0
;
}
if
(
oai_exit
)
break
;
LOG_D
(
PHY
,
"[SCHED][RX_PDSCH] Frame %d, slot %d: Calling rx_pdsch_decoding with harq_pid %d
\n
"
,
UE
->
frame_rx
,
UE
->
slot_rx
,
harq_pid
);
// Check if we are in even or odd slot
if
(
UE
->
slot_rx
%
2
)
{
// odd slots
// measure time
//time0 = rt_get_time_ns();
// rt_printk("[SCHED][RX_PDSCH][before rx_pdsch] Frame %d, slot %d, time %llu\n",UE->frame,last_slot,rt_get_time_ns());
for
(
m
=
pilot2
;
m
<
UE
->
lte_frame_parms
.
symbols_per_tti
;
m
++
)
{
rx_pdsch
(
UE
,
PDSCH
,
eNB_id
,
eNB_id_i
,
subframe
,
m
,
0
,
dual_stream_UE
,
i_mod
,
harq_pid
);
}
// time1 = rt_get_time_ns();
// rt_printk("[SCHED][RX_PDSCH] Frame %d, slot %d, start %llu, end %llu, proc time: %llu ns\n",UE->frame_rx,last_slot,time0,time1,(time1-time0));
dlsch_thread_index
=
harq_pid
;
if
(
pthread_mutex_lock
(
&
dlsch_mutex
[
dlsch_thread_index
])
!=
0
)
{
// Signal MAC_PHY Scheduler
LOG_E
(
PHY
,
"[UE %d] ERROR pthread_mutex_lock
\n
"
,
UE
->
Mod_id
);
// lock before accessing shared resource
// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
//return(-1);
}
dlsch_instance_cnt
[
dlsch_thread_index
]
++
;
dlsch_subframe
[
dlsch_thread_index
]
=
subframe
;
pthread_mutex_unlock
(
&
dlsch_mutex
[
dlsch_thread_index
]);
if
(
dlsch_instance_cnt
[
dlsch_thread_index
]
==
0
)
{
if
(
pthread_cond_signal
(
&
dlsch_cond
[
dlsch_thread_index
])
!=
0
)
{
LOG_E
(
PHY
,
"[UE %d] ERROR pthread_cond_signal for dlsch_cond[%d]
\n
"
,
UE
->
Mod_id
,
dlsch_thread_index
);
// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
//return(-1);
}
}
else
{
LOG_W
(
PHY
,
"[UE %d] DLSCH thread for dlsch_thread_index %d busy!!!
\n
"
,
UE
->
Mod_id
,
dlsch_thread_index
);
// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
//return(-1);
}
}
else
{
// even slots
for
(
m
=
UE
->
lte_ue_pdcch_vars
[
eNB_id
]
->
num_pdcch_symbols
;
m
<
pilot2
;
m
++
)
{
rx_pdsch
(
UE
,
PDSCH
,
eNB_id
,
eNB_id_i
,
subframe
,
m
,
(
m
==
UE
->
lte_ue_pdcch_vars
[
eNB_id
]
->
num_pdcch_symbols
)
?
1
:
0
,
// first_symbol_flag
dual_stream_UE
,
i_mod
,
harq_pid
);
}
}
if
(
pthread_mutex_lock
(
&
rx_pdsch_mutex
)
!=
0
)
{
msg
(
"[openair][SCHED][RX_PDSCH] error locking mutex.
\n
"
);
}
else
{
rx_pdsch_instance_cnt
--
;
if
(
pthread_mutex_unlock
(
&
rx_pdsch_mutex
)
!=
0
)
{
msg
(
"[openair][SCHED][RX_PDSCH] error unlocking mutex.
\n
"
);
}
}
}
#ifdef HARD_RT
rt_make_soft_real_time
();
#endif
LOG_D
(
PHY
,
"[openair][SCHED][RX_PDSCH] RX_PDSCH thread exiting
\n
"
);
return
0
;
}
int
init_rx_pdsch_thread
(
void
)
{
int
error_code
;
struct
sched_param
p
;
pthread_mutex_init
(
&
rx_pdsch_mutex
,
NULL
);
pthread_cond_init
(
&
rx_pdsch_cond
,
NULL
);
pthread_attr_init
(
&
attr_rx_pdsch_thread
);
pthread_attr_setstacksize
(
&
attr_rx_pdsch_thread
,
OPENAIR_THREAD_STACK_SIZE
);
//attr_rx_pdsch_thread.priority = 1;
p
.
sched_priority
=
OPENAIR_THREAD_PRIORITY
;
pthread_attr_setschedparam
(
&
attr_rx_pdsch_thread
,
&
p
);
#ifndef RTAI_ISNT_POSIX
pthread_attr_setschedpolicy
(
&
attr_rx_pdsch_thread
,
SCHED_FIFO
);
#endif
rx_pdsch_instance_cnt
=
-
1
;
rt_printk
(
"[openair][SCHED][RX_PDSCH][INIT] Allocating RX_PDSCH thread
\n
"
);
error_code
=
pthread_create
(
&
rx_pdsch_thread_var
,
&
attr_rx_pdsch_thread
,
rx_pdsch_thread
,
0
);
if
(
error_code
!=
0
)
{
rt_printk
(
"[openair][SCHED][RX_PDSCH][INIT] Could not allocate rx_pdsch_thread, error %d
\n
"
,
error_code
);
return
(
error_code
);
}
else
{
rt_printk
(
"[openair][SCHED][RX_PDSCH][INIT] Allocate rx_pdsch_thread successful
\n
"
);
return
(
0
);
}
}
void
cleanup_rx_pdsch_thread
(
void
)
{
rt_printk
(
"[openair][SCHED][RX_PDSCH] Scheduling rx_pdsch_thread to exit
\n
"
);
rx_pdsch_instance_cnt
=
0
;
if
(
pthread_cond_signal
(
&
rx_pdsch_cond
)
!=
0
)
rt_printk
(
"[openair][SCHED][RX_PDSCH] ERROR pthread_cond_signal
\n
"
);
else
rt_printk
(
"[openair][SCHED][RX_PDSCH] Signalled rx_pdsch_thread to exit
\n
"
);
rt_printk
(
"[openair][SCHED][RX_PDSCH] Exiting ...
\n
"
);
pthread_cond_destroy
(
&
rx_pdsch_cond
);
pthread_mutex_destroy
(
&
rx_pdsch_mutex
);
}
targets/RT/USER/sched_ulsch.c
deleted
100644 → 0
View file @
58ba0089
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file sched_ulsch.c
* \brief ULSCH decoding thread (RTAI)
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include "rt_wrapper.h"
#include <sys/mman.h>
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "MAC_INTERFACE/extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h"
#endif // CBMIMO1
#define DEBUG_PHY
/// Mutex for instance count on ulsch scheduling
pthread_mutex_t
ulsch_mutex
[
NUMBER_OF_UE_MAX
];
/// Condition variable for ulsch thread
pthread_cond_t
ulsch_cond
[
NUMBER_OF_UE_MAX
];
pthread_t
ulsch_threads
[
NUMBER_OF_UE_MAX
];
pthread_attr_t
attr_ulsch_threads
;
// activity indicators for harq_pid's
int
ulsch_instance_cnt
[
NUMBER_OF_UE_MAX
];
// process ids for cpu
int
ulsch_cpuid
[
NUMBER_OF_UE_MAX
];
// subframe number for each harq_pid (needed to store ack in right place for UL)
int
ulsch_subframe
[
NUMBER_OF_UE_MAX
];
extern
int
oai_exit
;
/*
extern int ulsch_errors;
extern int ulsch_received;
extern int ulsch_errors_last;
extern int ulsch_received_last;
extern int ulsch_fer;
extern int current_ulsch_cqi;
*/
/** ULSCH Decoding Thread */
static
void
*
ulsch_thread
(
void
*
param
)
{
//unsigned long cpuid;
unsigned
int
ulsch_thread_index
=
(
unsigned
int
)
param
;
RTIME
time_in
,
time_out
;
#ifdef RTAI
RT_TASK
*
task
;
char
ulsch_thread_name
[
64
];
#endif
int
eNB_id
=
0
,
UE_id
=
0
;
PHY_VARS_eNB
*
phy_vars_eNB
=
PHY_vars_eNB_g
[
eNB_id
];
if
((
ulsch_thread_index
<
0
)
||
(
ulsch_thread_index
>
NUMBER_OF_UE_MAX
))
{
LOG_E
(
PHY
,
"[SCHED][ULSCH] Illegal ulsch_thread_index %d!!!!
\n
"
,
ulsch_thread_index
);
return
0
;
}
#ifdef RTAI
sprintf
(
ulsch_thread_name
,
"ULSCH_THREAD%d"
,
ulsch_thread_index
);
LOG_I
(
PHY
,
"[SCHED][ULSCH] starting ulsch_thread %s for process %d
\n
"
,
ulsch_thread_name
,
ulsch_thread_index
);
task
=
rt_task_init_schmod
(
nam2num
(
ulsch_thread_name
),
0
,
0
,
0
,
SCHED_FIFO
,
0xF
);
if
(
task
==
NULL
)
{
LOG_E
(
PHY
,
"[SCHED][ULSCH] Problem starting ulsch_thread_index %d!!!!
\n
"
,
ulsch_thread_index
);
return
0
;
}
else
{
LOG_I
(
PHY
,
"[SCHED][ULSCH] ulsch_thread for process %d started with id %p
\n
"
,
ulsch_thread_index
,
task
);
}
#endif
mlockall
(
MCL_CURRENT
|
MCL_FUTURE
);
//rt_set_runnable_on_cpuid(task,1);
//cpuid = rtai_cpuid();
#ifdef HARD_RT
rt_make_hard_real_time
();
#endif
//ulsch_cpuid[ulsch_thread_index] = cpuid;
while
(
!
oai_exit
)
{
if
(
pthread_mutex_lock
(
&
ulsch_mutex
[
ulsch_thread_index
])
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][ULSCH] error locking mutex.
\n
"
);
}
else
{
while
(
ulsch_instance_cnt
[
ulsch_thread_index
]
<
0
)
{
pthread_cond_wait
(
&
ulsch_cond
[
ulsch_thread_index
],
&
ulsch_mutex
[
ulsch_thread_index
]);
}
if
(
pthread_mutex_unlock
(
&
ulsch_mutex
[
ulsch_thread_index
])
!=
0
)
{
LOG_E
(
PHY
,
"[SCHED][ULSCH] error unlocking mutex.
\n
"
);
}
}
if
(
oai_exit
)
break
;
LOG_D
(
PHY
,
"[SCHED][ULSCH] Frame %d: Calling ulsch_decoding with ulsch_thread_index = %d
\n
"
,
phy_vars_eNB
->
proc
[
0
].
frame_tx
,
ulsch_thread_index
);
time_in
=
rt_get_time_ns
();
ulsch_decoding_procedures
(
ulsch_subframe
[
ulsch_thread_index
]
<<
1
,
ulsch_thread_index
,
phy_vars_eNB
,
0
);
time_out
=
rt_get_time_ns
();
if
(
pthread_mutex_lock
(
&
ulsch_mutex
[
ulsch_thread_index
])
!=
0
)
{
msg
(
"[openair][SCHED][ULSCH] error locking mutex.
\n
"
);
}
else
{
ulsch_instance_cnt
[
ulsch_thread_index
]
--
;
if
(
pthread_mutex_unlock
(
&
ulsch_mutex
[
ulsch_thread_index
])
!=
0
)
{
msg
(
"[openair][SCHED][ULSCH] error unlocking mutex.
\n
"
);
}
}
}
#ifdef HARD_RT
rt_make_soft_real_time
();
#endif
msg
(
"[openair][SCHED][ULSCH] ULSCH thread %d exiting
\n
"
,
ulsch_thread_index
);
return
0
;
}
int
init_ulsch_threads
(
void
)
{
int
error_code
,
return_code
=
0
;
struct
sched_param
p
;
int
ulsch_thread_index
;
// later loop on all harq_pids, do 0 for now
for
(
ulsch_thread_index
=
0
;
ulsch_thread_index
<
NUMBER_OF_UE_MAX
;
ulsch_thread_index
++
)
{
pthread_mutex_init
(
&
ulsch_mutex
[
ulsch_thread_index
],
NULL
);
pthread_cond_init
(
&
ulsch_cond
[
ulsch_thread_index
],
NULL
);
pthread_attr_init
(
&
attr_ulsch_threads
);
pthread_attr_setstacksize
(
&
attr_ulsch_threads
,
OPENAIR_THREAD_STACK_SIZE
);
//attr_ulsch_threads.priority = 1;
p
.
sched_priority
=
OPENAIR_THREAD_PRIORITY
;
pthread_attr_setschedparam
(
&
attr_ulsch_threads
,
&
p
);
#ifndef RTAI_ISNT_POSIX
pthread_attr_setschedpolicy
(
&
attr_ulsch_threads
,
SCHED_FIFO
);
#endif
ulsch_instance_cnt
[
ulsch_thread_index
]
=
-
1
;
rt_printk
(
"[openair][SCHED][ULSCH][INIT] Allocating ULSCH thread for ulsch_thread_index %d
\n
"
,
ulsch_thread_index
);
error_code
=
pthread_create
(
&
ulsch_threads
[
ulsch_thread_index
],
&
attr_ulsch_threads
,
ulsch_thread
,
(
void
*
)
ulsch_thread_index
);
if
(
error_code
!=
0
)
{
rt_printk
(
"[openair][SCHED][ULSCH][INIT] Could not allocate ulsch_thread %d, error %d
\n
"
,
ulsch_thread_index
,
error_code
);
return_code
+=
error_code
;
//return(error_code);
}
else
{
rt_printk
(
"[openair][SCHED][ULSCH][INIT] Allocate ulsch_thread %d successful
\n
"
,
ulsch_thread_index
);
//return(0);
}
}
return
(
return_code
);
}
void
cleanup_ulsch_threads
(
void
)
{
int
ulsch_thread_index
;
for
(
ulsch_thread_index
=
0
;
ulsch_thread_index
<
NUMBER_OF_UE_MAX
;
ulsch_thread_index
++
)
{
// pthread_exit(&ulsch_threads[ulsch_thread_index]);
rt_printk
(
"[openair][SCHED][ULSCH] Scheduling ulsch_thread %d to exit
\n
"
,
ulsch_thread_index
);
ulsch_instance_cnt
[
ulsch_thread_index
]
=
0
;
if
(
pthread_cond_signal
(
&
ulsch_cond
[
ulsch_thread_index
])
!=
0
)
rt_printk
(
"[openair][SCHED][ULSCH] ERROR pthread_cond_signal
\n
"
);
else
rt_printk
(
"[openair][SCHED][ULSCH] Signalled ulsch_thread %d to exit
\n
"
,
ulsch_thread_index
);
rt_printk
(
"[openair][SCHED][ULSCH] Exiting ...
\n
"
);
pthread_cond_destroy
(
&
ulsch_cond
[
ulsch_thread_index
]);
pthread_mutex_destroy
(
&
ulsch_mutex
[
ulsch_thread_index
]);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment