@ -37,6 +37,8 @@
# include "srslte/phy/utils/debug.h"
# include "srslte/phy/utils/debug.h"
# include "srslte/radio/radio.h"
# include "srslte/radio/radio.h"
# include "srslte/common/test_common.h"
/********************************************************
/********************************************************
* Random Tester for Scheduler .
* Random Tester for Scheduler .
* Current Checks :
* Current Checks :
@ -77,8 +79,6 @@ float randf()
return unif_dist ( rand_gen ) ;
return unif_dist ( rand_gen ) ;
}
}
uint32_t err_counter = 0 ;
uint32_t warn_counter = 0 ;
struct ue_stats_t {
struct ue_stats_t {
uint64_t nof_dl_rbs = 0 ;
uint64_t nof_dl_rbs = 0 ;
uint64_t nof_ul_rbs = 0 ;
uint64_t nof_ul_rbs = 0 ;
@ -101,34 +101,25 @@ void erase_if(MapContainer& c, Predicate should_remove)
* Logging *
* Logging *
* * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * */
class log_tester : public srslte : : log_filter
class log_tester 2 final : public srslte : : scoped_tester_log
{
{
public :
public :
explicit log_tester ( std : : string layer ) : srslte : : log_filter ( layer ) { }
log_tester2 ( ) : srslte : : scoped_tester_log ( " MAC " ) { exit_on_error = true ; }
~ log_tester ( ) final
~ log_tester2 ( ) override { log_diagnostics ( ) ; }
void log_diagnostics ( ) override
{
{
info ( " [TESTER] UE stats: \n " ) ;
info ( " [TESTER] UE stats: \n " ) ;
for ( auto & e : ue_stats ) {
for ( auto & e : ue_stats ) {
info ( " 0x%x: {DL RBs: % " PRIu64 " , UL RBs: % " PRIu64 " } \n " , e . first , e . second . nof_dl_rbs , e . second . nof_ul_rbs ) ;
info ( " 0x%x: {DL RBs: % " PRIu64 " , UL RBs: % " PRIu64 " } \n " , e . first , e . second . nof_dl_rbs , e . second . nof_ul_rbs ) ;
}
}
info ( " [TESTER] Number of assertion warnings: %u \n " , warn_counter ) ;
info ( " [TESTER] Number of assertion errors: %u \n " , error_counter ) ;
info ( " [TESTER] This was the seed: %u \n " , seed ) ;
info ( " [TESTER] This was the seed: %u \n " , seed ) ;
}
}
} ;
} ;
log_tester log_out ( " ALL " ) ;
log_tester2 log_global ;
bool check_old_pids = true ;
# define Warning(fmt, ...) \
log_out . warning ( fmt , # # __VA_ARGS__ ) ; \
warn_counter + +
# define TestError(fmt, ...) \
log_out . error ( fmt , # # __VA_ARGS__ ) ; \
exit ( - 1 )
# define CondError(cond, fmt, ...) \
do { \
if ( cond ) { \
log_out . error ( fmt , # # __VA_ARGS__ ) ; \
exit ( - 1 ) ; \
} \
} while ( 0 )
/*******************
/*******************
* Dummies *
* Dummies *
@ -219,49 +210,50 @@ struct sched_tester : public srsenb::sched {
// sched results
// sched results
sched_tti_data tti_data ;
sched_tti_data tti_data ;
void add_user ( uint16_t rnti ,
int add_user ( uint16_t rnti ,
srsenb : : sched_interface : : ue_bearer_cfg_t bearer_cfg ,
srsenb : : sched_interface : : ue_bearer_cfg_t bearer_cfg ,
srsenb : : sched_interface : : ue_cfg_t ue_cfg_ ) ;
srsenb : : sched_interface : : ue_cfg_t ue_cfg_ ) ;
void rem_user ( uint16_t rnti ) ;
void rem_user ( uint16_t rnti ) ;
void test_ra ( ) ;
int test_ra ( ) ;
void test_tti_result ( ) ;
int test_tti_result ( ) ;
void assert_no_empty_allocs ( ) ;
int assert_no_empty_allocs ( ) ;
void test_collisions ( ) ;
int test_collisions ( ) ;
void test_harqs ( ) ;
int test_harqs ( ) ;
void test_sibs ( ) ;
int test_sibs ( ) ;
void run_tti ( uint32_t tti_rx ) ;
void run_tti ( uint32_t tti_rx ) ;
private :
private :
void new_test_tti ( uint32_t tti_ ) ;
void new_test_tti ( uint32_t tti_ ) ;
void process_tti_args ( ) ;
int process_tti_args ( ) ;
void before_sched ( ) ;
void before_sched ( ) ;
void process_results ( ) ;
int process_results ( ) ;
void ack_txs ( ) ;
int ack_txs ( ) ;
} ;
} ;
void sched_tester : : add_user ( uint16_t rnti ,
int sched_tester : : add_user ( uint16_t rnti ,
srsenb : : sched_interface : : ue_bearer_cfg_t bearer_cfg ,
srsenb : : sched_interface : : ue_bearer_cfg_t bearer_cfg ,
srsenb : : sched_interface : : ue_cfg_t ue_cfg_ )
srsenb : : sched_interface : : ue_cfg_t ue_cfg_ )
{
{
ue_info info ;
ue_info info ;
info . prach_tti = tti_data . tti_rx ;
info . prach_tti = tti_data . tti_rx ;
info . bearer_cfg = bearer_cfg ;
info . bearer_cfg = bearer_cfg ;
info . user_cfg = ue_cfg_ ;
info . user_cfg = ue_cfg_ ;
tester_ues . insert ( std : : make_pair ( rnti , info ) ) ;
tester_ues . insert ( std : : make_pair ( rnti , info ) ) ;
if ( ue_cfg ( rnti , & ue_cfg_ ) ! = SRSLTE_SUCCESS ) {
if ( ue_cfg ( rnti , & ue_cfg_ ) ! = SRSLTE_SUCCESS ) {
T estError ( " [TESTER] Registering new user rnti=0x%x to SCHED \n " , rnti ) ;
T ESTERROR ( " [TESTER] Registering new user rnti=0x%x to SCHED \n " , rnti ) ;
}
}
dl_sched_rar_info_t rar_info = { } ;
dl_sched_rar_info_t rar_info = { } ;
rar_info . prach_tti = tti_data . tti_rx ;
rar_info . prach_tti = tti_data . tti_rx ;
rar_info . temp_crnti = rnti ;
rar_info . temp_crnti = rnti ;
rar_info . msg3_size = 7 ;
rar_info . msg3_size = 7 ;
dl_rach_info ( rar_info ) ;
dl_rach_info ( rar_info ) ;
// setup bearers
// setup bearers
bearer_ue_cfg ( rnti , 0 , & bearer_cfg ) ;
bearer_ue_cfg ( rnti , 0 , & bearer_cfg ) ;
log_out . info ( " [TESTER] Adding user rnti=0x%x \n " , rnti ) ;
log_global . info ( " [TESTER] Adding user rnti=0x%x \n " , rnti ) ;
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : rem_user ( uint16_t rnti )
void sched_tester : : rem_user ( uint16_t rnti )
@ -290,11 +282,11 @@ void sched_tester::new_test_tti(uint32_t tti_)
tti_data . total_ues = tester_user_results ( ) ;
tti_data . total_ues = tester_user_results ( ) ;
}
}
void sched_tester : : process_tti_args ( )
int sched_tester : : process_tti_args ( )
{
{
// may add a new user
// may add a new user
if ( sim_args . tti_events [ tti_data . tti_rx ] . new_user ) {
if ( sim_args . tti_events [ tti_data . tti_rx ] . new_user ) {
C ondError ( ! srslte_prach_tti_opportunity_config_fdd ( cfg . prach_config , tti_data . tti_rx , - 1 ) ,
C ONDERROR ( ! srslte_prach_tti_opportunity_config_fdd ( cfg . prach_config , tti_data . tti_rx , - 1 ) ,
" [TESTER] New user added in a non-PRACH TTI \n " ) ;
" [TESTER] New user added in a non-PRACH TTI \n " ) ;
uint16_t rnti = sim_args . tti_events [ tti_data . tti_rx ] . new_rnti ;
uint16_t rnti = sim_args . tti_events [ tti_data . tti_rx ] . new_rnti ;
add_user ( rnti , sim_args . bearer_cfg , sim_args . ue_cfg ) ;
add_user ( rnti , sim_args . bearer_cfg , sim_args . ue_cfg ) ;
@ -306,7 +298,7 @@ void sched_tester::process_tti_args()
bearer_ue_rem ( rnti , 0 ) ;
bearer_ue_rem ( rnti , 0 ) ;
ue_rem ( rnti ) ;
ue_rem ( rnti ) ;
rem_user ( rnti ) ;
rem_user ( rnti ) ;
log_ out . info ( " [TESTER] Removing user rnti=0x%x \n " , rnti ) ;
log_ global . info ( " [TESTER] Removing user rnti=0x%x \n " , rnti ) ;
}
}
// push UL SRs and DL packets
// push UL SRs and DL packets
@ -323,6 +315,8 @@ void sched_tester::process_tti_args()
dl_rlc_buffer_state ( e . first , lcid , tot_dl_data , 0 ) ;
dl_rlc_buffer_state ( e . first , lcid , tot_dl_data , 0 ) ;
}
}
}
}
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : before_sched ( )
void sched_tester : : before_sched ( )
@ -360,12 +354,12 @@ void sched_tester::before_sched()
// TODO: Check whether pending pending_rar.rar_tti correspond to a prach_tti
// TODO: Check whether pending pending_rar.rar_tti correspond to a prach_tti
}
}
void sched_tester : : process_results ( )
int sched_tester : : process_results ( )
{
{
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
uint16_t rnti = tti_data . sched_result_ul . pusch [ i ] . dci . rnti ;
uint16_t rnti = tti_data . sched_result_ul . pusch [ i ] . dci . rnti ;
tti_data . ue_data [ rnti ] . ul_sched = & tti_data . sched_result_ul . pusch [ i ] ;
tti_data . ue_data [ rnti ] . ul_sched = & tti_data . sched_result_ul . pusch [ i ] ;
C ondError ( tester_ues . count ( rnti ) = = 0 ,
C ONDERROR ( tester_ues . count ( rnti ) = = 0 ,
" [TESTER] [%d] The user rnti=0x%x that no longer exists got allocated. \n " ,
" [TESTER] [%d] The user rnti=0x%x that no longer exists got allocated. \n " ,
tti_data . tti_rx ,
tti_data . tti_rx ,
rnti ) ;
rnti ) ;
@ -373,7 +367,7 @@ void sched_tester::process_results()
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
uint16_t rnti = tti_data . sched_result_dl . data [ i ] . dci . rnti ;
uint16_t rnti = tti_data . sched_result_dl . data [ i ] . dci . rnti ;
tti_data . ue_data [ rnti ] . dl_sched = & tti_data . sched_result_dl . data [ i ] ;
tti_data . ue_data [ rnti ] . dl_sched = & tti_data . sched_result_dl . data [ i ] ;
C ondError ( tester_ues . count ( rnti ) = = 0 ,
C ONDERROR ( tester_ues . count ( rnti ) = = 0 ,
" [TESTER] [%d] The user rnti=0x%x that no longer exists got allocated. \n " ,
" [TESTER] [%d] The user rnti=0x%x that no longer exists got allocated. \n " ,
tti_data . tti_rx ,
tti_data . tti_rx ,
rnti ) ;
rnti ) ;
@ -385,12 +379,14 @@ void sched_tester::process_results()
assert_no_empty_allocs ( ) ;
assert_no_empty_allocs ( ) ;
test_harqs ( ) ;
test_harqs ( ) ;
test_sibs ( ) ;
test_sibs ( ) ;
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : run_tti ( uint32_t tti_rx )
void sched_tester : : run_tti ( uint32_t tti_rx )
{
{
new_test_tti ( tti_rx ) ;
new_test_tti ( tti_rx ) ;
log_ out . info ( " [TESTER] ---- tti=%u | nof_ues=%zd ---- \n " , tti_rx , ue_db . size ( ) ) ;
log_ global . info ( " [TESTER] ---- tti=%u | nof_ues=%zd ---- \n " , tti_rx , ue_db . size ( ) ) ;
process_tti_args ( ) ;
process_tti_args ( ) ;
@ -406,7 +402,7 @@ void sched_tester::run_tti(uint32_t tti_rx)
/**
/**
* Tests whether the RAR and Msg3 were scheduled within the expected windows
* Tests whether the RAR and Msg3 were scheduled within the expected windows
*/
*/
void sched_tester : : test_ra ( )
int sched_tester : : test_ra ( )
{
{
uint32_t msg3_count = 0 ;
uint32_t msg3_count = 0 ;
@ -424,7 +420,7 @@ void sched_tester::test_ra()
bool rar_not_sent = prach_tti > = userinfo . rar_tti ;
bool rar_not_sent = prach_tti > = userinfo . rar_tti ;
uint32_t window [ 2 ] = { ( uint32_t ) prach_tti + 3 , prach_tti + 3 + cfg . prach_rar_window } ;
uint32_t window [ 2 ] = { ( uint32_t ) prach_tti + 3 , prach_tti + 3 + cfg . prach_rar_window } ;
if ( rar_not_sent ) {
if ( rar_not_sent ) {
C ondError ( tti_data . tti_tx_dl > window [ 1 ] , " [TESTER] There was no RAR scheduled within the RAR Window \n " ) ;
C ONDERROR ( tti_data . tti_tx_dl > window [ 1 ] , " [TESTER] There was no RAR scheduled within the RAR Window \n " ) ;
if ( tti_data . tti_tx_dl > = window [ 0 ] ) {
if ( tti_data . tti_tx_dl > = window [ 0 ] ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_rar_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_rar_elems ; + + i ) {
for ( uint32_t j = 0 ; j < tti_data . sched_result_dl . rar [ i ] . nof_grants ; + + j ) {
for ( uint32_t j = 0 ; j < tti_data . sched_result_dl . rar [ i ] . nof_grants ; + + j ) {
@ -439,27 +435,29 @@ void sched_tester::test_ra()
if ( msg3_tti = = tti_data . tti_tx_ul ) {
if ( msg3_tti = = tti_data . tti_tx_ul ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
if ( tti_data . sched_result_ul . pusch [ i ] . dci . rnti = = rnti ) {
if ( tti_data . sched_result_ul . pusch [ i ] . dci . rnti = = rnti ) {
C ondError ( tti_data . sched_result_ul . pusch [ i ] . needs_pdcch ,
C ONDERROR ( tti_data . sched_result_ul . pusch [ i ] . needs_pdcch ,
" [TESTER] Msg3 allocations do not require PDCCH \n " ) ;
" [TESTER] Msg3 allocations do not require PDCCH \n " ) ;
C ondError ( tti_data . ul_pending_msg3 . rnti ! = rnti , " [TESTER] The UL pending msg3 RNTI did not match \n " ) ;
C ONDERROR ( tti_data . ul_pending_msg3 . rnti ! = rnti , " [TESTER] The UL pending msg3 RNTI did not match \n " ) ;
C ondError ( not tti_data . ul_pending_msg3 . enabled , " [TESTER] The UL pending msg3 RNTI did not match \n " ) ;
C ONDERROR ( not tti_data . ul_pending_msg3 . enabled , " [TESTER] The UL pending msg3 RNTI did not match \n " ) ;
userinfo . msg3_tti = tti_data . tti_tx_ul ;
userinfo . msg3_tti = tti_data . tti_tx_ul ;
msg3_count + + ;
msg3_count + + ;
}
}
}
}
C ondError ( msg3_count = = 0 , " [TESTER] No UL msg3 allocation was made \n " ) ;
C ONDERROR ( msg3_count = = 0 , " [TESTER] No UL msg3 allocation was made \n " ) ;
} else if ( msg3_tti < tti_data . tti_tx_ul ) {
} else if ( msg3_tti < tti_data . tti_tx_ul ) {
T estError ( " [TESTER] No UL msg3 allocation was made \n " ) ;
T ESTERROR ( " [TESTER] No UL msg3 allocation was made \n " ) ;
}
}
}
}
}
}
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
msg3_count - = tti_data . sched_result_ul . pusch [ i ] . needs_pdcch ? 0 : 1 ;
msg3_count - = tti_data . sched_result_ul . pusch [ i ] . needs_pdcch ? 0 : 1 ;
}
}
CondError ( msg3_count > 0 , " [TESTER] There are pending msg3 that do not belong to any active UE \n " ) ;
CONDERROR ( msg3_count > 0 , " [TESTER] There are pending msg3 that do not belong to any active UE \n " ) ;
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : assert_no_empty_allocs ( )
int sched_tester : : assert_no_empty_allocs ( )
{
{
// Test if allocations only take place for users with pending data or in RAR
// Test if allocations only take place for users with pending data or in RAR
for ( auto & iter : tti_data . ue_data ) {
for ( auto & iter : tti_data . ue_data ) {
@ -469,13 +467,13 @@ void sched_tester::assert_no_empty_allocs()
if ( ! iter . second . has_ul_tx and tti_data . ue_data [ rnti ] . ul_sched ! = nullptr and
if ( ! iter . second . has_ul_tx and tti_data . ue_data [ rnti ] . ul_sched ! = nullptr and
tti_data . ue_data [ rnti ] . ul_sched - > needs_pdcch ) {
tti_data . ue_data [ rnti ] . ul_sched - > needs_pdcch ) {
// FIXME: This test does not work for adaptive re-tx
// FIXME: This test does not work for adaptive re-tx
T estError ( " [TESTER] There was a user without data that got allocated in UL \n " ) ;
T ESTERROR ( " [TESTER] There was a user without data that got allocated in UL \n " ) ;
}
}
// srsenb::ul_harq_proc* hul = user->get_ul_harq(tti_data.tti_tx_ul);
// srsenb::ul_harq_proc* hul = user->get_ul_harq(tti_data.tti_tx_ul);
iter . second . ul_retx_got_delayed = iter . second . has_ul_retx and iter . second . ul_harq . is_empty ( 0 ) ;
iter . second . ul_retx_got_delayed = iter . second . has_ul_retx and iter . second . ul_harq . is_empty ( 0 ) ;
tti_data . total_ues . ul_retx_got_delayed | = iter . second . ul_retx_got_delayed ;
tti_data . total_ues . ul_retx_got_delayed | = iter . second . ul_retx_got_delayed ;
// Retxs cannot give space to newtx allocations
// Retxs cannot give space to newtx allocations
C ondError (
C ONDERROR (
tti_data . total_ues . ul_retx_got_delayed , " [TESTER] There was a retx that was erased for user rnti=0x%x \n " , rnti ) ;
tti_data . total_ues . ul_retx_got_delayed , " [TESTER] There was a retx that was erased for user rnti=0x%x \n " , rnti ) ;
}
}
@ -486,14 +484,15 @@ void sched_tester::assert_no_empty_allocs()
no_dl_allocs = false ;
no_dl_allocs = false ;
}
}
}
}
// C ondError (tti_data.total_ues.has_dl_tx and no_dl_allocs, "There was pending DL data but no user got allocated\n");
// C ONDERROR (tti_data.total_ues.has_dl_tx and no_dl_allocs, "There was pending DL data but no user got allocated\n");
// FIXME: You have to verify if there is space for the retx since it is non-adaptive
// FIXME: You have to verify if there is space for the retx since it is non-adaptive
return SRSLTE_SUCCESS ;
}
}
/**
/**
* Tests whether there were collisions in the DCI allocations
* Tests whether there were collisions in the DCI allocations
*/
*/
void sched_tester : : test_tti_result ( )
int sched_tester : : test_tti_result ( )
{
{
carrier_sched : : tti_sched_result_t * tti_sched = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) ;
carrier_sched : : tti_sched_result_t * tti_sched = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) ;
@ -501,21 +500,22 @@ void sched_tester::test_tti_result()
auto try_cce_fill = [ & ] ( const srslte_dci_location_t & dci_loc , const char * ch ) {
auto try_cce_fill = [ & ] ( const srslte_dci_location_t & dci_loc , const char * ch ) {
uint32_t cce_start = dci_loc . ncce , cce_stop = dci_loc . ncce + ( 1u < < dci_loc . L ) ;
uint32_t cce_start = dci_loc . ncce , cce_stop = dci_loc . ncce + ( 1u < < dci_loc . L ) ;
if ( tti_data . used_cce . any ( cce_start , cce_stop ) ) {
if ( tti_data . used_cce . any ( cce_start , cce_stop ) ) {
T estError ( " [TESTER] %s DCI collision between CCE positions (%u, %u) \n " , ch , cce_start , cce_stop ) ;
T ESTERROR ( " [TESTER] %s DCI collision between CCE positions (%u, %u) \n " , ch , cce_start , cce_stop ) ;
}
}
tti_data . used_cce . fill ( cce_start , cce_stop ) ;
tti_data . used_cce . fill ( cce_start , cce_stop ) ;
return SRSLTE_SUCCESS ;
} ;
} ;
/* verify there are no dci collisions for UL, DL data, BC, RAR */
/* verify there are no dci collisions for UL, DL data, BC, RAR */
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
const auto & pusch = tti_data . sched_result_ul . pusch [ i ] ;
const auto & pusch = tti_data . sched_result_ul . pusch [ i ] ;
C ondError ( pusch . tbs = = 0 , " Allocated RAR process with invalid TBS=%d \n " , pusch . tbs ) ;
C ONDERROR ( pusch . tbs = = 0 , " Allocated RAR process with invalid TBS=%d \n " , pusch . tbs ) ;
C ondError ( ue_db . count ( pusch . dci . rnti ) = = 0 , " The allocated rnti=0x%x does not exist \n " , pusch . dci . rnti ) ;
C ONDERROR ( ue_db . count ( pusch . dci . rnti ) = = 0 , " The allocated rnti=0x%x does not exist \n " , pusch . dci . rnti ) ;
if ( not pusch . needs_pdcch ) {
if ( not pusch . needs_pdcch ) {
// In case of non-adaptive retx or Msg3
// In case of non-adaptive retx or Msg3
continue ;
continue ;
}
}
C ondError ( pusch . dci . location . L = = 0 ,
C ONDERROR ( pusch . dci . location . L = = 0 ,
" [TESTER] Invalid aggregation level %d \n " ,
" [TESTER] Invalid aggregation level %d \n " ,
pusch . dci . location . L ) ; // TODO: Extend this test
pusch . dci . location . L ) ; // TODO: Extend this test
try_cce_fill ( pusch . dci . location , " UL " ) ;
try_cce_fill ( pusch . dci . location , " UL " ) ;
@ -523,34 +523,34 @@ void sched_tester::test_tti_result()
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
auto & data = tti_data . sched_result_dl . data [ i ] ;
auto & data = tti_data . sched_result_dl . data [ i ] ;
try_cce_fill ( data . dci . location , " DL data " ) ;
try_cce_fill ( data . dci . location , " DL data " ) ;
C ondError ( ue_db . count ( data . dci . rnti ) = = 0 , " Allocated rnti=0x%x that does not exist \n " , data . dci . rnti ) ;
C ONDERROR ( ue_db . count ( data . dci . rnti ) = = 0 , " Allocated rnti=0x%x that does not exist \n " , data . dci . rnti ) ;
}
}
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_bc_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_bc_elems ; + + i ) {
auto & bc = tti_data . sched_result_dl . bc [ i ] ;
auto & bc = tti_data . sched_result_dl . bc [ i ] ;
try_cce_fill ( bc . dci . location , " DL BC " ) ;
try_cce_fill ( bc . dci . location , " DL BC " ) ;
if ( bc . type = = sched_interface : : dl_sched_bc_t : : BCCH ) {
if ( bc . type = = sched_interface : : dl_sched_bc_t : : BCCH ) {
C ondError ( bc . index > = MAX_SIBS , " Invalid SIB idx=%d \n " , bc . index + 1 ) ;
C ONDERROR ( bc . index > = MAX_SIBS , " Invalid SIB idx=%d \n " , bc . index + 1 ) ;
C ondError ( bc . tbs < cfg . sibs [ bc . index ] . len ,
C ONDERROR ( bc . tbs < cfg . sibs [ bc . index ] . len ,
" Allocated BC process with TBS=%d < sib_len=%d \n " ,
" Allocated BC process with TBS=%d < sib_len=%d \n " ,
bc . tbs ,
bc . tbs ,
cfg . sibs [ bc . index ] . len ) ;
cfg . sibs [ bc . index ] . len ) ;
} else if ( bc . type = = sched_interface : : dl_sched_bc_t : : PCCH ) {
} else if ( bc . type = = sched_interface : : dl_sched_bc_t : : PCCH ) {
C ondError ( bc . tbs = = 0 , " Allocated paging process with invalid TBS=%d \n " , bc . tbs ) ;
C ONDERROR ( bc . tbs = = 0 , " Allocated paging process with invalid TBS=%d \n " , bc . tbs ) ;
} else {
} else {
T estError ( " Invalid broadcast process id=%d \n " , ( int ) bc . type ) ;
T ESTERROR ( " Invalid broadcast process id=%d \n " , ( int ) bc . type ) ;
}
}
}
}
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_rar_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_rar_elems ; + + i ) {
const auto & rar = tti_data . sched_result_dl . rar [ i ] ;
const auto & rar = tti_data . sched_result_dl . rar [ i ] ;
try_cce_fill ( rar . dci . location , " DL RAR " ) ;
try_cce_fill ( rar . dci . location , " DL RAR " ) ;
C ondError ( rar . tbs = = 0 , " Allocated RAR process with invalid TBS=%d \n " , rar . tbs ) ;
C ONDERROR ( rar . tbs = = 0 , " Allocated RAR process with invalid TBS=%d \n " , rar . tbs ) ;
for ( uint32_t j = 0 ; j < rar . nof_grants ; + + j ) {
for ( uint32_t j = 0 ; j < rar . nof_grants ; + + j ) {
const auto & msg3_grant = rar . msg3_grant [ j ] ;
const auto & msg3_grant = rar . msg3_grant [ j ] ;
const srsenb : : ra_sched : : pending_msg3_t & p =
const srsenb : : ra_sched : : pending_msg3_t & p =
carrier_schedulers [ 0 ] - > ra_sched_ptr - > find_pending_msg3 ( tti_sched - > get_tti_tx_dl ( ) + MSG3_DELAY_MS + TX_DELAY ) ;
carrier_schedulers [ 0 ] - > ra_sched_ptr - > find_pending_msg3 ( tti_sched - > get_tti_tx_dl ( ) + MSG3_DELAY_MS + TX_DELAY ) ;
C ondError ( not p . enabled , " Pending Msg3 should have been set \n " ) ;
C ONDERROR ( not p . enabled , " Pending Msg3 should have been set \n " ) ;
uint32_t rba = srslte_ra_type2_to_riv ( p . L , p . n_prb , cfg . cell . nof_prb ) ;
uint32_t rba = srslte_ra_type2_to_riv ( p . L , p . n_prb , cfg . cell . nof_prb ) ;
C ondError ( msg3_grant . grant . rba ! = rba , " Pending Msg3 RBA is not valid \n " ) ;
C ONDERROR ( msg3_grant . grant . rba ! = rba , " Pending Msg3 RBA is not valid \n " ) ;
}
}
}
}
@ -558,7 +558,7 @@ void sched_tester::test_tti_result()
auto * tti_alloc = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) ;
auto * tti_alloc = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) ;
if ( tti_data . used_cce ! = tti_alloc - > get_pdcch_mask ( ) ) {
if ( tti_data . used_cce ! = tti_alloc - > get_pdcch_mask ( ) ) {
std : : string mask_str = tti_alloc - > get_pdcch_mask ( ) . to_string ( ) ;
std : : string mask_str = tti_alloc - > get_pdcch_mask ( ) . to_string ( ) ;
T estError ( " [TESTER] The used_cce do not match: (%s!=%s) \n " , mask_str . c_str ( ) , tti_data . used_cce . to_hex ( ) . c_str ( ) ) ;
T ESTERROR ( " [TESTER] The used_cce do not match: (%s!=%s) \n " , mask_str . c_str ( ) , tti_data . used_cce . to_hex ( ) . c_str ( ) ) ;
}
}
// FIXME: Check postponed retxs
// FIXME: Check postponed retxs
@ -569,13 +569,14 @@ void sched_tester::test_tti_result()
// for (it_t it = ue_db.begin(); it != ue_db.end(); ++it) {
// for (it_t it = ue_db.begin(); it != ue_db.end(); ++it) {
// uint32_t aggr_level = it->second.get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, cfg.cell.nof_prb,
// uint32_t aggr_level = it->second.get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, cfg.cell.nof_prb,
// cfg.cell.nof_ports)); if (find_empty_dci(it->second.get_locations(current_cfi, sf_idx), aggr_level) > 0) {
// cfg.cell.nof_ports)); if (find_empty_dci(it->second.get_locations(current_cfi, sf_idx), aggr_level) > 0) {
// T estError ("[%d] There was pending UL data and free CCEs, but no user got allocated\n", tti_data.tti_rx);
// T ESTERROR ("[%d] There was pending UL data and free CCEs, but no user got allocated\n", tti_data.tti_rx);
// }
// }
// }
// }
// }
// }
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : test_harqs ( )
int sched_tester : : test_harqs ( )
{
{
/* check consistency of DL harq procedures and allocations */
/* check consistency of DL harq procedures and allocations */
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
@ -583,23 +584,23 @@ void sched_tester::test_harqs()
uint32_t h_id = data . dci . pid ;
uint32_t h_id = data . dci . pid ;
uint16_t rnti = data . dci . rnti ;
uint16_t rnti = data . dci . rnti ;
const srsenb : : dl_harq_proc * h = ue_db [ rnti ] . get_dl_harq ( h_id ) ;
const srsenb : : dl_harq_proc * h = ue_db [ rnti ] . get_dl_harq ( h_id ) ;
C ondError ( h = = nullptr , " [TESTER] scheduled DL harq pid=%d does not exist \n " , h_id ) ;
C ONDERROR ( h = = nullptr , " [TESTER] scheduled DL harq pid=%d does not exist \n " , h_id ) ;
C ondError ( h - > is_empty ( ) , " [TESTER] Cannot schedule an empty harq proc \n " ) ;
C ONDERROR ( h - > is_empty ( ) , " [TESTER] Cannot schedule an empty harq proc \n " ) ;
C ondError ( h - > get_tti ( ) ! = tti_data . tti_tx_dl ,
C ONDERROR ( h - > get_tti ( ) ! = tti_data . tti_tx_dl ,
" [TESTER] The scheduled DL harq pid=%d does not a valid tti=%u \n " ,
" [TESTER] The scheduled DL harq pid=%d does not a valid tti=%u \n " ,
h_id ,
h_id ,
tti_data . tti_tx_dl ) ;
tti_data . tti_tx_dl ) ;
C ondError ( h - > get_n_cce ( ) ! = data . dci . location . ncce , " [TESTER] Harq DCI location does not match with result \n " ) ;
C ONDERROR ( h - > get_n_cce ( ) ! = data . dci . location . ncce , " [TESTER] Harq DCI location does not match with result \n " ) ;
if ( tti_data . ue_data [ rnti ] . dl_harqs [ h_id ] . has_pending_retx ( 0 , tti_data . tti_tx_dl ) ) { // retx
if ( tti_data . ue_data [ rnti ] . dl_harqs [ h_id ] . has_pending_retx ( 0 , tti_data . tti_tx_dl ) ) { // retx
C ondError ( tti_data . ue_data [ rnti ] . dl_harqs [ h_id ] . nof_retx ( 0 ) + 1 ! = h - > nof_retx ( 0 ) ,
C ONDERROR ( tti_data . ue_data [ rnti ] . dl_harqs [ h_id ] . nof_retx ( 0 ) + 1 ! = h - > nof_retx ( 0 ) ,
" [TESTER] A dl harq of user rnti=0x%x was likely overwritten. \n " ,
" [TESTER] A dl harq of user rnti=0x%x was likely overwritten. \n " ,
rnti ) ;
rnti ) ;
C ondError ( h - > nof_retx ( 0 ) > = sim_args . ue_cfg . maxharq_tx ,
C ONDERROR ( h - > nof_retx ( 0 ) > = sim_args . ue_cfg . maxharq_tx ,
" [TESTER] The number of retx=%d exceeded its max=%d \n " ,
" [TESTER] The number of retx=%d exceeded its max=%d \n " ,
h - > nof_retx ( 0 ) ,
h - > nof_retx ( 0 ) ,
sim_args . ue_cfg . maxharq_tx ) ;
sim_args . ue_cfg . maxharq_tx ) ;
} else { // newtx
} else { // newtx
C ondError ( h - > nof_retx ( 0 ) ! = 0 , " [TESTER] A new harq was scheduled but with invalid number of retxs \n " ) ;
C ONDERROR ( h - > nof_retx ( 0 ) ! = 0 , " [TESTER] A new harq was scheduled but with invalid number of retxs \n " ) ;
}
}
}
}
@ -608,36 +609,36 @@ void sched_tester::test_harqs()
uint16_t rnti = pusch . dci . rnti ;
uint16_t rnti = pusch . dci . rnti ;
const auto & ue_data = tti_data . ue_data [ rnti ] ;
const auto & ue_data = tti_data . ue_data [ rnti ] ;
const srsenb : : ul_harq_proc * h = ue_db [ rnti ] . get_ul_harq ( tti_data . tti_tx_ul ) ;
const srsenb : : ul_harq_proc * h = ue_db [ rnti ] . get_ul_harq ( tti_data . tti_tx_ul ) ;
C ondError ( h = = nullptr or h - > is_empty ( ) , " [TESTER] scheduled UL harq does not exist or is empty \n " ) ;
C ONDERROR ( h = = nullptr or h - > is_empty ( ) , " [TESTER] scheduled UL harq does not exist or is empty \n " ) ;
C ondError ( h - > get_tti ( ) ! = tti_data . tti_tx_ul ,
C ONDERROR ( h - > get_tti ( ) ! = tti_data . tti_tx_ul ,
" [TESTER] The scheduled UL harq does not a valid tti=%u \n " ,
" [TESTER] The scheduled UL harq does not a valid tti=%u \n " ,
tti_data . tti_tx_ul ) ;
tti_data . tti_tx_ul ) ;
C ondError ( h - > has_pending_ack ( ) , " [TESTER] At the end of the TTI, there shouldnt be any pending ACKs \n " ) ;
C ONDERROR ( h - > has_pending_ack ( ) , " [TESTER] At the end of the TTI, there shouldnt be any pending ACKs \n " ) ;
if ( h - > has_pending_retx ( ) ) {
if ( h - > has_pending_retx ( ) ) {
// retx
// retx
C ondError ( ue_data . ul_harq . is_empty ( 0 ) , " [TESTER] reTx in an UL harq that was empty \n " ) ;
C ONDERROR ( ue_data . ul_harq . is_empty ( 0 ) , " [TESTER] reTx in an UL harq that was empty \n " ) ;
C ondError ( h - > nof_retx ( 0 ) ! = ue_data . ul_harq . nof_retx ( 0 ) + 1 ,
C ONDERROR ( h - > nof_retx ( 0 ) ! = ue_data . ul_harq . nof_retx ( 0 ) + 1 ,
" [TESTER] A retx UL harq was scheduled but with invalid number of retxs \n " ) ;
" [TESTER] A retx UL harq was scheduled but with invalid number of retxs \n " ) ;
C ondError ( h - > is_adaptive_retx ( ) and not pusch . needs_pdcch , " [TESTER] Adaptive retxs need PDCCH alloc \n " ) ;
C ONDERROR ( h - > is_adaptive_retx ( ) and not pusch . needs_pdcch , " [TESTER] Adaptive retxs need PDCCH alloc \n " ) ;
} else {
} else {
C ondError ( h - > nof_retx ( 0 ) ! = 0 , " [TESTER] A new harq was scheduled but with invalid number of retxs \n " ) ;
C ONDERROR ( h - > nof_retx ( 0 ) ! = 0 , " [TESTER] A new harq was scheduled but with invalid number of retxs \n " ) ;
C ondError ( not ue_data . ul_harq . is_empty ( 0 ) , " [TESTER] UL new tx in a UL harq that was not empty \n " ) ;
C ONDERROR ( not ue_data . ul_harq . is_empty ( 0 ) , " [TESTER] UL new tx in a UL harq that was not empty \n " ) ;
}
}
}
}
/* Check PHICH allocations */
/* Check PHICH allocations */
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_phich_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_phich_elems ; + + i ) {
const auto & phich = tti_data . sched_result_ul . phich [ i ] ;
const auto & phich = tti_data . sched_result_ul . phich [ i ] ;
C ondError ( tti_data . ue_data . count ( phich . rnti ) = = 0 , " [TESTER] Allocated PHICH rnti no longer exists \n " ) ;
C ONDERROR ( tti_data . ue_data . count ( phich . rnti ) = = 0 , " [TESTER] Allocated PHICH rnti no longer exists \n " ) ;
const auto & hprev = tti_data . ue_data [ phich . rnti ] . ul_harq ;
const auto & hprev = tti_data . ue_data [ phich . rnti ] . ul_harq ;
const auto * h = ue_db [ phich . rnti ] . get_ul_harq ( tti_data . tti_tx_ul ) ;
const auto * h = ue_db [ phich . rnti ] . get_ul_harq ( tti_data . tti_tx_ul ) ;
C ondError ( not hprev . has_pending_ack ( ) , " [TESTER] Alloc PHICH did not have any pending ack \n " ) ;
C ONDERROR ( not hprev . has_pending_ack ( ) , " [TESTER] Alloc PHICH did not have any pending ack \n " ) ;
bool maxretx_flag = hprev . nof_retx ( 0 ) + 1 > = hprev . max_nof_retx ( ) ;
bool maxretx_flag = hprev . nof_retx ( 0 ) + 1 > = hprev . max_nof_retx ( ) ;
if ( phich . phich = = sched_interface : : ul_sched_phich_t : : ACK ) {
if ( phich . phich = = sched_interface : : ul_sched_phich_t : : ACK ) {
C ondError ( ! hprev . is_empty ( ) , " [TESTER] ack phich for UL harq that is not empty \n " ) ;
C ONDERROR ( ! hprev . is_empty ( ) , " [TESTER] ack phich for UL harq that is not empty \n " ) ;
} else {
} else {
C ondError ( h - > get_pending_data ( ) = = 0 and ! maxretx_flag , " [TESTER] NACKed harq has no pending data \n " ) ;
C ONDERROR ( h - > get_pending_data ( ) = = 0 and ! maxretx_flag , " [TESTER] NACKed harq has no pending data \n " ) ;
}
}
}
}
for ( const auto & ue : ue_db ) {
for ( const auto & ue : ue_db ) {
@ -652,7 +653,7 @@ void sched_tester::test_harqs()
break ;
break ;
}
}
}
}
C ondError ( i = = tti_data . sched_result_ul . nof_phich_elems ,
C ONDERROR ( i = = tti_data . sched_result_ul . nof_phich_elems ,
" [TESTER] harq had pending ack but no phich was allocked \n " ) ;
" [TESTER] harq had pending ack but no phich was allocked \n " ) ;
}
}
@ -673,7 +674,7 @@ void sched_tester::test_harqs()
ack_it_t it = to_ack . begin ( ) ;
ack_it_t it = to_ack . begin ( ) ;
while ( it ! = to_ack . end ( ) and it - > first < ack_data . tti ) {
while ( it ! = to_ack . end ( ) and it - > first < ack_data . tti ) {
if ( it - > second . rnti = = ack_data . rnti and it - > second . dl_harq . get_id ( ) = = ack_data . dl_harq . get_id ( ) ) {
if ( it - > second . rnti = = ack_data . rnti and it - > second . dl_harq . get_id ( ) = = ack_data . dl_harq . get_id ( ) ) {
C ondError ( it - > second . tti + 2 * FDD_HARQ_DELAY_MS > ack_data . tti ,
C ONDERROR ( it - > second . tti + 2 * FDD_HARQ_DELAY_MS > ack_data . tti ,
" [TESTER] The retx dl harq id=%d was transmitted too soon \n " ,
" [TESTER] The retx dl harq id=%d was transmitted too soon \n " ,
ack_data . dl_harq . get_id ( ) ) ;
ack_data . dl_harq . get_id ( ) ) ;
ack_it_t toerase_it = it + + ;
ack_it_t toerase_it = it + + ;
@ -703,20 +704,23 @@ void sched_tester::test_harqs()
to_ul_ack . insert ( std : : make_pair ( ack_data . tti_tx_ul , ack_data ) ) ;
to_ul_ack . insert ( std : : make_pair ( ack_data . tti_tx_ul , ack_data ) ) ;
}
}
// // Check whether some pids got old
// Check whether some pids got old
// for (auto& user : ue_db) {
if ( check_old_pids ) {
// for (int i = 0; i < 2 * FDD_HARQ_DELAY_MS; i++) {
for ( auto & user : ue_db ) {
// if (not(user.second.get_dl_harq(i)->is_empty(0) and user.second.get_dl_harq(1))) {
for ( int i = 0 ; i < 2 * FDD_HARQ_DELAY_MS ; i + + ) {
// if (srslte_tti_interval(tti_data.tti_tx_dl, user.second.get_dl_harq(i)->get_tti()) > 49) {
if ( not ( user . second . get_dl_harq ( i ) - > is_empty ( 0 ) and user . second . get_dl_harq ( 1 ) ) ) {
// TestError("[TESTER] The pid=%d for rnti=0x%x got old.\n", user.second.get_dl_harq(i)->get_id(),
if ( srslte_tti_interval ( tti_data . tti_tx_dl , user . second . get_dl_harq ( i ) - > get_tti ( ) ) > 49 ) {
// user.first);
TESTERROR ( " [TESTER] The pid=%d for rnti=0x%x got old. \n " , user . second . get_dl_harq ( i ) - > get_id ( ) , user . first ) ;
// }
}
// }
}
// }
}
// }
}
}
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : test_sibs ( )
int sched_tester : : test_sibs ( )
{
{
uint32_t sfn = tti_data . tti_tx_dl / 10 ;
uint32_t sfn = tti_data . tti_tx_dl / 10 ;
uint32_t sf_idx = TTI_TX ( tti_data . tti_rx ) % 10 ;
uint32_t sf_idx = TTI_TX ( tti_data . tti_rx ) % 10 ;
@ -729,7 +733,7 @@ void sched_tester::test_sibs()
/* Test if SIB1 was correctly scheduled */
/* Test if SIB1 was correctly scheduled */
if ( sib1_present ) {
if ( sib1_present ) {
auto it = std : : find_if ( bc_begin , bc_end , [ ] ( bc_elem & elem ) { return elem . index = = 0 ; } ) ;
auto it = std : : find_if ( bc_begin , bc_end , [ ] ( bc_elem & elem ) { return elem . index = = 0 ; } ) ;
C ondError ( it = = bc_end , " Failed to allocate SIB1 in even sfn, sf_idx==5 \n " ) ;
C ONDERROR ( it = = bc_end , " Failed to allocate SIB1 in even sfn, sf_idx==5 \n " ) ;
}
}
/* Test if any SIB was scheduled outside of its window */
/* Test if any SIB was scheduled outside of its window */
@ -745,12 +749,13 @@ void sched_tester::test_sibs()
}
}
uint32_t win_start = sfn_start * 10 + sf ;
uint32_t win_start = sfn_start * 10 + sf ;
uint32_t win_end = win_start + cfg . si_window_ms ;
uint32_t win_end = win_start + cfg . si_window_ms ;
C ondError ( tti_data . tti_tx_dl < win_start or tti_data . tti_tx_dl > win_end ,
C ONDERROR ( tti_data . tti_tx_dl < win_start or tti_data . tti_tx_dl > win_end ,
" Scheduled SIB is outside of its SIB window \n " ) ;
" Scheduled SIB is outside of its SIB window \n " ) ;
}
}
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : test_collisions ( )
int sched_tester : : test_collisions ( )
{
{
carrier_sched : : tti_sched_result_t * tti_sched = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) ;
carrier_sched : : tti_sched_result_t * tti_sched = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) ;
@ -758,19 +763,20 @@ void sched_tester::test_collisions()
// Helper function to fill RBG mask
// Helper function to fill RBG mask
auto try_ul_fill = [ & ] ( srsenb : : ul_harq_proc : : ul_alloc_t alloc , const char * ch_str , bool strict = true ) {
auto try_ul_fill = [ & ] ( srsenb : : ul_harq_proc : : ul_alloc_t alloc , const char * ch_str , bool strict = true ) {
C ondError ( ( alloc . RB_start + alloc . L ) > cfg . cell . nof_prb ,
C ONDERROR ( ( alloc . RB_start + alloc . L ) > cfg . cell . nof_prb ,
" [TESTER] Allocated RBs (%d,%d) out of bounds \n " ,
" [TESTER] Allocated RBs (%d,%d) out of bounds \n " ,
alloc . RB_start ,
alloc . RB_start ,
alloc . RB_start + alloc . L ) ;
alloc . RB_start + alloc . L ) ;
C ondError ( alloc . L = = 0 , " [TESTER] Allocations must have at least one PRB \n " ) ;
C ONDERROR ( alloc . L = = 0 , " [TESTER] Allocations must have at least one PRB \n " ) ;
if ( strict and ul_allocs . any ( alloc . RB_start , alloc . RB_start + alloc . L ) ) {
if ( strict and ul_allocs . any ( alloc . RB_start , alloc . RB_start + alloc . L ) ) {
T estError ( " [TESTER] There is a collision of %s alloc=(%d,%d) and cumulative_mask=%s \n " ,
T ESTERROR ( " [TESTER] There is a collision of %s alloc=(%d,%d) and cumulative_mask=%s \n " ,
ch_str ,
ch_str ,
alloc . RB_start ,
alloc . RB_start ,
alloc . RB_start + alloc . L ,
alloc . RB_start + alloc . L ,
ul_allocs . to_hex ( ) . c_str ( ) ) ;
ul_allocs . to_hex ( ) . c_str ( ) ) ;
}
}
ul_allocs . fill ( alloc . RB_start , alloc . RB_start + alloc . L , true ) ;
ul_allocs . fill ( alloc . RB_start , alloc . RB_start + alloc . L , true ) ;
return SRSLTE_SUCCESS ;
} ;
} ;
/* TEST: Check if there is space for PRACH */
/* TEST: Check if there is space for PRACH */
@ -797,23 +803,23 @@ void sched_tester::test_collisions()
bool passed = false ;
bool passed = false ;
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_ul . nof_dci_elems ; + + i ) {
if ( tti_data . ul_pending_msg3 . rnti = = tti_data . sched_result_ul . pusch [ i ] . dci . rnti ) {
if ( tti_data . ul_pending_msg3 . rnti = = tti_data . sched_result_ul . pusch [ i ] . dci . rnti ) {
C ondError ( passed , " [TESTER] There can only be one msg3 allocation per UE \n " ) ;
C ONDERROR ( passed , " [TESTER] There can only be one msg3 allocation per UE \n " ) ;
C ondError ( tti_data . sched_result_ul . pusch [ i ] . needs_pdcch , " [TESTER] Msg3 allocations do not need PDCCH DCI \n " ) ;
C ONDERROR ( tti_data . sched_result_ul . pusch [ i ] . needs_pdcch , " [TESTER] Msg3 allocations do not need PDCCH DCI \n " ) ;
uint32_t L , RBstart ;
uint32_t L , RBstart ;
srslte_ra_type2_from_riv (
srslte_ra_type2_from_riv (
tti_data . sched_result_ul . pusch [ i ] . dci . type2_alloc . riv , & L , & RBstart , cfg . cell . nof_prb , cfg . cell . nof_prb ) ;
tti_data . sched_result_ul . pusch [ i ] . dci . type2_alloc . riv , & L , & RBstart , cfg . cell . nof_prb , cfg . cell . nof_prb ) ;
if ( RBstart ! = tti_data . ul_pending_msg3 . n_prb or L ! = tti_data . ul_pending_msg3 . L ) {
if ( RBstart ! = tti_data . ul_pending_msg3 . n_prb or L ! = tti_data . ul_pending_msg3 . L ) {
T estError ( " [TESTER] The Msg3 allocation does not coincide with the expected. \n " ) ;
T ESTERROR ( " [TESTER] The Msg3 allocation does not coincide with the expected. \n " ) ;
}
}
passed = true ;
passed = true ;
}
}
}
}
C ondError ( not passed , " [TESTER] No Msg3 allocation was found in the sched_result \n " ) ;
C ONDERROR ( not passed , " [TESTER] No Msg3 allocation was found in the sched_result \n " ) ;
}
}
/* TEST: check whether cumulative UL PRB masks coincide */
/* TEST: check whether cumulative UL PRB masks coincide */
if ( ul_allocs ! = tti_sched - > get_ul_mask ( ) ) {
if ( ul_allocs ! = tti_sched - > get_ul_mask ( ) ) {
T estError ( " [TESTER] The UL PRB mask and the scheduler result UL mask are not consistent \n " ) ;
T ESTERROR ( " [TESTER] The UL PRB mask and the scheduler result UL mask are not consistent \n " ) ;
}
}
srslte : : bounded_bitset < 100 , true > dl_allocs ( cfg . cell . nof_prb ) , alloc_mask ( cfg . cell . nof_prb ) ;
srslte : : bounded_bitset < 100 , true > dl_allocs ( cfg . cell . nof_prb ) , alloc_mask ( cfg . cell . nof_prb ) ;
@ -823,7 +829,7 @@ void sched_tester::test_collisions()
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_data_elems ; + + i ) {
alloc_mask . reset ( ) ;
alloc_mask . reset ( ) ;
srslte_pdsch_grant_t grant ;
srslte_pdsch_grant_t grant ;
C ondError ( srslte_ra_dl_dci_to_grant (
C ONDERROR ( srslte_ra_dl_dci_to_grant (
& cfg . cell , & dl_sf , SRSLTE_TM1 , false , & tti_data . sched_result_dl . data [ i ] . dci , & grant ) = = SRSLTE_ERROR ,
& cfg . cell , & dl_sf , SRSLTE_TM1 , false , & tti_data . sched_result_dl . data [ i ] . dci , & grant ) = = SRSLTE_ERROR ,
" Failed to decode PDSCH grant \n " ) ;
" Failed to decode PDSCH grant \n " ) ;
for ( uint32_t j = 0 ; j < alloc_mask . size ( ) ; + + j ) {
for ( uint32_t j = 0 ; j < alloc_mask . size ( ) ; + + j ) {
@ -834,7 +840,7 @@ void sched_tester::test_collisions()
}
}
}
}
if ( ( dl_allocs & alloc_mask ) . any ( ) ) {
if ( ( dl_allocs & alloc_mask ) . any ( ) ) {
T estError ( " [TESTER] Detected collision in the DL data allocation (%s intersects %s) \n " ,
T ESTERROR ( " [TESTER] Detected collision in the DL data allocation (%s intersects %s) \n " ,
dl_allocs . to_string ( ) . c_str ( ) ,
dl_allocs . to_string ( ) . c_str ( ) ,
alloc_mask . to_string ( ) . c_str ( ) ) ;
alloc_mask . to_string ( ) . c_str ( ) ) ;
}
}
@ -843,7 +849,7 @@ void sched_tester::test_collisions()
}
}
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_bc_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_bc_elems ; + + i ) {
srslte_pdsch_grant_t grant ;
srslte_pdsch_grant_t grant ;
C ondError ( srslte_ra_dl_dci_to_grant (
C ONDERROR ( srslte_ra_dl_dci_to_grant (
& cfg . cell , & dl_sf , SRSLTE_TM1 , false , & tti_data . sched_result_dl . bc [ i ] . dci , & grant ) = = SRSLTE_ERROR ,
& cfg . cell , & dl_sf , SRSLTE_TM1 , false , & tti_data . sched_result_dl . bc [ i ] . dci , & grant ) = = SRSLTE_ERROR ,
" Failed to decode PDSCH grant \n " ) ;
" Failed to decode PDSCH grant \n " ) ;
alloc_mask . reset ( ) ;
alloc_mask . reset ( ) ;
@ -853,7 +859,7 @@ void sched_tester::test_collisions()
}
}
}
}
if ( ( dl_allocs & alloc_mask ) . any ( ) ) {
if ( ( dl_allocs & alloc_mask ) . any ( ) ) {
T estError ( " [TESTER] Detected collision in the DL bc allocation (%s intersects %s) \n " ,
T ESTERROR ( " [TESTER] Detected collision in the DL bc allocation (%s intersects %s) \n " ,
dl_allocs . to_string ( ) . c_str ( ) ,
dl_allocs . to_string ( ) . c_str ( ) ,
alloc_mask . to_string ( ) . c_str ( ) ) ;
alloc_mask . to_string ( ) . c_str ( ) ) ;
}
}
@ -862,7 +868,7 @@ void sched_tester::test_collisions()
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_rar_elems ; + + i ) {
for ( uint32_t i = 0 ; i < tti_data . sched_result_dl . nof_rar_elems ; + + i ) {
alloc_mask . reset ( ) ;
alloc_mask . reset ( ) ;
srslte_pdsch_grant_t grant ;
srslte_pdsch_grant_t grant ;
C ondError ( srslte_ra_dl_dci_to_grant (
C ONDERROR ( srslte_ra_dl_dci_to_grant (
& cfg . cell , & dl_sf , SRSLTE_TM1 , false , & tti_data . sched_result_dl . rar [ i ] . dci , & grant ) = = SRSLTE_ERROR ,
& cfg . cell , & dl_sf , SRSLTE_TM1 , false , & tti_data . sched_result_dl . rar [ i ] . dci , & grant ) = = SRSLTE_ERROR ,
" Failed to decode PDSCH grant \n " ) ;
" Failed to decode PDSCH grant \n " ) ;
for ( uint32_t j = 0 ; j < alloc_mask . size ( ) ; + + j ) {
for ( uint32_t j = 0 ; j < alloc_mask . size ( ) ; + + j ) {
@ -873,7 +879,7 @@ void sched_tester::test_collisions()
}
}
}
}
if ( ( dl_allocs & alloc_mask ) . any ( ) ) {
if ( ( dl_allocs & alloc_mask ) . any ( ) ) {
T estError ( " [TESTER] Detected collision in the DL RAR allocation (%s intersects %s) \n " ,
T ESTERROR ( " [TESTER] Detected collision in the DL RAR allocation (%s intersects %s) \n " ,
dl_allocs . to_string ( ) . c_str ( ) ,
dl_allocs . to_string ( ) . c_str ( ) ,
alloc_mask . to_string ( ) . c_str ( ) ) ;
alloc_mask . to_string ( ) . c_str ( ) ) ;
}
}
@ -888,7 +894,7 @@ void sched_tester::test_collisions()
for ( uint32_t i = 0 ; i < nof_rbgs ; + + i ) {
for ( uint32_t i = 0 ; i < nof_rbgs ; + + i ) {
uint32_t lim = SRSLTE_MIN ( ( i + 1 ) * P , dl_allocs . size ( ) ) ;
uint32_t lim = SRSLTE_MIN ( ( i + 1 ) * P , dl_allocs . size ( ) ) ;
bool val = dl_allocs . any ( i * P , lim ) ;
bool val = dl_allocs . any ( i * P , lim ) ;
C ondError ( rev_alloc . any ( i * P , lim ) and val , " [TESTER] No holes can be left in an RBG \n " ) ;
C ONDERROR ( rev_alloc . any ( i * P , lim ) and val , " [TESTER] No holes can be left in an RBG \n " ) ;
if ( val ) {
if ( val ) {
rbgmask . set ( i ) ;
rbgmask . set ( i ) ;
} else {
} else {
@ -896,11 +902,12 @@ void sched_tester::test_collisions()
}
}
}
}
if ( rbgmask ! = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) - > get_dl_mask ( ) ) {
if ( rbgmask ! = carrier_schedulers [ 0 ] - > get_tti_sched ( tti_data . tti_rx ) - > get_dl_mask ( ) ) {
T estError ( " [TESTER] The UL PRB mask and the scheduler result UL mask are not consistent \n " ) ;
T ESTERROR ( " [TESTER] The UL PRB mask and the scheduler result UL mask are not consistent \n " ) ;
}
}
return SRSLTE_SUCCESS ;
}
}
void sched_tester : : ack_txs ( )
int sched_tester : : ack_txs ( )
{
{
/* check if user was removed. If so, clean respective acks */
/* check if user was removed. If so, clean respective acks */
erase_if ( to_ack ,
erase_if ( to_ack ,
@ -915,7 +922,7 @@ void sched_tester::ack_txs()
}
}
srsenb : : dl_harq_proc * h = ue_db [ ack_it . second . rnti ] . get_dl_harq ( ack_it . second . dl_harq . get_id ( ) ) ;
srsenb : : dl_harq_proc * h = ue_db [ ack_it . second . rnti ] . get_dl_harq ( ack_it . second . dl_harq . get_id ( ) ) ;
const srsenb : : dl_harq_proc & hack = ack_it . second . dl_harq ;
const srsenb : : dl_harq_proc & hack = ack_it . second . dl_harq ;
C ondError ( hack . is_empty ( ) , " [TESTER] The acked DL harq was not active \n " ) ;
C ONDERROR ( hack . is_empty ( ) , " [TESTER] The acked DL harq was not active \n " ) ;
bool ret = false ;
bool ret = false ;
for ( uint32_t tb = 0 ; tb < SRSLTE_MAX_TB ; + + tb ) {
for ( uint32_t tb = 0 ; tb < SRSLTE_MAX_TB ; + + tb ) {
@ -924,17 +931,17 @@ void sched_tester::ack_txs()
}
}
ret | = dl_ack_info ( tti_data . tti_rx , ack_it . second . rnti , tb , ack_it . second . dl_ack ) > 0 ;
ret | = dl_ack_info ( tti_data . tti_rx , ack_it . second . rnti , tb , ack_it . second . dl_ack ) > 0 ;
}
}
C ondError ( not ret , " [TESTER] The dl harq proc that was acked does not exist \n " ) ;
C ONDERROR ( not ret , " [TESTER] The dl harq proc that was acked does not exist \n " ) ;
if ( ack_it . second . dl_ack ) {
if ( ack_it . second . dl_ack ) {
C ondError ( ! h - > is_empty ( ) , " [TESTER] ACKed dl harq was not emptied \n " ) ;
C ONDERROR ( ! h - > is_empty ( ) , " [TESTER] ACKed dl harq was not emptied \n " ) ;
C ondError ( h - > has_pending_retx ( 0 , tti_data . tti_tx_dl ) , " [TESTER] ACKed dl harq still has pending retx \n " ) ;
C ONDERROR ( h - > has_pending_retx ( 0 , tti_data . tti_tx_dl ) , " [TESTER] ACKed dl harq still has pending retx \n " ) ;
log_ out . info ( " [TESTER] DL ACK tti=%u rnti=0x%x pid=%d \n " ,
log_ global . info ( " [TESTER] DL ACK tti=%u rnti=0x%x pid=%d \n " ,
tti_data . tti_rx ,
tti_data . tti_rx ,
ack_it . second . rnti ,
ack_it . second . rnti ,
ack_it . second . dl_harq . get_id ( ) ) ;
ack_it . second . dl_harq . get_id ( ) ) ;
} else {
} else {
C ondError ( h - > is_empty ( ) and hack . nof_retx ( 0 ) + 1 < hack . max_nof_retx ( ) , " [TESTER] NACKed DL harq got emptied \n " ) ;
C ONDERROR ( h - > is_empty ( ) and hack . nof_retx ( 0 ) + 1 < hack . max_nof_retx ( ) , " [TESTER] NACKed DL harq got emptied \n " ) ;
}
}
}
}
@ -945,23 +952,23 @@ void sched_tester::ack_txs()
}
}
srsenb : : ul_harq_proc * h = ue_db [ ack_it . second . rnti ] . get_ul_harq ( tti_data . tti_rx ) ;
srsenb : : ul_harq_proc * h = ue_db [ ack_it . second . rnti ] . get_ul_harq ( tti_data . tti_rx ) ;
const srsenb : : ul_harq_proc & hack = ack_it . second . ul_harq ;
const srsenb : : ul_harq_proc & hack = ack_it . second . ul_harq ;
C ondError ( h = = nullptr or h - > get_tti ( ) ! = hack . get_tti ( ) , " [TESTER] UL Harq TTI does not match the ACK TTI \n " ) ;
C ONDERROR ( h = = nullptr or h - > get_tti ( ) ! = hack . get_tti ( ) , " [TESTER] UL Harq TTI does not match the ACK TTI \n " ) ;
C ondError ( h - > is_empty ( 0 ) , " [TESTER] The acked UL harq is not active \n " ) ;
C ONDERROR ( h - > is_empty ( 0 ) , " [TESTER] The acked UL harq is not active \n " ) ;
C ondError ( hack . is_empty ( 0 ) , " [TESTER] The acked UL harq was not active \n " ) ;
C ONDERROR ( hack . is_empty ( 0 ) , " [TESTER] The acked UL harq was not active \n " ) ;
ul_crc_info ( tti_data . tti_rx , ack_it . second . rnti , ack_it . second . ack ) ;
ul_crc_info ( tti_data . tti_rx , ack_it . second . rnti , ack_it . second . ack ) ;
C ondError ( ! h - > get_pending_data ( ) , " [TESTER] UL harq lost its pending data \n " ) ;
C ONDERROR ( ! h - > get_pending_data ( ) , " [TESTER] UL harq lost its pending data \n " ) ;
C ondError ( ! h - > has_pending_ack ( ) , " [TESTER] ACK/NACKed UL harq should have a pending ACK \n " ) ;
C ONDERROR ( ! h - > has_pending_ack ( ) , " [TESTER] ACK/NACKed UL harq should have a pending ACK \n " ) ;
if ( ack_it . second . ack ) {
if ( ack_it . second . ack ) {
C ondError ( ! h - > is_empty ( ) , " [TESTER] ACKed UL harq did not get emptied \n " ) ;
C ONDERROR ( ! h - > is_empty ( ) , " [TESTER] ACKed UL harq did not get emptied \n " ) ;
C ondError ( h - > has_pending_retx ( ) , " [TESTER] ACKed UL harq still has pending retx \n " ) ;
C ONDERROR ( h - > has_pending_retx ( ) , " [TESTER] ACKed UL harq still has pending retx \n " ) ;
log_ out . info ( " [TESTER] UL ACK tti=%u rnti=0x%x pid=%d \n " , tti_data . tti_rx , ack_it . second . rnti , hack . get_id ( ) ) ;
log_ global . info ( " [TESTER] UL ACK tti=%u rnti=0x%x pid=%d \n " , tti_data . tti_rx , ack_it . second . rnti , hack . get_id ( ) ) ;
} else {
} else {
// NACK
// NACK
C ondError ( ! h - > is_empty ( ) and ! h - > has_pending_retx ( ) , " [TESTER] If NACKed, UL harq has to have pending retx \n " ) ;
C ONDERROR ( ! h - > is_empty ( ) and ! h - > has_pending_retx ( ) , " [TESTER] If NACKed, UL harq has to have pending retx \n " ) ;
C ondError ( h - > is_empty ( ) and hack . nof_retx ( 0 ) + 1 < hack . max_nof_retx ( ) ,
C ONDERROR ( h - > is_empty ( ) and hack . nof_retx ( 0 ) + 1 < hack . max_nof_retx ( ) ,
" [TESTER] Nacked UL harq did get emptied \n " ) ;
" [TESTER] Nacked UL harq did get emptied \n " ) ;
}
}
}
}
@ -980,6 +987,7 @@ void sched_tester::ack_txs()
// }
// }
// }
// }
// }
// }
return SRSLTE_SUCCESS ;
}
}
srsenb : : sched_interface : : cell_cfg_t generate_cell_cfg ( )
srsenb : : sched_interface : : cell_cfg_t generate_cell_cfg ( )
@ -1018,14 +1026,14 @@ void test_scheduler_rand(srsenb::sched_interface::cell_cfg_t cell_cfg, const sch
srsenb : : dl_metric_rr dl_metric ;
srsenb : : dl_metric_rr dl_metric ;
srsenb : : ul_metric_rr ul_metric ;
srsenb : : ul_metric_rr ul_metric ;
log_ out . set_level ( srslte : : LOG_LEVEL_INFO ) ;
log_ global . set_level ( srslte : : LOG_LEVEL_INFO ) ;
tester . sim_args = args ;
tester . sim_args = args ;
// srslte_cell_t& cell_cfg_phy = cell_cfg.cell;
// srslte_cell_t& cell_cfg_phy = cell_cfg.cell;
// srsenb::sched_interface::dl_sched_res_t& sched_result_dl = tester.tti_data.sched_result_dl;
// srsenb::sched_interface::dl_sched_res_t& sched_result_dl = tester.tti_data.sched_result_dl;
// srsenb::sched_interface::ul_sched_res_t& sched_result_ul = tester.tti_data.sched_result_ul;
// srsenb::sched_interface::ul_sched_res_t& sched_result_ul = tester.tti_data.sched_result_ul;
tester . init ( nullptr , & log_ out ) ;
tester . init ( nullptr , & log_ global ) ;
tester . set_metric ( & dl_metric , & ul_metric ) ;
tester . set_metric ( & dl_metric , & ul_metric ) ;
tester . cell_cfg ( & cell_cfg ) ;
tester . cell_cfg ( & cell_cfg ) ;
@ -1036,7 +1044,7 @@ void test_scheduler_rand(srsenb::sched_interface::cell_cfg_t cell_cfg, const sch
if ( nof_ttis > args . nof_ttis ) {
if ( nof_ttis > args . nof_ttis ) {
running = false ;
running = false ;
}
}
log_ out . step ( tti ) ;
log_ global . step ( tti ) ;
tester . run_tti ( tti ) ;
tester . run_tti ( tti ) ;
@ -1128,8 +1136,4 @@ int main()
// printf("\n\n********* New Test ***********\n");
// printf("\n\n********* New Test ***********\n");
// sim_args.P_sr = 0.05;
// sim_args.P_sr = 0.05;
// test_scheduler_rand(sim_args);
// test_scheduler_rand(sim_args);
printf ( " [TESTER] Number of assertion warnings: %u \n " , warn_counter ) ;
printf ( " [TESTER] Number of assertion errors: %u \n " , err_counter ) ;
printf ( " [TESTER] This was the chosen seed: %u \n " , seed ) ;
}
}