diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 3dbb61b5aec615544e728523304a10c0b48474fb..e1668888440c1e5ef9bf1bcc7bf49b627d53042b 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -605,6 +605,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchange add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams") add_boolean_option(FLEXRAN_AGENT_SB_IF False "enable FlexRAN agent to inteface with a SDN controller") +add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION with max 256 UE") ######################## # Include order diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index d3a13c41c93cab31eda220e1e7c5d2240b709322..2bef50313b34c73f776b2f59aca136e81c4cac88 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -43,6 +43,7 @@ conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf MSC_GEN="False" XFORMS="True" FLEXRAN_AGENT_SB_IF="True" +UE_EXPANSION="False" PRINT_STATS="False" VCD_TIMING="False" DEADLINE_SCHEDULER_FLAG_USER="False" @@ -210,6 +211,10 @@ function main() { UE=1 echo_info "Will compile UE" shift;; + --mu) + UE_EXPANSION="True" + echo_info "Will compile with UE_EXPANSION" + shift;; --UE-conf-nvram) conf_nvram_path=$(readlink -f "$1") shift 2;; @@ -528,6 +533,7 @@ function main() { if [ "$FLEXRAN_AGENT" = "1" ] ; then echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file fi + echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file @@ -689,6 +695,7 @@ function main() { if [ "$FLEXRAN_AGENT" = "1" ] ; then echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file fi + echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file @@ -772,6 +779,7 @@ function main() { if [ "$FLEXRAN_AGENT" = "1" ] ; then echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file fi + echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( T_TRACER $T_TRACER )" >> $cmake_file diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h index e16409a6a17746615f0fde7c363b50d4be4721f2..d61c4c774d4394622637c9c5c830e0ad746a69ff 100644 --- a/openair1/PHY/impl_defs_lte.h +++ b/openair1/PHY/impl_defs_lte.h @@ -636,6 +636,7 @@ typedef struct { struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[MAX_MBSFN_AREA]; + uint32_t ue_multiple_max; } LTE_DL_FRAME_PARMS; typedef enum { diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 6fd0a0411363a1d0903dad4d5a45f223aeb37183..eb1bb67849be79c9d7602660e4547283c7d446e3 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -166,6 +166,7 @@ typedef struct RrcConfigurationReq_s { long ue_TimersAndConstants_n310[MAX_NUM_CCs]; long ue_TimersAndConstants_n311[MAX_NUM_CCs]; long ue_TransmissionMode[MAX_NUM_CCs]; + long ue_multiple_max[MAX_NUM_CCs]; } RrcConfigurationReq; // UE: NAS -> RRC messages diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 9141a85d33293c55b14a0b3d514eb9398d1bcaf1..061009b7bc6fe2d92c050ad249f2eeba7b1aca37 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -438,6 +438,7 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) { int32_t ue_TimersAndConstants_n311 = 0; int32_t ue_TransmissionMode = 0; + int32_t ue_multiple_max = 0; int32_t srb1_timer_poll_retransmit = 0; int32_t srb1_timer_reordering = 0; @@ -1717,6 +1718,36 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) { RC.config_file_name, i, ue_TransmissionMode); break; } + +#ifdef UE_EXPANSION + RRC_CONFIGURATION_REQ (msg_p).ue_multiple_max[j] = ue_multiple_max; + + switch (N_RB_DL) { + case 25: + if ((ue_multiple_max < 1) || (ue_multiple_max > 5)) + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for ue_multiple_max choice: 1..5!\n", + RC.config_file_name, i, ue_multiple_max); + break; + case 50: + if ((ue_multiple_max < 1) || (ue_multiple_max > 10)) + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for ue_multiple_max choice: 1..10!\n", + RC.config_file_name, i, ue_multiple_max); + break; + case 100: + if ((ue_multiple_max < 1) || (ue_multiple_max > 20)) + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for ue_multiple_max choice: 1..20!\n", + RC.config_file_name, i, ue_multiple_max); + break; + default: + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 25,50,100 !\n", + RC.config_file_name, i, N_RB_DL); + break; + } +#endif } } char srb1path[MAX_OPTNAME_SIZE*2 + 8]; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 6a03687fab8917be9fdab8bd99f6da4451a1a039..3d3ee747d2debf56951c4f211328d994dae8b1d6 100755 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -371,6 +371,7 @@ static int DEFENBS[] = {0}; #define ENB_CONFIG_STRING_UETIMERS_N310 "ue_TimersAndConstants_n310" #define ENB_CONFIG_STRING_UETIMERS_N311 "ue_TimersAndConstants_n311" #define ENB_CONFIG_STRING_UE_TRANSMISSION_MODE "ue_TransmissionMode" +#define ENB_CONFIG_STRING_UE_MULTIPLE_MAX "ue_multiple_max" /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* component carriers configuration parameters */ @@ -444,7 +445,8 @@ static int DEFENBS[] = {0}; {ENB_CONFIG_STRING_UETIMERS_T311, NULL, 0, iptr:&ue_TimersAndConstants_t311, defintval:10000, TYPE_UINT, 0}, \ {ENB_CONFIG_STRING_UETIMERS_N310, NULL, 0, iptr:&ue_TimersAndConstants_n310, defintval:20, TYPE_UINT, 0}, \ {ENB_CONFIG_STRING_UETIMERS_N311, NULL, 0, iptr:&ue_TimersAndConstants_n311, defintval:1, TYPE_UINT, 0}, \ -{ENB_CONFIG_STRING_UE_TRANSMISSION_MODE, NULL, 0, iptr:&ue_TransmissionMode, defintval:1, TYPE_UINT, 0} \ +{ENB_CONFIG_STRING_UE_TRANSMISSION_MODE, NULL, 0, iptr:&ue_TransmissionMode, defintval:1, TYPE_UINT, 0}, \ +{ENB_CONFIG_STRING_UE_MULTIPLE_MAX, NULL, 0, iptr:&ue_multiple_max, defintval:5, TYPE_UINT, 0} \ } /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index ba02a3569419dbb1afb07b3e4bbe157abfade4ae..235256ec4f681619d6d589f1e52c660fe0c5b3dc 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -1327,6 +1327,48 @@ typedef struct { uint8_t n_adj_cells; } neigh_cell_id_t; +#ifdef UE_EXPANSION +enum SCH_UE_PRIORITY { + SCH_PRIORITY_NONE, + SCH_DL_SI, + SCH_DL_PAGING, + SCH_DL_MSG2, + SCH_DL_MSG4, + SCH_UL_PRACH, + SCH_UL_MSG3, + SCH_DL_RETRANS, + SCH_UL_RETRANS, + SCH_DL_FIRST, + SCH_UL_FIRST, + SCH_UL_INACTIVE +}; + +typedef struct { + int UE_id; + enum SCH_UE_PRIORITY ue_priority; + rnti_t rnti; + uint16_t nb_rb; +} DLSCH_UE_INFO; + +typedef struct { + uint16_t ue_num; + DLSCH_UE_INFO list[20]; +} DLSCH_UE_SELECT; + +typedef struct { + int UE_id; + enum SCH_UE_PRIORITY ue_priority; + uint8_t start_rb; + uint8_t nb_rb; + uint16_t ul_total_buffer; +} ULSCH_UE_INFO; + +typedef struct { + uint8_t ue_num; + ULSCH_UE_INFO list[20]; +} ULSCH_UE_SELECT; +#endif + #include "proto.h" /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 3e767ec516b076fa8d21d49dfca9f8f32708e1c6..4028cad58d258ed82af0b2031b6c7ed1772a1b44 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -504,6 +504,10 @@ schedule_ue_spec( } } +#ifdef UE_EXPANSION + DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]; + memset(dlsch_ue_select, 0, sizeof(dlsch_ue_select)); +#endif //weight = get_ue_weight(module_idP,UE_id); aggregation = 2; for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { @@ -533,7 +537,11 @@ schedule_ue_spec( frameP, subframeP, N_RBG, - mbsfn_flag); + mbsfn_flag +#ifdef UE_EXPANSION + , dlsch_ue_select +#endif +); stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT); @@ -545,7 +553,14 @@ schedule_ue_spec( if (mbsfn_flag[CC_id]>0) continue; +#ifdef UE_EXPANSION + for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) { + UE_id = dlsch_ue_select[CC_id].list[i].UE_id; + +#else for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { +#endif + continue_flag=0; // reset the flag to allow allocation for the remaining UEs rnti = UE_RNTI(module_idP,UE_id); eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; @@ -1319,9 +1334,11 @@ schedule_ue_spec( } // CC_id loop - +#ifndef UE_EXPANSION fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_flag); - +#else + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_flag,dlsch_ue_select); +#endif stop_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT); @@ -1334,6 +1351,9 @@ fill_DLSCH_dci( frame_t frameP, sub_frame_t subframeP, int* mbsfn_flagP +#ifdef UE_EXPANSION + , DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs] +#endif ) //------------------------------------------------------------------------------ { @@ -1370,7 +1390,12 @@ fill_DLSCH_dci( N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); // UE specific DCIs +#ifdef UE_EXPANSION + for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) { + UE_id = dlsch_ue_select[CC_id].list[i].UE_id; +#else for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { +#endif LOG_T(MAC,"CC_id %d, UE_id: %d => status %d\n",CC_id,UE_id,eNB_dlsch_info[module_idP][CC_id][UE_id].status); if (eNB_dlsch_info[module_idP][CC_id][UE_id].status == S_DL_SCHEDULED) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 1fcd07c1d3f889d80827c4da6a0afb4ada035dad..5b2f652c4f03646b71370af257c699b72e25c683 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -731,7 +731,10 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { - uint16_t first_rb[MAX_NUM_CCs],i; +#ifndef UE_EXPANSION + uint16_t first_rb[MAX_NUM_CCs]; +#endif + uint16_t i; int CC_id; eNB_MAC_INST *eNB=RC.mac[module_idP]; COMMON_channels_t *cc; @@ -793,6 +796,8 @@ void schedule_ulsch(module_id_t module_idP, break; } } + +#ifndef UE_EXPANSION for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { @@ -828,10 +833,54 @@ void schedule_ulsch(module_id_t module_idP, } schedule_ulsch_rnti(module_idP, frameP, subframeP, sched_subframe,first_rb); +#else + ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]; + memset(ulsch_ue_select, 0, sizeof(ulsch_ue_select)); + + LTE_DL_FRAME_PARMS *frame_parms ; + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + cc = &eNB->common_channels[CC_id]; + frame_parms= &RC.eNB[module_idP][CC_id]->frame_parms; + // output of scheduling, the UE numbers in RBs, where it is in the code??? + // check if RA (Msg3) is active in this subframeP, if so skip the PRBs used for Msg3 + // Msg3 is using 1 PRB so we need to increase first_rb accordingly + // not sure about the break (can there be more than 1 active RA procedure?) + for (i=0; i<NB_RA_PROC_MAX; i++) { + if ((cc->RA_template[i].RA_active == TRUE) && + (cc->RA_template[i].generate_rar == 0) && + (cc->RA_template[i].generate_Msg4 == 0) && + (cc->RA_template[i].wait_ack_Msg4 == 0) && + (cc->RA_template[i].Msg3_subframe == sched_subframe)) { + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_MSG3; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = 1; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = 1; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = -1; + ulsch_ue_select[CC_id].ue_num++; + break; + } + } + //PRACH + if (is_prach_subframe(frame_parms,frameP,subframeP)==1) { + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_PRACH; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = get_prach_prb_offset( + frame_parms, + frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, + frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, + 0,//tdd_mapindex + frameP); //Nf + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = 6; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = -1; + ulsch_ue_select[CC_id].ue_num++; + } + } + + schedule_ulsch_rnti(module_idP, frameP, subframeP, sched_subframe,ulsch_ue_select); +#endif stop_meas(&eNB->schedule_ulsch); } - +#ifndef UE_EXPANSION void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, @@ -1242,3 +1291,382 @@ abort(); } // loop over UE_id } // loop of CC_id } +#else +void schedule_ulsch_rnti(module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + unsigned char sched_subframeP, + ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]) +{ + int16_t UE_id; + uint8_t aggregation = 2; + uint16_t first_rb[MAX_NUM_CCs]; + uint8_t ULSCH_first_end; + rnti_t rnti = -1; + uint8_t round = 0; + uint8_t harq_pid = 0; + uint8_t status = 0; + uint8_t rb_table_index = -1; + uint32_t cqi_req,cshift,ndi,tpc; + int32_t normalized_rx_power; + int32_t target_rx_power=-90; + static int32_t tpc_accumulated=0; + int CC_id,ulsch_ue_num; + int N_RB_UL; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + UE_list_t *UE_list=&eNB->UE_list; + UE_TEMPLATE *UE_template; + UE_sched_ctrl *UE_sched_ctrl; + int sched_frame=frameP; + int rvidx_tab[4] = {0,2,3,1}; + + if (sched_subframeP < subframeP) sched_frame++; + + nfapi_hi_dci0_request_body_t *hi_dci0_req = &eNB->HI_DCI0_req[module_idP].hi_dci0_request_body; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; + + nfapi_ul_config_request_body_t *ul_req_tmp = &eNB->UL_req_tmp[module_idP][sched_subframeP].ul_config_request_body; + + LOG_D(MAC,"entering ulsch preprocesor\n"); + ulsch_scheduler_pre_processor(module_idP, + frameP, + subframeP, + ulsch_ue_select); + + LOG_D(MAC,"exiting ulsch preprocesor\n"); + + eNB->HI_DCI0_req[module_idP].sfn_sf = (frameP<<4)+subframeP; + + // loop over all active UEs + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + //leave out first RB for PUCCH + first_rb[CC_id] = 1; + ULSCH_first_end = 0; + cc = &eNB->common_channels[CC_id]; + for ( ulsch_ue_num = 0; ulsch_ue_num < ulsch_ue_select[CC_id].ue_num; ulsch_ue_num++ ) { + // This is the actual CC_id in the list + N_RB_UL = to_prb(cc->ul_Bandwidth); + UE_id = ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id; + /* be sure that there are some free RBs */ + if (first_rb[CC_id] >= N_RB_UL-1) { + LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", + module_idP,frameP,subframeP,UE_id,rnti,CC_id); + break; + } + //MSG3 + if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_MSG3) { + first_rb[CC_id] ++; + continue; + } + //PRACH + if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_PRACH) { + first_rb[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb+ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + continue; + } + + UE_template = &UE_list->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + harq_pid = subframe2harqpid(cc,sched_frame,sched_subframeP); + rnti = UE_RNTI(CC_id,UE_id); + LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n", + module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, aggregation,N_RB_UL); + + RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->ul_total_buffer; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP]); + + status = mac_eNB_get_rrc_status(module_idP,rnti); + if (status < RRC_CONNECTED) + cqi_req = 0; + else if (UE_sched_ctrl->cqi_req_timer>30) { + cqi_req = 1; + UE_sched_ctrl->cqi_req_timer=0; + } + else + cqi_req = 0; + + //power control + //compute the expected ULSCH RX power (for the stats) + + // this is the normalized RX power and this should be constant (regardless of mcs + normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id]; + target_rx_power = 178; + + // this assumes accumulated tpc + // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out + int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe; + if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case + ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around + { + UE_template->pusch_tpc_tx_frame=frameP; + UE_template->pusch_tpc_tx_subframe=subframeP; + if (normalized_rx_power>(target_rx_power+4)) { + tpc = 0; //-1 + tpc_accumulated--; + } else if (normalized_rx_power<(target_rx_power-4)) { + tpc = 2; //+1 + tpc_accumulated++; + } else { + tpc = 1; //0 + } + } else { + tpc = 1; //0 + } + + if (tpc!=1) { + LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", + module_idP,frameP,subframeP,harq_pid,tpc, + tpc_accumulated,normalized_rx_power,target_rx_power); + } + // new transmission + if ((ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST) || + (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE)) { + LOG_D(MAC,"[eNB %d][PUSCH %d] Frame %d subframe %d Scheduling UE %d/%x (SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n", + module_idP,harq_pid,frameP,subframeP,UE_id,rnti,UE_template->ul_SR, + UE_sched_ctrl->ul_inactivity_timer, + UE_sched_ctrl->ul_failure_timer, + UE_sched_ctrl->cqi_req_timer); + + ndi = 1-UE_template->oldNDI_UL[harq_pid]; + UE_template->oldNDI_UL[harq_pid]=ndi; + UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power; + UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power; + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; + UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS + if (UE_template->pre_allocated_rb_table_index_ul >=0) { + rb_table_index=UE_template->pre_allocated_rb_table_index_ul; + } else { + UE_template->mcs_UL[harq_pid]=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs); + rb_table_index=5; // for PHR + } + + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; + + UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],rb_table[rb_table_index]); + UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index]; + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; + + T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), + T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi)); + + if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED) + LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n", + module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid], + first_rb[CC_id],rb_table[rb_table_index], + rb_table_index,UE_template->TBS_UL[harq_pid],harq_pid); + + // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB) + //store for possible retransmission + UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; + UE_template->first_rb_ul[harq_pid] = first_rb[CC_id]; + + UE_sched_ctrl->ul_scheduled |= (1<<harq_pid); + if (UE_id == UE_list->head) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled); + + // adjust total UL buffer status by TBS, wait for UL sdus to do final update + LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,UE_template->TBS_UL[harq_pid]); + if (UE_template->ul_total_buffer > UE_template->TBS_UL[harq_pid]) + UE_template->ul_total_buffer -= UE_template->TBS_UL[harq_pid]; + else + UE_template->ul_total_buffer = 0; + LOG_D(MAC,"ul_total_buffer, new %d\n", UE_template->ul_total_buffer); + // Cyclic shift for DM RS + cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) + // save it for a potential retransmission + UE_template->cshift[harq_pid] = cshift; + + hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci+eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi]; + memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template->DAI_ul[sched_subframeP]; + + eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci++; + + LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP); + + // Add UL_config PDUs + fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], + cqi_req, + cc, + UE_template->physicalConfigDedicated, + get_tmode(module_idP,CC_id,UE_id), + eNB->ul_handle, + rnti, + first_rb[CC_id], // resource_block_start + rb_table[rb_table_index], // number_of_resource_blocks + UE_template->mcs_UL[harq_pid], + cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + ndi, // new_data_indication + 0, // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + get_TBS_UL(UE_template->mcs_UL[harq_pid], + rb_table[rb_table_index]) + ); +#ifdef Rel14 + if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation + fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], + UE_template->rach_resource_type>2 ? 2 : 1, + 1, //total_number_of_repetitions + 1, //repetition_number + (frameP*10)+subframeP); + } +#endif + ul_req_tmp->number_of_pdus++; + eNB->ul_handle++; + + add_ue_ulsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_UL_SCHEDULED); + + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id); + + // increment first rb for next UE allocation + first_rb[CC_id]+=rb_table[rb_table_index]; + if(ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST) { + if(ulsch_ue_select[CC_id].list[ulsch_ue_num].ul_total_buffer > 0){ + if (UE_template->ul_total_buffer > UE_template->TBS_UL[harq_pid]) + UE_template->ul_total_buffer -= UE_template->TBS_UL[harq_pid]; + else + UE_template->ul_total_buffer = 0; + } else { + UE_template->ul_SR = 0; + } + } + if((ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE) && (ULSCH_first_end == 0)) { + ULSCH_first_end = 1; + last_ulsch_ue_id[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num-1].UE_id; + } + if((ulsch_ue_num == ulsch_ue_select[CC_id].ue_num-1) && (ULSCH_first_end == 0)) { + ULSCH_first_end = 1; + last_ulsch_ue_id[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id; + } + } + else if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_RETRANS) { // round > 0 => retransmission + T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), + T_INT(round)); + + round = UE_sched_ctrl->round_UL[CC_id][harq_pid]; + UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power; + UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power; + + UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb); + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; + + if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED) + LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n", + module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid], + first_rb[CC_id],rb_table[rb_table_index], + rb_table_index,UE_template->TBS_UL[harq_pid],harq_pid); + + // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB) + //store for possible retransmission + UE_template->nb_rb_ul[harq_pid] = ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + UE_template->first_rb_ul[harq_pid] = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb; + + UE_sched_ctrl->ul_scheduled |= (1<<harq_pid); + // Cyclic shift for DM RS + cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) + + hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci+eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi]; + memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = UE_template->oldNDI_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template->DAI_ul[sched_subframeP]; + + eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci++; + // fill in NAK information + hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi]; + memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_hi_pdu); + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = UE_template->cshift[harq_pid]; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0; + hi_dci0_req->number_of_hi++; + + LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, round %d)\n", + module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid], + ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb, ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb, + UE_template->TBS_UL[harq_pid],round); + // Add UL_config PDUs + LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP); + fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], + cqi_req, + cc, + UE_template->physicalConfigDedicated, + get_tmode(module_idP,CC_id,UE_id), + eNB->ul_handle, + rnti, + ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb, // resource_block_start + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb, // number_of_resource_blocks + UE_template->mcs_UL[harq_pid], + cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + UE_template->oldNDI_UL[harq_pid], // new_data_indication + rvidx_tab[round&3], // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + get_TBS_UL(UE_template->mcs_UL[harq_pid], + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb) + ); +#ifdef Rel14 + if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation + fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], + UE_template->rach_resource_type>2 ? 2 : 1, + 1, //total_number_of_repetitions + 1, //repetition_number + (frameP*10)+subframeP); + } +#endif + ul_req_tmp->number_of_pdus++; + eNB->ul_handle++; + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0(round >0)\n", module_idP,CC_id,frameP,subframeP,UE_id); + + // increment first rb for next UE allocation + first_rb[CC_id]+=ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + } + } // loop over UE_id + } // loop of CC_id + +} +#endif diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h index f192cd7e127ef01b1ea66adc14c03c4d2217f7a3..e3f289f7107f79479a3046d48e6fcdf76b87f55d 100644 --- a/openair2/LAYER2/MAC/extern.h +++ b/openair2/LAYER2/MAC/extern.h @@ -101,6 +101,11 @@ extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1; extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E; +#ifdef UE_EXPANSION +extern int last_dlsch_ue_id[MAX_NUM_CCs]; +extern int last_ulsch_ue_id[MAX_NUM_CCs]; +#endif + #endif //DEF_H diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 612f64fe61c2f991fc24944d1debe28da7e0aafb..fecf8b111cc0a310c66a3f936f9a486c18168a04 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -481,7 +481,365 @@ void sort_UEs (module_id_t Mod_idP, #endif } +#ifdef UE_EXPANSION +void dlsch_scheduler_pre_ue_select( + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + int* mbsfn_flag, + uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]) +{ + uint8_t CC_id; + int UE_id; +// uint16_t nb_rb; + unsigned char round = 0; + unsigned char harq_pid = 0; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = eNB->common_channels; + UE_list_t *UE_list = &eNB->UE_list; + UE_sched_ctrl *ue_sched_ctl; + rnti_t rnti; + unsigned char aggregation; + // int i; + // int N_RB_DL[MAX_NUM_CCs]; + uint16_t used_dlsch_rbs_num[MAX_NUM_CCs] = {0}; + uint16_t available_dlsch_rbs_num[MAX_NUM_CCs] = {0}; + uint16_t dl_ue_max_num[MAX_NUM_CCs] = {0}; + uint16_t dlsch_ue_max_num[MAX_NUM_CCs] = {0}; + int format_flag; + nfapi_dl_config_request_body_t *DL_req; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + uint16_t saved_dlsch_dci[MAX_NUM_CCs] = {0}; + int continue_flag = 0; + int old_last_dlsch_ue_id[MAX_NUM_CCs]; + // Initialization + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + // get maximum UE number of DLSCH + dl_ue_max_num[CC_id] = NUMBER_OF_UE_MAX; + dlsch_ue_max_num[CC_id] = (uint16_t)RC.rrc[module_idP]->configuration.ue_multiple_max[CC_id]; + + // save origin DL PDU number + DL_req = &eNB->DL_req[CC_id].dl_config_request_body; + saved_dlsch_dci[CC_id] = DL_req->number_pdu; + // set available_dlsch_rbs + available_dlsch_rbs_num[CC_id] = eNB->eNB_stats[CC_id].available_prbs; + + // get last DLSCH ue_id + old_last_dlsch_ue_id[CC_id] = last_dlsch_ue_id[CC_id]; + } + + // Insert DLSCH(retransmission) UE into selected UE list + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + if (mbsfn_flag[CC_id]>0) { + continue; + } + + DL_req = &eNB->DL_req[CC_id].dl_config_request_body; + for (UE_id = 0; UE_id < dl_ue_max_num[CC_id] /*NUMBER_OF_UE_MAX*/; UE_id++) { + if (UE_list->active[UE_id] == FALSE) { + continue; + } + + rnti = UE_RNTI(module_idP, UE_id); + if (rnti == NOT_A_RNTI) { + continue; + } + + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (ue_sched_ctl->ul_out_of_sync == 1) { + continue; + } + if (nb_rbs_required[CC_id][UE_id] == 0) { + continue; + } + + if (cc[CC_id].tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; + else harq_pid = ((frameP*10)+subframeP)&7; + + round = ue_sched_ctl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP, CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format1); + break; + case 3: + aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format2A); + break; + default: + LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id)); + aggregation = 2; + } + format_flag = 1; + if (!CCE_allocation_infeasible(module_idP, + CC_id, + format_flag, + subframeP, + aggregation, + rnti)) { + dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; + DL_req->number_pdu++; + + nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + // Insert DLSCH(retransmission) UE into selected UE list + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_RETRANS; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].rnti = rnti; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].nb_rb = nb_rbs_required[CC_id][UE_id]; + dlsch_ue_select[CC_id].ue_num++; + used_dlsch_rbs_num[CC_id] += nb_rbs_required[CC_id][UE_id]; + if (dlsch_ue_select[CC_id].ue_num == dlsch_ue_max_num[CC_id]) { + break; + } + if (used_dlsch_rbs_num[CC_id] > available_dlsch_rbs_num[CC_id]) { + dlsch_ue_select[CC_id].ue_num--; // roll back + break; + } + } else { + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai (subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_list); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); + } + + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_NONE); + } + } + } + } + + // Insert DLSCH(first transmission) UE into selected UE list (UE_id > last_dlsch_ue_id[CC_id]) + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + if (mbsfn_flag[CC_id]>0) { + continue; + } + + if (dlsch_ue_select[CC_id].ue_num < dlsch_ue_max_num[CC_id] && + used_dlsch_rbs_num[CC_id] < available_dlsch_rbs_num[CC_id]) { + DL_req = &eNB->DL_req[CC_id].dl_config_request_body; + for (UE_id = (old_last_dlsch_ue_id[CC_id]+1); UE_id < dl_ue_max_num[CC_id]; UE_id++) { + if (dlsch_ue_select[CC_id].ue_num >= dlsch_ue_max_num[CC_id]) { + break; + } + + if (UE_list->active[UE_id] == FALSE) { + continue; + } + + rnti = UE_RNTI(module_idP,UE_id); + if (rnti == NOT_A_RNTI) + continue; + + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (ue_sched_ctl->ul_out_of_sync == 1) { + continue; + } + + continue_flag = 0; + if (nb_rbs_required[CC_id][UE_id] == 0) { + continue_flag = 1; + } else { + if (cc[CC_id].tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; + else harq_pid = ((frameP*10)+subframeP)&7; + + round = ue_sched_ctl->round[CC_id][harq_pid]; + if (round == 8) { + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP, CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format1); + break; + case 3: + aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format2A); + break; + default: + LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id)); + aggregation = 2; + } + format_flag = 1; + if (!CCE_allocation_infeasible(module_idP, + CC_id, + format_flag, + subframeP, + aggregation, + rnti)) { + dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; + DL_req->number_pdu++; + + // Insert DLSCH(first transmission) UE into selected selected UE list + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_FIRST; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].nb_rb = nb_rbs_required[CC_id][UE_id]; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].rnti = rnti; + dlsch_ue_select[CC_id].ue_num++; + last_dlsch_ue_id[CC_id] = UE_id; + } else { + continue_flag = 1; + } + } + } + + if (continue_flag == 1) { + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai (subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_list); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); + } + + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_NONE); + } + } + } + } + + // Insert DLSCH(first transmission) UE into selected UE list (UE_id <= last_dlsch_ue_id[CC_id]) + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + if (mbsfn_flag[CC_id]>0) { + continue; + } + + if (dlsch_ue_select[CC_id].ue_num < dlsch_ue_max_num[CC_id] && + used_dlsch_rbs_num[CC_id] < available_dlsch_rbs_num[CC_id]) { + DL_req = &eNB->DL_req[CC_id].dl_config_request_body; + for (UE_id = 0; UE_id <= old_last_dlsch_ue_id[CC_id]; UE_id++) { + if (dlsch_ue_select[CC_id].ue_num >= dlsch_ue_max_num[CC_id]) { + break; + } + + if (UE_list->active[UE_id] == FALSE) { + continue; + } + + rnti = UE_RNTI(module_idP,UE_id); + if (rnti == NOT_A_RNTI) + continue; + + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (ue_sched_ctl->ul_out_of_sync == 1) { + continue; + } + + continue_flag = 0; + if (nb_rbs_required[CC_id][UE_id] == 0) { + continue_flag = 1; + } else { + if (cc[CC_id].tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; + else harq_pid = ((frameP*10)+subframeP)&7; + + round = ue_sched_ctl->round[CC_id][harq_pid]; + if (round == 8) { + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP, CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format1); + break; + case 3: + aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format2A); + break; + default: + LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id)); + aggregation = 2; + } + format_flag = 1; + if (!CCE_allocation_infeasible(module_idP, + CC_id, + format_flag, + subframeP, + aggregation, + rnti)) { + dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; + DL_req->number_pdu++; + + // Insert DLSCH(first transmission) UE into selected selected UE list + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_FIRST; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].nb_rb = nb_rbs_required[CC_id][UE_id]; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id; + dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].rnti = rnti; + dlsch_ue_select[CC_id].ue_num++; + last_dlsch_ue_id[CC_id] = UE_id; + } else { + continue_flag = 1; + } + } + } + + if (continue_flag == 1) { + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai (subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_list); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); + } + + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_NONE); + } + } + } + } + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + DL_req = &eNB->DL_req[CC_id].dl_config_request_body; + DL_req->number_pdu = saved_dlsch_dci[CC_id]; + } +} + + + +#endif // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done @@ -489,20 +847,32 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP, int N_RBG[MAX_NUM_CCs], - int *mbsfn_flag) + int *mbsfn_flag +#ifdef UE_EXPANSION + , DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs] +#endif +) { +#ifndef UE_EXPANSION unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,round=0,total_ue_count; + uint16_t ii; + uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t r1=0; +// int rrc_status = RRC_IDLE; +#else + unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,Round=0; +#endif unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; int UE_id, i; - uint16_t ii,j; + uint16_t j; uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; +// uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; uint16_t average_rbs_per_user[MAX_NUM_CCs] = {0}; rnti_t rnti; int min_rb_unit[MAX_NUM_CCs]; - uint16_t r1=0; +// uint16_t r1=0; uint8_t CC_id; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; @@ -523,6 +893,11 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, UE_sched_ctrl *ue_sched_ctl1,*ue_sched_ctl2; #endif +#ifdef UE_EXPANSION + uint16_t temp_total_rbs_count; + unsigned char temp_total_ue_count; +#endif + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (mbsfn_flag[CC_id]>0) // If this CC is allocated for MBSFN skip it here @@ -564,13 +939,89 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit); - +#ifdef UE_EXPANSION + dlsch_scheduler_pre_ue_select(Mod_id,frameP,subframeP, mbsfn_flag,nb_rbs_required,dlsch_ue_select); +#else // Sorts the user on the basis of dlsch logical channel buffer and CQI sort_UEs (Mod_id,frameP,subframeP); total_ue_count =0; +#endif + + + //total_ue_count =0; + +#ifdef UE_EXPANSION + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + average_rbs_per_user[CC_id] = 0; + cc = &RC.mac[Mod_id]->common_channels[CC_id]; + // Get total available RBS count and total UE count + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + temp_total_rbs_count = RC.mac[Mod_id]->eNB_stats[CC_id].available_prbs; + temp_total_ue_count = dlsch_ue_select[CC_id].ue_num; + + for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) { + UE_id = dlsch_ue_select[CC_id].list[i].UE_id; + nb_rbs_required[CC_id][UE_id] = dlsch_ue_select[CC_id].list[i].nb_rb; + + if( (min_rb_unit[CC_id] * temp_total_ue_count) <= temp_total_rbs_count ) { + //average_rbs_per_user[CC_id] = ((uint16_t)round((double)temp_total_rbs_count/(double)(temp_total_ue_count*min_rb_unit[CC_id])))*min_rb_unit[CC_id]; + average_rbs_per_user[CC_id] = (uint16_t)round((double)temp_total_rbs_count/(double)temp_total_ue_count); + } else { + average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE + } + + rnti = dlsch_ue_select[CC_id].list[i].rnti; + + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; + else harq_pid = ((frameP*10)+subframeP)&7; + Round = ue_sched_ctl->round[CC_id][harq_pid]; + + //if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round > 0) { + if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || Round != 8) { // FIXME + nb_rbs_required_remaining[CC_id][UE_id] = dlsch_ue_select[CC_id].list[i].nb_rb; + } else { + nb_rbs_required_remaining[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], dlsch_ue_select[CC_id].list[i].nb_rb); + } + + transmission_mode = get_tmode(Mod_id,CC_id,UE_id); + + LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n "); + dlsch_scheduler_pre_processor_allocate (Mod_id, + UE_id, + CC_id, + N_RBG[CC_id], + transmission_mode, + min_rb_unit[CC_id], + N_RB_DL, + nb_rbs_required, + nb_rbs_required_remaining, + rballoc_sub, + MIMO_mode_indicator); + if (ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) { + last_dlsch_ue_id[CC_id] = dlsch_ue_select[CC_id].list[i-1].UE_id; + dlsch_ue_select[CC_id].ue_num = i; + break; + } + + temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id]; + temp_total_ue_count--; + + if (temp_total_rbs_count == 0) { + last_dlsch_ue_id[CC_id] = UE_id; + dlsch_ue_select[CC_id].ue_num = i+1; + break; + } +#ifdef TM5 + // TODO: data channel TM5: to be re-visited +#endif + } + } + +#else // loop over all active UEs for (i=UE_list->head; i>=0; i=UE_list->next[i]) { @@ -802,6 +1253,7 @@ if (nb_rbs_required_remaining[CC_id][i]<0) abort(); } } // total_ue_count } // end of for for r1 and r2 +#endif // end of #ifndef UE_EXPANSION #ifdef TM5 @@ -838,13 +1290,19 @@ if (nb_rbs_required_remaining[CC_id][i]<0) abort(); } #endif - +#ifdef UE_EXPANSION + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) { + UE_id = dlsch_ue_select[CC_id].list[i].UE_id; + ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id]; +#else for(i=UE_list->head; i>=0; i=UE_list->next[i]) { UE_id = i; ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { CC_id = UE_list->ordered_CCids[ii][UE_id]; +#endif //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) { @@ -1082,7 +1540,7 @@ void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, /// ULSCH PRE_PROCESSOR - +#ifndef UE_EXPANSION void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, @@ -1259,7 +1717,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } } } - +#endif void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP, uint16_t *first_rb) { @@ -1532,3 +1990,416 @@ void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP) } #endif } + +#ifdef UE_EXPANSION +int ulsch_cc_id_end(uint8_t *cc_id_flag ) +{ + int end_flag = 1; + for (int CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) { + if (cc_id_flag[CC_id]==0) { + end_flag = 0; + break; + } + } + return end_flag; +} + +void ulsch_scheduler_pre_ue_select( + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]) +{ + eNB_MAC_INST *eNB=RC.mac[module_idP]; + COMMON_channels_t *cc; + int CC_id,UE_id; + int ret; + uint8_t ue_first_num[MAX_NUM_CCs]; + uint8_t first_ue_total[MAX_NUM_CCs][20]; + uint8_t first_ue_id[MAX_NUM_CCs][20]; + uint8_t ul_inactivity_num[MAX_NUM_CCs]; + uint8_t ul_inactivity_id[MAX_NUM_CCs][20]; +// LTE_DL_FRAME_PARMS *frame_parms; + uint8_t ulsch_ue_max_num[MAX_NUM_CCs]; + uint16_t saved_ulsch_dci[MAX_NUM_CCs]; + rnti_t rnti; + UE_sched_ctrl *UE_sched_ctl = NULL; + uint8_t cc_id_flag[MAX_NUM_CCs]; + uint8_t harq_pid = 0,round = 0; + UE_list_t *UE_list= &eNB->UE_list; + + + uint8_t aggregation = 4; + int format_flag; + nfapi_hi_dci0_request_body_t *HI_DCI0_req; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; + + + for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) { + //save ulsch dci number + saved_ulsch_dci[CC_id] = eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci; + // maximum multiplicity number + ulsch_ue_max_num[CC_id] =RC.rrc[module_idP]->configuration.ue_multiple_max[CC_id]; + + cc_id_flag[CC_id] = 0; + ue_first_num[CC_id] = 0; + ul_inactivity_num[CC_id] = 0; + + } + // UE round >0 + for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { + rnti = UE_RNTI(module_idP,UE_id); + CC_id = UE_PCCID(module_idP,UE_id); + if (rnti ==NOT_A_RNTI) + continue; + + if (UE_list->UE_template[CC_id][UE_id].configured == FALSE) + continue; + + if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + continue; + + // UL DCI + HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; + if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { + cc_id_flag[CC_id] = 1; + HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id]; + ret = ulsch_cc_id_end(cc_id_flag); + if ( ret == 0 ) { + continue; + } + if ( ret == 1 ) { + return; + } + } + + cc = &eNB->common_channels[CC_id]; + //harq_pid + harq_pid = subframe2harqpid(cc,frameP,subframeP); + //round + round = UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; + + if ( round > 0 ) { + hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; + format_flag = 2; + if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { + cc_id_flag[CC_id] = 1; + continue; + } else { + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + HI_DCI0_req->number_of_dci++; + + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_RETRANS; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = eNB->UE_list.UE_template[CC_id][UE_id].first_rb_ul[harq_pid]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = eNB->UE_list.UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id; + ulsch_ue_select[CC_id].ue_num++; + continue; + } + } + // + if ( UE_id > last_ulsch_ue_id[CC_id] && ((ulsch_ue_select[CC_id].ue_num+ue_first_num[CC_id]) < ulsch_ue_max_num[CC_id]) ) { + if ( UE_list->UE_template[CC_id][UE_id].ul_total_buffer > 0 ) { + first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id; + first_ue_total[CC_id][ue_first_num[CC_id]] = UE_list->UE_template[CC_id][UE_id].ul_total_buffer; + ue_first_num[CC_id]++; + continue; + } + if ( UE_list->UE_template[CC_id][UE_id].ul_SR > 0 ) { + first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id; + first_ue_total[CC_id] [ue_first_num[CC_id]] = 0; + ue_first_num[CC_id]++; + continue; + } + if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id] ) < ulsch_ue_max_num[CC_id] ) { + UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || + ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) { + ul_inactivity_id[CC_id][ul_inactivity_num[CC_id]]= UE_id; + ul_inactivity_num[CC_id] ++; + continue; + } + } + } + + } + + for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) { + HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; + for ( int temp = 0; temp < ue_first_num[CC_id]; temp++ ) { + if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { + cc_id_flag[CC_id] = 1; + HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id]; + break; + } + + hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; + format_flag = 2; + rnti = UE_RNTI(module_idP,UE_id); + if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { + cc_id_flag[CC_id] = 1; + break; + } else { + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + HI_DCI0_req->number_of_dci++; + + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_FIRST; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = first_ue_total[CC_id][temp]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = first_ue_id[CC_id][temp]; + ulsch_ue_select[CC_id].ue_num++; + } + } + } + + for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { + rnti = UE_RNTI(module_idP,UE_id); + CC_id = UE_PCCID(module_idP,UE_id); + if (rnti ==NOT_A_RNTI) + continue; + + if (UE_list->UE_template[CC_id][UE_id].configured == FALSE) + continue; + + if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + continue; + + if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { + cc_id_flag[CC_id] = 1; + HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id]; + ret = ulsch_cc_id_end(cc_id_flag); + if ( ret == 0 ) { + continue; + } + if ( ret == 1 ) { + return; + } + } + + if (UE_id > last_ulsch_ue_id[CC_id]) + continue; + + HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; + //SR BSR + if ( (UE_list->UE_template[CC_id][UE_id].ul_total_buffer > 0) || (UE_list->UE_template[CC_id][UE_id].ul_SR > 0) ) { + hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; + format_flag = 2; + if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { + cc_id_flag[CC_id] = 1; + continue; + } else { + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + HI_DCI0_req->number_of_dci++; + + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_FIRST; + if(UE_list->UE_template[CC_id][UE_id].ul_total_buffer > 0) + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = UE_list->UE_template[CC_id][UE_id].ul_total_buffer; + else if(UE_list->UE_template[CC_id][UE_id].ul_SR > 0) + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = 0; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id; + ulsch_ue_select[CC_id].ue_num++; + continue; + } + } + //inactivity UE + if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id]) < ulsch_ue_max_num[CC_id] ) { + UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || + ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) { + ul_inactivity_id[CC_id][ul_inactivity_num[CC_id]]= UE_id; + ul_inactivity_num[CC_id]++; + continue; + } + } + } + + for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) { + HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; + for ( int temp = 0; temp < ue_first_num[CC_id]; temp++ ) { + if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { + HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; + cc_id_flag[CC_id] = 1; + break; + } + + hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; + format_flag = 2; + rnti = UE_RNTI(module_idP,UE_id); + if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { + cc_id_flag[CC_id] = 1; + return; + } else { + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + HI_DCI0_req->number_of_dci++; + + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_INACTIVE; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = 0; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = ul_inactivity_id[CC_id][temp]; + ulsch_ue_select[CC_id].ue_num++; + } + } + HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id]; + } + return; +} + +uint8_t find_rb_table_index(uint8_t average_rbs) +{ + int i; + for ( i = 0; i < 34; i++ ) { + if ( rb_table[i] > average_rbs ) { + return (i-1); + } + } + return i; +} + +void ulsch_scheduler_pre_processor(module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]) +{ + int CC_id,ulsch_ue_num; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list= &eNB->UE_list; + UE_TEMPLATE *UE_template = NULL; + LTE_DL_FRAME_PARMS *frame_parms = NULL; + uint8_t ue_num_temp; + uint8_t total_rbs=0; + uint8_t average_rbs; + uint16_t first_rb[MAX_NUM_CCs]; + uint8_t mcs; + uint8_t rb_table_index; + uint32_t tbs; + int16_t tx_power; + int UE_id; + rnti_t rnti; + LOG_D(MAC,"In ulsch_preprocessor: ulsch ue select\n"); + //ue select + ulsch_scheduler_pre_ue_select(module_idP,frameP,subframeP,ulsch_ue_select); + + // MCS and RB assgin + for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) { + frame_parms = &(RC.eNB[module_idP][CC_id]->frame_parms); + first_rb[CC_id] = 1; + ue_num_temp = ulsch_ue_select[CC_id].ue_num; + for ( ulsch_ue_num = 0; ulsch_ue_num < ulsch_ue_select[CC_id].ue_num; ulsch_ue_num++ ) { + + UE_id = ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id; + rnti = UE_RNTI(CC_id,UE_id); + if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_MSG3) { + first_rb[CC_id] ++; + ue_num_temp--; + continue; + } + if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_PRACH) { + first_rb[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb+ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + ue_num_temp--; + continue; + } + + if ( first_rb[CC_id] >= frame_parms->N_RB_UL-1 ) { + LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", + module_idP,frameP,subframeP,UE_id,rnti,CC_id); + break; + } + // calculate the average rb ( remain UE) + total_rbs = frame_parms->N_RB_UL-1-first_rb[CC_id]; + average_rbs = (int)round((double)total_rbs/(double)ue_num_temp); + if ( average_rbs < 3 ) { + ue_num_temp--; + ulsch_ue_num--; + ulsch_ue_select[CC_id].ue_num--; + continue; + } + if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_RETRANS ) { + if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb <= average_rbs ) { + // assigne RBS(nb_rb) + ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb = first_rb[CC_id]; + first_rb[CC_id] = first_rb[CC_id] + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + } + if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb > average_rbs ) { + if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb <= total_rbs ) { + // assigne RBS(average_rbs) + ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb = first_rb[CC_id]; + first_rb[CC_id] = first_rb[CC_id] + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb; + } else { + // assigne RBS(remain rbs) + ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb = first_rb[CC_id]; + first_rb[CC_id] = first_rb[CC_id] + total_rbs; + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb = first_rb[CC_id]-ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb; + } + } + }else{ + UE_template = &UE_list->UE_template[CC_id][ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id]; + if ( UE_list->UE_sched_ctrl[ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id].phr_received == 1 ) { + mcs = 20; + } else { + mcs = 10; + } + if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST ) { + if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ul_total_buffer > 0 ) { + rb_table_index = 2; + tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3; + tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0); + while ( (((UE_template->phr_info - tx_power) < 0 ) || (tbs > UE_template->ul_total_buffer)) && (mcs > 3) ) { + mcs--; + tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3; + tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0); + } + while ( (tbs < UE_template->ul_total_buffer) && (rb_table[rb_table_index]<(frame_parms->N_RB_UL-first_rb[CC_id])) && + ((UE_template->phr_info - tx_power) > 0) && (rb_table_index < 32 )) { + rb_table_index++; + tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3; + tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0); + } + if ( rb_table[rb_table_index]<3 ) { + rb_table_index=2; + } + if ( rb_table[rb_table_index] <= average_rbs ) { + // assigne RBS( nb_rb) + first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; + UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; + UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + } + if ( rb_table[rb_table_index] > average_rbs ) { + // assigne RBS(average_rbs) + rb_table_index = find_rb_table_index(average_rbs); + if (rb_table_index>=34){ + LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: average RBs %d > 100\n", + module_idP,frameP,subframeP,UE_id,rnti,CC_id,average_rbs); + break; + } + first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; + UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; + UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + } + }else { + // assigne RBS( 3 RBs) + first_rb[CC_id] = first_rb[CC_id] + 3; + UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; + UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; + UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + } + }else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) { + // assigne RBS( 3 RBs) + first_rb[CC_id] = first_rb[CC_id] + 3; + UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; + UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; + UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + } + } + ue_num_temp--; + } + } +} +#endif diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index b316cbfeeb8333e709106d0e44a2dc024760d454..a9069b3b8ef030662a088f6f69b05cbb157043a5 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -100,7 +100,11 @@ void schedule_ulsch(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); @param subframe Subframe number on which to act @param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup) */ +#ifndef UE_EXPANSION void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, uint16_t *first_rb); +#else +void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]); +#endif /** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4. @param Mod_id Instance of eNB @@ -108,7 +112,11 @@ void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t sub @param subframe Index of subframe @param mbsfn_flag Indicates that this subframe is for MCH/MCCH */ +#ifndef UE_EXPANSION void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag); +#else +void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag, DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]); +#endif /** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies @param Mod_id Instance ID of eNB @@ -188,7 +196,11 @@ void dlsch_scheduler_pre_processor (module_id_t module_idP, frame_t frameP, sub_frame_t subframe, int N_RBG[MAX_NUM_CCs], - int *mbsfn_flag); + int *mbsfn_flag +#ifdef UE_EXPANSION + , DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs] +#endif +); void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, @@ -579,9 +591,22 @@ void dump_ue_list(UE_list_t *listP, int ul_flag); int UE_num_active_CC(UE_list_t *listP,int ue_idP); int UE_PCCID(module_id_t mod_idP,int ue_idP); rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); +uint8_t find_rb_table_index(uint8_t average_rbs); - +#ifndef UE_EXPANSION void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, uint16_t *first_rb); +#else +void ulsch_scheduler_pre_processor(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]); +void ulsch_scheduler_pre_ue_select(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP,ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]); +#endif +void +set_ul_DAI( + int module_idP, + int UE_idP, + int CC_idP, + int frameP, + int subframeP +); void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP); void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP); void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP,uint16_t *first_rb); diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h index 4ff54752530fe9e892d8bf93f355effd03d12c89..d1e46d0512f265d9f87a0ff4331856ae7f1f5775 100644 --- a/openair2/LAYER2/MAC/vars.h +++ b/openair2/LAYER2/MAC/vars.h @@ -136,6 +136,10 @@ DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E; +#ifdef UE_EXPANSION +int last_dlsch_ue_id[MAX_NUM_CCs] = {-1}; +int last_ulsch_ue_id[MAX_NUM_CCs] = {-1}; +#endif #endif diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c index a05b27ddc361f93e62c6bb6bac70803b662ac152..21f1a2f5269802896c841bd54b7130d7815a5806 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c @@ -1555,7 +1555,11 @@ do_RRCConnectionSetup( // SchedulingRequestConfig physicalConfigDedicated2->schedulingRequestConfig->present = SchedulingRequestConfig_PR_setup; +#ifdef UE_EXPANSION + physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = 31 - ue_context_pP->local_uid/10;//ue_context_pP->local_uid; +#else physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = 71 - ue_context_pP->local_uid/10;//ue_context_pP->local_uid; +#endif if (carrier->sib1->tdd_Config == NULL) { // FDD physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 5+(ue_context_pP->local_uid%10); // Isr = 5 (every 10 subframes, offset=2+UE_id mod3) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf new file mode 100644 index 0000000000000000000000000000000000000000..f7f2eff340eb564ea6fa80586801e23ee098cf14 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf @@ -0,0 +1,210 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "3GPP_eNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2685000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -27; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONE"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + ue_multiple_max = 20; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.19/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.19/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 125; + eNB_instances = [0]; + + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; +