Commit c31d250d authored by francescomani's avatar francescomani

new structure to handle beams

fix: reset beam only if it is a newly allocated one
parent 871078a6
...@@ -51,10 +51,12 @@ ...@@ -51,10 +51,12 @@
* *
*********************************************************************/ *********************************************************************/
int set_tdd_config_nr( nfapi_nr_config_request_scf_t *cfg, int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg,
int mu, int mu,
int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofDownlinkSlots,
int nrofUplinkSlots, int nrofUplinkSymbols) int nrofDownlinkSymbols,
int nrofUplinkSlots,
int nrofUplinkSymbols)
{ {
int slot_number = 0; int slot_number = 0;
......
...@@ -72,6 +72,9 @@ ...@@ -72,6 +72,9 @@
#define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb" #define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb"
#define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs" #define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs"
#define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix" #define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix"
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
#define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period"
#define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not" #define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not"
#define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS" #define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS"
...@@ -85,6 +88,9 @@ ...@@ -85,6 +88,9 @@
#define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs" #define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs"
#define HLP_MACRLC_MIN_GRANT_MCS "Minimal Periodic ULSCH Grant MCS" #define HLP_MACRLC_MIN_GRANT_MCS "Minimal Periodic ULSCH Grant MCS"
#define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding" #define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding"
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
#define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period"
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* MacRLC configuration parameters */ /* MacRLC configuration parameters */
...@@ -127,6 +133,9 @@ ...@@ -127,6 +133,9 @@
{CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \ {CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
{CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \ {CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \
{CONFIG_STRING_MACRLC_TRANSPORT_S_POLL_CORE, NULL, 0, .i8ptr=NULL, .defintval=-1, TYPE_INT8, 0}, \ {CONFIG_STRING_MACRLC_TRANSPORT_S_POLL_CORE, NULL, 0, .i8ptr=NULL, .defintval=-1, TYPE_INT8, 0}, \
{CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
} }
// clang-format off // clang-format off
...@@ -165,6 +174,9 @@ ...@@ -165,6 +174,9 @@
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 32 #define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 32
#define MACRLC_TRANSPORT_S_SHM_PREFIX 33 #define MACRLC_TRANSPORT_S_SHM_PREFIX 33
#define MACRLC_TRANSPORT_S_POLL_CORE 34 #define MACRLC_TRANSPORT_S_POLL_CORE 34
#define MACRLC_ANALOG_BEAMFORMING_IDX 35
#define MACRLC_ANALOG_BEAM_DURATION_IDX 36
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37
#define MACRLCPARAMS_CHECK { \ #define MACRLCPARAMS_CHECK { \
{ .s5 = { NULL } }, \ { .s5 = { NULL } }, \
...@@ -202,6 +214,9 @@ ...@@ -202,6 +214,9 @@
{ .s5 = { NULL } }, \ { .s5 = { NULL } }, \
{ .s5 = { NULL } }, \ { .s5 = { NULL } }, \
{ .s2 = { NULL } }, \ { .s2 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
} }
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
......
...@@ -1405,6 +1405,15 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) ...@@ -1405,6 +1405,15 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr); RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr);
RC.nrmac[j]->num_ulprbbl = num_prbbl; RC.nrmac[j]->num_ulprbbl = num_prbbl;
memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0])); memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0]));
bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
if (ab) {
NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info;
int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMS_PERIOD_IDX].u8ptr;
beam_info->beam_allocation = malloc16(beams_per_period * sizeof(int *));
beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAM_DURATION_IDX].u8ptr;
beam_info->beams_per_period = beams_per_period;
beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration
}
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++) } // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
uint64_t gnb_du_id = 0; uint64_t gnb_du_id = 0;
......
...@@ -1787,8 +1787,8 @@ int get_nr_prach_info_from_index(uint8_t index, ...@@ -1787,8 +1787,8 @@ int get_nr_prach_info_from_index(uint8_t index,
uint8_t *N_dur, uint8_t *N_dur,
uint16_t *RA_sfn_index, uint16_t *RA_sfn_index,
uint8_t *N_RA_slot, uint8_t *N_RA_slot,
uint8_t *config_period) { uint8_t *config_period)
{
int x,y; int x,y;
int64_t s_map; int64_t s_map;
uint8_t format2 = 0xff; uint8_t format2 = 0xff;
......
...@@ -587,20 +587,31 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant ...@@ -587,20 +587,31 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols); scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols);
AssertFatal(periods_per_frame > 0, "TDD configuration cannot be configured\n"); AssertFatal(periods_per_frame > 0, "TDD configuration cannot be configured\n");
if (frequency_range == FR2) {
LOG_I(NR_MAC, "Configuring TDD beam association to default\n");
nrmac->tdd_beam_association = malloc16(periods_per_frame * sizeof(int16_t));
for (int i = 0; i < periods_per_frame; ++i)
nrmac->tdd_beam_association[i] = -1; /* default: beams not configured */
} else {
nrmac->tdd_beam_association = NULL; /* default: no beams */
}
} }
// precoding matrix configuration (to be improved) // precoding matrix configuration (to be improved)
cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts); cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts);
} }
static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int slots_per_frame)
{
if(!beam_info->beam_allocation)
return;
int size = mu == 0 ? slots_per_frame << 1 : slots_per_frame;
// slots in beam duration gives the number of consecutive slots tied the the same beam
AssertFatal(size % beam_info->beam_duration == 0,
"Beam duration %d should be divider of number of slots per frame %d\n",
beam_info->beam_duration,
slots_per_frame);
beam_info->beam_allocation_size = size / beam_info->beam_duration;
for (int i = 0; i < beam_info->beams_per_period; i++) {
beam_info->beam_allocation[i] = malloc16(beam_info->beam_allocation_size * sizeof(int));
for (int j = 0; j < beam_info->beam_allocation_size; j++)
beam_info->beam_allocation[i][j] = -1;
}
}
void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config) void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config)
{ {
DevAssert(nrmac != NULL); DevAssert(nrmac != NULL);
...@@ -624,6 +635,8 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c ...@@ -624,6 +635,8 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
nrmac->UL_tti_req_ahead[0] = calloc(size, sizeof(nfapi_nr_ul_tti_request_t)); nrmac->UL_tti_req_ahead[0] = calloc(size, sizeof(nfapi_nr_ul_tti_request_t));
AssertFatal(nrmac->UL_tti_req_ahead[0], "could not allocate memory for nrmac->UL_tti_req_ahead[0]\n"); AssertFatal(nrmac->UL_tti_req_ahead[0], "could not allocate memory for nrmac->UL_tti_req_ahead[0]\n");
initialize_beam_information(&nrmac->beam_info, *scc->ssbSubcarrierSpacing, n);
LOG_I(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n"); LOG_I(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
config_common(nrmac, config->pdsch_AntennaPorts, config->pusch_AntennaPorts, scc); config_common(nrmac, config->pdsch_AntennaPorts, config->pusch_AntennaPorts, scc);
......
...@@ -146,6 +146,24 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, ...@@ -146,6 +146,24 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
TX_req[CC_idP].Number_of_PDUs = 0; TX_req[CC_idP].Number_of_PDUs = 0;
} }
void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int mu)
{
// for now we use the same logic of UL_tti_req_ahead
// reset after 1 frame with the exception of 15kHz
if(!beam_info->beam_allocation)
return;
// initialization done only once
const int slots_per_frame = nr_slots_per_frame[mu];
AssertFatal(beam_info->beam_allocation_size >= 0, "Beam information not initialized\n");
int idx_to_clear = (frame * slots_per_frame + slot) / beam_info->beam_duration;
idx_to_clear = (idx_to_clear + beam_info->beam_allocation_size - 1) % beam_info->beam_allocation_size;
if (slot % beam_info->beam_duration == 0) {
// resetting previous period allocation
for (int i = 0; i < beam_info->beams_per_period; i++)
beam_info->beam_allocation[i][idx_to_clear] = -1;
}
}
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
return (bitmap >> (slot % 64)) & 0x01; return (bitmap >> (slot % 64)) & 0x01;
} }
...@@ -199,15 +217,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ ...@@ -199,15 +217,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_
NR_SCHED_LOCK(&gNB->sched_lock); NR_SCHED_LOCK(&gNB->sched_lock);
if (slot==0 && (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]>=257)) { clear_beam_information(&gNB->beam_info, frame, slot, *scc->ssbSubcarrierSpacing);
//FR2
const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
AssertFatal(tdd,"Dynamic TDD not handled yet\n");
const int nb_periods_per_frame = get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
// re-initialization of tdd_beam_association at beginning of frame
for (int i=0; i<nb_periods_per_frame; i++)
gNB->tdd_beam_association[i] = -1;
}
gNB->frame = frame; gNB->frame = frame;
start_meas(&gNB->eNB_scheduler); start_meas(&gNB->eNB_scheduler);
......
...@@ -86,7 +86,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, ...@@ -86,7 +86,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES; uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES;
if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
...@@ -135,7 +135,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, ...@@ -135,7 +135,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
} }
// prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; // prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index;
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) + prach_occasion_id = (((frameP % (cc->max_association_period * config_period)) / config_period) * cc->total_prach_occasions_per_config_period) +
(RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index;
//one RO is shared by one or more SSB //one RO is shared by one or more SSB
...@@ -145,7 +145,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, ...@@ -145,7 +145,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
else if ( num_ssb_per_RO > 1) { else if ( num_ssb_per_RO > 1) {
index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ; index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ;
for(int j = 0;j < num_ssb_per_RO;j++) { for(int j = 0;j < num_ssb_per_RO;j++) {
if(preamble_index < (((j+1) * total_RApreambles) / num_ssb_per_RO)) if(preamble_index < (((j + 1) * total_RApreambles) / num_ssb_per_RO))
index = index + j; index = index + j;
} }
} }
...@@ -308,24 +308,24 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP ...@@ -308,24 +308,24 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
uint16_t format1 = (format >> 8) & 0xff; // second column of format from table uint16_t format1 = (format >> 8) & 0xff; // second column of format from table
if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe
if (slotP%2 == 1) if (slotP % 2 == 1)
slot_index = 1; slot_index = 1;
else else
slot_index = 0; slot_index = 0;
}else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe } else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
slot_index = 0; slot_index = 0;
} }
UL_tti_req->SFN = frameP; UL_tti_req->SFN = frameP;
UL_tti_req->Slot = slotP; UL_tti_req->Slot = slotP;
UL_tti_req->rach_present = 1; UL_tti_req->rach_present = 1;
for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
for (int td_index=0; td_index<N_t_slot; td_index++) { for (int td_index = 0; td_index < N_t_slot; td_index++) {
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) +
(RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index; (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index;
if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){ if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)) {
AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]), AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
"Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus); "Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus);
...@@ -551,20 +551,6 @@ static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_Cont ...@@ -551,20 +551,6 @@ static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_Cont
ra->contention_resolution_timer); ra->contention_resolution_timer);
} }
static bool beam_is_active(const NR_TDD_UL_DL_Pattern_t *tdd, int mu, const int16_t *tdd_beam_association, int slot, int16_t ra_beam)
{
if (tdd_beam_association == NULL) // no beams configured
return true;
DevAssert(tdd != NULL);
const int n_slots_frame = nr_slots_per_frame[mu];
uint8_t tdd_period_slot = n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
int num_tdd_period = slot / tdd_period_slot;
int16_t current_beam = tdd_beam_association[num_tdd_period];
return current_beam == -1 /* no beams */
|| current_beam == ra_beam;
}
static void nr_generate_Msg3_retransmission(module_id_t module_idP, static void nr_generate_Msg3_retransmission(module_id_t module_idP,
int CC_id, int CC_id,
frame_t frame, frame_t frame,
...@@ -585,14 +571,19 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ...@@ -585,14 +571,19 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) { if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) {
// beam association for FR2 const int n_slots_frame = nr_slots_per_frame[mu];
if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) { NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info,
// FR2 sched_frame,
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; sched_slot,
if (!beam_is_active(tdd, mu, nr_mac->tdd_beam_association, sched_slot, ra->beam_id)) ra->beam_id,
n_slots_frame);
if (beam_ul.idx < 0)
return;
NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, ra->beam_id, n_slots_frame);
if (beam_dci.idx < 0) {
reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, n_slots_frame, beam_ul.new_beam);
return; return;
} }
int fh = 0; int fh = 0;
int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
int StartSymbolIndex, NrOfSymbols; int StartSymbolIndex, NrOfSymbols;
...@@ -752,7 +743,10 @@ static int get_feasible_msg3_tda(frame_type_t frame_type, ...@@ -752,7 +743,10 @@ static int get_feasible_msg3_tda(frame_type_t frame_type,
uint64_t ulsch_slot_bitmap[3], uint64_t ulsch_slot_bitmap[3],
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list, const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list,
int slots_per_frame, int slots_per_frame,
int frame,
int slot, int slot,
NR_RA_t *ra,
NR_beam_info_t *beam_info,
const NR_TDD_UL_DL_Pattern_t *tdd) const NR_TDD_UL_DL_Pattern_t *tdd)
{ {
DevAssert(tda_list != NULL); DevAssert(tda_list != NULL);
...@@ -770,7 +764,9 @@ static int get_feasible_msg3_tda(frame_type_t frame_type, ...@@ -770,7 +764,9 @@ static int get_feasible_msg3_tda(frame_type_t frame_type,
for (int i = 0; i < tda_list->list.count; i++) { for (int i = 0; i < tda_list->list.count; i++) {
// check if it is UL // check if it is UL
long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset; long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset;
int temp_slot = (slot + k2 + mu_delta) % slots_per_frame; // msg3 slot according to 8.3 in 38.213 int abs_slot = slot + k2 + mu_delta;
int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023;
int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213
if (!is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot)) if (!is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot))
continue; continue;
...@@ -791,9 +787,17 @@ static int get_feasible_msg3_tda(frame_type_t frame_type, ...@@ -791,9 +787,17 @@ static int get_feasible_msg3_tda(frame_type_t frame_type,
if ((slot_mask & msg3_mask) != msg3_mask) if ((slot_mask & msg3_mask) != msg3_mask)
continue; continue;
// check if it is possible to allocate MSG3 in a beam in this slot
NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ra->beam_id, slots_per_frame);
if (beam.idx < 0)
continue;
// is in mixed slot with more or equal than 3 symbols, or UL slot // is in mixed slot with more or equal than 3 symbols, or UL slot
int tda = i; ra->Msg3_frame = temp_frame;
return tda; ra->Msg3_slot = temp_slot;
ra->Msg3_tda_id = i;
ra->Msg3_beam = beam;
return true;
} }
return -1; // invalid return -1; // invalid
...@@ -804,8 +808,7 @@ static void nr_get_Msg3alloc(module_id_t module_id, ...@@ -804,8 +808,7 @@ static void nr_get_Msg3alloc(module_id_t module_id,
NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfigCommon_t *scc,
sub_frame_t current_slot, sub_frame_t current_slot,
frame_t current_frame, frame_t current_frame,
NR_RA_t *ra, NR_RA_t *ra)
int16_t *tdd_beam_association)
{ {
// msg3 is scheduled in mixed slot in the following TDD period // msg3 is scheduled in mixed slot in the following TDD period
DevAssert(ra->Msg3_tda_id >= 0 && ra->Msg3_tda_id < 16); DevAssert(ra->Msg3_tda_id >= 0 && ra->Msg3_tda_id < 16);
...@@ -818,24 +821,17 @@ static void nr_get_Msg3alloc(module_id_t module_id, ...@@ -818,24 +821,17 @@ static void nr_get_Msg3alloc(module_id_t module_id,
const NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common; const NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common;
int mu = ul_bwp->scs; int mu = ul_bwp->scs;
const int n_slots_frame = nr_slots_per_frame[mu];
int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
SLIV2SL(startSymbolAndLength, &ra->msg3_startsymb, &ra->msg3_nbSymb); SLIV2SL(startSymbolAndLength, &ra->msg3_startsymb, &ra->msg3_nbSymb);
long k2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc);
int abs_slot = current_slot + k2 + DELTA[mu];
ra->Msg3_slot = abs_slot % n_slots_frame;
ra->Msg3_frame = (current_frame + (abs_slot / n_slots_frame)) % MAX_FRAME_NUMBER;
LOG_I(NR_MAC, LOG_I(NR_MAC,
"UE %04x: Msg3 scheduled at %d.%d (%d.%d k2 %ld TDA %u)\n", "UE %04x: Msg3 scheduled at %d.%d (%d.%d TDA %u)\n",
ra->rnti, ra->rnti,
ra->Msg3_frame, ra->Msg3_frame,
ra->Msg3_slot, ra->Msg3_slot,
current_frame, current_frame,
current_slot, current_slot,
k2,
ra->Msg3_tda_id); ra->Msg3_tda_id);
const int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, mu, mac->vrb_map_UL_size); const int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, mu, mac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE]; uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
...@@ -1219,26 +1215,32 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1219,26 +1215,32 @@ static void nr_generate_Msg2(module_id_t module_idP,
LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, ra->rnti); LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, ra->rnti);
return; return;
} }
const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
if (!beam_is_active(tdd, ul_bwp->scs, nr_mac->tdd_beam_association, slotP, ra->beam_id)) {
LOG_I(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: beam %d inactive\n", ra->RA_rnti, ra->rnti, ra->beam_id);
return;
}
ra->Msg3_tda_id = get_feasible_msg3_tda(cc->frame_type, ra->Msg3_tda_id = get_feasible_msg3_tda(cc->frame_type,
scc, scc,
DELTA[ul_bwp->scs], DELTA[ul_bwp->scs],
nr_mac->ulsch_slot_bitmap, nr_mac->ulsch_slot_bitmap,
ul_bwp->tdaList_Common, ul_bwp->tdaList_Common,
nr_slots_per_frame[ul_bwp->scs], nr_slots_per_frame[ul_bwp->scs],
frameP,
slotP, slotP,
ra,
&nr_mac->beam_info,
tdd); tdd);
if (ra->Msg3_tda_id < 0 || ra->Msg3_tda_id > 15) { if (ra->Msg3_tda_id < 0 || ra->Msg3_tda_id > 15) {
LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP); LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP);
return; return;
} }
const int n_slots_frame = nr_slots_per_frame[dl_bwp->scs];
NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame);
if (beam.idx < 0) {
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
return;
}
int mcsIndex = -1; // initialization value int mcsIndex = -1; // initialization value
int rbStart = 0; int rbStart = 0;
int rbSize = 8; int rbSize = 8;
...@@ -1284,6 +1286,8 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1284,6 +1286,8 @@ static void nr_generate_Msg2(module_id_t module_idP,
if (rbStart > (BWPSize - rbSize)) { if (rbStart > (BWPSize - rbSize)) {
LOG_W(NR_MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti); LOG_W(NR_MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti);
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
...@@ -1291,6 +1295,8 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1291,6 +1295,8 @@ static void nr_generate_Msg2(module_id_t module_idP,
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP); LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP);
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
...@@ -1299,6 +1305,8 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1299,6 +1305,8 @@ static void nr_generate_Msg2(module_id_t module_idP,
if (CCEIndex < 0) { if (CCEIndex < 0) {
LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", ra->rnti, frameP, slotP); LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", ra->rnti, frameP, slotP);
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
...@@ -1462,7 +1470,7 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1462,7 +1470,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs];
// Program UL processing for Msg3 // Program UL processing for Msg3
nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra, nr_mac->tdd_beam_association); nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra);
nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *)&tx_req->TLVs[0].value.direct[0]);
// Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2)
...@@ -1762,6 +1770,11 @@ static void nr_generate_Msg4(module_id_t module_idP, ...@@ -1762,6 +1770,11 @@ static void nr_generate_Msg4(module_id_t module_idP,
mac_sdu_length = srb_status.bytes_in_buffer; mac_sdu_length = srb_status.bytes_in_buffer;
} }
const int n_slots_frame = nr_slots_per_frame[dl_bwp->scs];
NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame);
if (beam.idx < 0)
return;
long BWPStart = 0; long BWPStart = 0;
long BWPSize = 0; long BWPSize = 0;
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL;
...@@ -1785,7 +1798,8 @@ static void nr_generate_Msg4(module_id_t module_idP, ...@@ -1785,7 +1798,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
true); true);
if (CCEIndex < 0) { if (CCEIndex < 0) {
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti); LOG_E(NR_MAC, "Cannot find free CCE for RA RNTI 0x%04x!\n", ra->rnti);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
...@@ -1793,6 +1807,7 @@ static void nr_generate_Msg4(module_id_t module_idP, ...@@ -1793,6 +1807,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP); LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
...@@ -1857,7 +1872,8 @@ static void nr_generate_Msg4(module_id_t module_idP, ...@@ -1857,7 +1872,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
} }
if (rbStart > (BWPSize - rbSize)) { if (rbStart > (BWPSize - rbSize)) {
LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RNTI %04x!\n", __func__, ra->rnti); LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", ra->rnti);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
...@@ -1877,9 +1893,10 @@ static void nr_generate_Msg4(module_id_t module_idP, ...@@ -1877,9 +1893,10 @@ static void nr_generate_Msg4(module_id_t module_idP,
LOG_D(NR_MAC, "Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI); LOG_D(NR_MAC, "Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI);
alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, r_pucch, 1); alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, ra->beam_id, r_pucch, 1);
if (alloc < 0) { if (alloc < 0) {
LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n",frameP,slotP); LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n", frameP, slotP);
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
return; return;
} }
} }
......
...@@ -115,10 +115,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, ...@@ -115,10 +115,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
gNB_MAC_INST *gNB = RC.nrmac[module_idP]; gNB_MAC_INST *gNB = RC.nrmac[module_idP];
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
nfapi_nr_dl_tti_request_body_t *dl_req; nfapi_nr_dl_tti_request_body_t *dl_req;
uint8_t num_tdd_period,num_ssb;
int CC_id;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
NR_COMMON_channels_t *cc= &gNB->common_channels[CC_id]; NR_COMMON_channels_t *cc= &gNB->common_channels[CC_id];
const NR_MIB_t *mib = cc->mib->message.choice.mib; const NR_MIB_t *mib = cc->mib->message.choice.mib;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
...@@ -169,15 +167,18 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, ...@@ -169,15 +167,18 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;
uint16_t ssb_start_symbol; uint16_t ssb_start_symbol;
const int n_slots_frame = nr_slots_per_frame[scs];
switch (scc->ssb_PositionsInBurst->present) { switch (scc->ssb_PositionsInBurst->present) {
case 1: case 1:
// short bitmap (<3GHz) max 4 SSBs // short bitmap (<3GHz) max 4 SSBs
for (int i_ssb=0; i_ssb<4; i_ssb++) { for (int i_ssb = 0; i_ssb < 4; i_ssb++) {
if ((shortBitmap->buf[0]>>(7-i_ssb))&0x01) { if ((shortBitmap->buf[0] >> (7 - i_ssb)) & 0x01) {
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){ if ((ssb_start_symbol / 14) == rel_slot){
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, i_ssb, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
const int prb_offset = offset_pointa >> scs; const int prb_offset = offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu); schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id); fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
...@@ -202,11 +203,13 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, ...@@ -202,11 +203,13 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
break; break;
case 2: case 2:
// medium bitmap (<6GHz) max 8 SSBs // medium bitmap (<6GHz) max 8 SSBs
for (int i_ssb=0; i_ssb<8; i_ssb++) { for (int i_ssb = 0; i_ssb < 8; i_ssb++) {
if ((mediumBitmap->buf[0]>>(7-i_ssb))&0x01) { if ((mediumBitmap->buf[0] >> (7 - i_ssb)) & 0x01) {
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){ if ((ssb_start_symbol / 14) == rel_slot){
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, i_ssb, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
const int prb_offset = offset_pointa >> scs; const int prb_offset = offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu); schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id); fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
...@@ -231,23 +234,16 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, ...@@ -231,23 +234,16 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
break; break;
case 3: case 3:
// long bitmap FR2 max 64 SSBs // long bitmap FR2 max 64 SSBs
num_ssb = 0; for (int i_ssb = 0; i_ssb < 64; i_ssb++) {
for (int i_ssb=0; i_ssb<64; i_ssb++) { if ((longBitmap->buf[i_ssb / 8] >> (7 - (i_ssb % 8))) & 0x01) {
if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) { ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){ if ((ssb_start_symbol / 14) == rel_slot){
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, i_ssb, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
const int prb_offset = offset_pointa >> (scs-2); // reference 60kHz const int prb_offset = offset_pointa >> (scs-2); // reference 60kHz
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu); schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset >> (scs - 2), ssb_start_symbol, CC_id); fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset >> (scs - 2), ssb_start_symbol, CC_id);
const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
// FR2 is only TDD, to be fixed for flexible TDD
const int nr_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) : n_slots_frame;
num_tdd_period = rel_slot/nr_slots_period;
gNB->tdd_beam_association[num_tdd_period]=i_ssb;
num_ssb++;
AssertFatal(num_ssb<2,"beamforming currently not supported for more than one SSB per slot\n");
if (get_softmodem_params()->sa == 1) { if (get_softmodem_params()->sa == 1) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP, frameP,
...@@ -571,15 +567,18 @@ void schedule_nr_sib1(module_id_t module_idP, ...@@ -571,15 +567,18 @@ void schedule_nr_sib1(module_id_t module_idP,
scc->ssb_PositionsInBurst->present); scc->ssb_PositionsInBurst->present);
} }
for (int i=0; i<L_max; i++) { for (int i = 0; i < L_max; i++) {
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i]; NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
if((frameP%2 == type0_PDCCH_CSS_config->sfn_c) && if((frameP % 2 == type0_PDCCH_CSS_config->sfn_c) &&
(slotP == type0_PDCCH_CSS_config->n_0) && (slotP == type0_PDCCH_CSS_config->n_0) &&
(type0_PDCCH_CSS_config->num_rbs > 0) && (type0_PDCCH_CSS_config->num_rbs > 0) &&
(type0_PDCCH_CSS_config->active == true)) { (type0_PDCCH_CSS_config->active == true)) {
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, i, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SIB1 corresponding to SSB %d in any available beam\n", i);
LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index); LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
default_table_type_t table_type = get_default_table_type(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern); default_table_type_t table_type = get_default_table_type(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern);
......
...@@ -565,8 +565,9 @@ static bool allocate_dl_retransmission(module_id_t module_id, ...@@ -565,8 +565,9 @@ static bool allocate_dl_retransmission(module_id_t module_id,
int alloc = -1; int alloc = -1;
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, current_harq_pid)) { if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, current_harq_pid)) {
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex); int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, r_pucch, 0); // TODO properly set the beam index (currently only done for RA)
if (alloc<0) { alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, 0, r_pucch, 0);
if (alloc < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI retransmission\n", LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI retransmission\n",
UE->rnti, UE->rnti,
frame, frame,
...@@ -758,8 +759,9 @@ static void pf_dl(module_id_t module_id, ...@@ -758,8 +759,9 @@ static void pf_dl(module_id_t module_id,
int alloc = -1; int alloc = -1;
if (!get_FeedbackDisabled(iterator->UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) { if (!get_FeedbackDisabled(iterator->UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex); int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, r_pucch, 0); // TODO properly set the beam index (currently only done for RA)
if (alloc<0) { alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, 0, r_pucch, 0);
if (alloc < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI\n", LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI\n",
rnti, rnti,
frame, frame,
......
...@@ -149,11 +149,10 @@ void nr_preprocessor_phytest(module_id_t module_id, ...@@ -149,11 +149,10 @@ void nr_preprocessor_phytest(module_id_t module_id,
int alloc = -1; int alloc = -1;
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) { if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex); int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex);
alloc = nr_acknack_scheduling(RC.nrmac[module_id], UE, frame, slot, r_pucch, 0); alloc = nr_acknack_scheduling(RC.nrmac[module_id], UE, frame, slot, 0, r_pucch, 0);
if (alloc < 0) { if (alloc < 0) {
LOG_D(MAC, LOG_D(MAC,
"%s(): could not find PUCCH for UE %04x@%d.%d\n", "Could not find PUCCH for UE %04x@%d.%d\n",
__func__,
rnti, rnti,
frame, frame,
slot); slot);
......
...@@ -3110,6 +3110,43 @@ void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t ...@@ -3110,6 +3110,43 @@ void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t
} }
} }
static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame)
{
return ((frame * slots_per_frame + slot) / beam_info->beam_duration) % beam_info->beam_allocation_size;
}
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame)
{
// if no beam allocation for analog beamforming we always return beam index 0 (no multiple beams)
if (!beam_info->beam_allocation)
return (NR_beam_alloc_t) {.new_beam = false, .idx = 0};
const int index = get_beam_index(beam_info, frame, slot, beam_index, slots_per_frame);
for (int i = 0; i < beam_info->beams_per_period; i++) {
NR_beam_alloc_t beam_struct = {.new_beam = false, .idx = i};
int *beam = &beam_info->beam_allocation[i][index];
if (*beam == -1) {
beam_struct.new_beam = true;
*beam = beam_index;
}
if (*beam == beam_index)
return beam_struct;
}
return (NR_beam_alloc_t) {.new_beam = false, .idx = -1};
}
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam)
{
if(!new_beam) // need to reset only if the beam was allocated specifically for this instance
return;
const int index = get_beam_index(beam_info, frame, slot, beam_index, slots_per_frame);
for (int i = 0; i < beam_info->beams_per_period; i++) {
if (beam_info->beam_allocation[i][index] == beam_index)
beam_info->beam_allocation[i][index] = -1;
}
}
void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data) void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data)
{ {
gNB_MAC_INST *mac = RC.nrmac[0]; gNB_MAC_INST *mac = RC.nrmac[0];
......
...@@ -1239,6 +1239,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, ...@@ -1239,6 +1239,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
NR_UE_info_t *UE, NR_UE_info_t *UE,
frame_t frame, frame_t frame,
sub_frame_t slot, sub_frame_t slot,
int beam_index,
int r_pucch, int r_pucch,
int is_common) int is_common)
{ {
...@@ -1335,8 +1336,17 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, ...@@ -1335,8 +1336,17 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
bwp_start, bwp_start,
bwp_size); bwp_size);
if(!ret) { if(!ret) {
LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n", LOG_D(NR_MAC,
"DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n",
frame, slot, pucch_frame, pucch_slot);
continue;
}
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, beam_index, n_slots_frame);
if (beam.idx < 0) {
LOG_D(NR_MAC,
"DL %4d.%2d, UL_ACK %4d.%2d beam resources for this occasion are already occupied, move to the following occasion\n",
frame, slot, pucch_frame, pucch_slot); frame, slot, pucch_frame, pucch_slot);
// TODO add reset beam status
continue; continue;
} }
// allocating a new PUCCH structure for this occasion // allocating a new PUCCH structure for this occasion
......
...@@ -175,6 +175,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, ...@@ -175,6 +175,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
NR_UE_info_t *UE, NR_UE_info_t *UE,
frame_t frameP, frame_t frameP,
sub_frame_t slotP, sub_frame_t slotP,
int beam_index,
int r_pucch, int r_pucch,
int do_common); int do_common);
...@@ -420,9 +421,11 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, ...@@ -420,9 +421,11 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
frame_t frame); frame_t frame);
int ul_buffer_index(int frame, int slot, int scs, int size); int ul_buffer_index(int frame, int slot, int scs, int size);
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP); void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame);
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam);
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP); void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP);
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp);
......
...@@ -120,8 +120,15 @@ typedef enum { ...@@ -120,8 +120,15 @@ typedef enum {
nrRA_Msg4 = 4, nrRA_Msg4 = 4,
nrRA_WAIT_Msg4_ACK = 5, nrRA_WAIT_Msg4_ACK = 5,
} RA_gNB_state_t; } RA_gNB_state_t;
static const char *const nrra_text[] = static const char *const nrra_text[] =
{"IDLE", "Msg2", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "WAIT_Msg4_ACK"}; {"IDLE", "Msg2", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "WAIT_Msg4_ACK"};
typedef struct {
int idx;
bool new_beam;
} NR_beam_alloc_t;
typedef struct nr_pdsch_AntennaPorts_t { typedef struct nr_pdsch_AntennaPorts_t {
int N1; int N1;
int N2; int N2;
...@@ -203,6 +210,8 @@ typedef struct { ...@@ -203,6 +210,8 @@ typedef struct {
frame_t Msg3_frame; frame_t Msg3_frame;
/// Msg3 time domain allocation index /// Msg3 time domain allocation index
int Msg3_tda_id; int Msg3_tda_id;
/// Msg3 beam matrix index
NR_beam_alloc_t Msg3_beam;
/// harq_pid used for Msg4 transmission /// harq_pid used for Msg4 transmission
uint8_t harq_pid; uint8_t harq_pid;
/// UE RNTI allocated during RAR /// UE RNTI allocated during RAR
...@@ -742,6 +751,14 @@ typedef struct { ...@@ -742,6 +751,14 @@ typedef struct {
uid_allocator_t uid_allocator; uid_allocator_t uid_allocator;
} NR_UEs_t; } NR_UEs_t;
typedef struct {
/// list of allocated beams per period
int **beam_allocation;
int beam_duration; // in slots
int beams_per_period;
int beam_allocation_size;
} NR_beam_info_t;
#define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++))) #define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
typedef void (*nr_pp_impl_dl)(module_id_t mod_id, typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
...@@ -841,8 +858,8 @@ typedef struct gNB_MAC_INST_s { ...@@ -841,8 +858,8 @@ typedef struct gNB_MAC_INST_s {
time_stats_t rx_ulsch_sdu; // include rlc_data_ind time_stats_t rx_ulsch_sdu; // include rlc_data_ind
/// processing time of eNB PCH scheduler /// processing time of eNB PCH scheduler
time_stats_t schedule_pch; time_stats_t schedule_pch;
/// list of allocated beams per period
int16_t *tdd_beam_association; NR_beam_info_t beam_info;
/// bitmap of DLSCH slots, can hold up to 160 slots /// bitmap of DLSCH slots, can hold up to 160 slots
uint64_t dlsch_slot_bitmap[3]; uint64_t dlsch_slot_bitmap[3];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment