535 lines
23 KiB
C
535 lines
23 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
/* \file nr_ue_dci_configuration.c
|
|
* \brief functions for generating dci search procedures based on RRC Serving Cell Group Configuration
|
|
* \author R. Knopp, G. Casati
|
|
* \date 2020
|
|
* \version 0.2
|
|
* \company Eurecom, Fraunhofer IIS
|
|
* \email: knopp@eurecom.fr, guido.casati@iis.fraunhofer.de
|
|
* \note
|
|
* \warning
|
|
*/
|
|
|
|
#include "mac_proto.h"
|
|
#include "mac_defs.h"
|
|
#include "assertions.h"
|
|
#include "mac_defs.h"
|
|
#include "common/utils/nr/nr_common.h"
|
|
#include "executables/softmodem-common.h"
|
|
#include <stdio.h>
|
|
|
|
void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, const uint32_t Y)
|
|
{
|
|
LOG_T(NR_MAC_DCI, "Filling search candidates for DCI\n");
|
|
|
|
int i = 0;
|
|
for (int maxL = 16; maxL > 0; maxL >>= 1) {
|
|
uint8_t aggregation, max_number_of_candidates;
|
|
find_aggregation_candidates(&aggregation,
|
|
&max_number_of_candidates,
|
|
ss,
|
|
maxL);
|
|
if (max_number_of_candidates == 0)
|
|
continue;
|
|
LOG_T(NR_MAC_DCI, "L %d, max number of candidates %d, aggregation %d\n", maxL, max_number_of_candidates, aggregation);
|
|
int N_cce_sym = 0; // nb of rbs of coreset per symbol
|
|
for (int f = 0; f < 6; f++) {
|
|
for (int t = 0; t < 8; t++) {
|
|
N_cce_sym += ((rel15->coreset.frequency_domain_resource[f] >> t) & 1);
|
|
}
|
|
}
|
|
int N_cces = N_cce_sym * rel15->coreset.duration;
|
|
if (N_cces < aggregation)
|
|
continue;
|
|
for (int j = 0; j < max_number_of_candidates; j++) {
|
|
int first_cce = aggregation * ((Y + ((j * N_cces) / (aggregation * max_number_of_candidates)) + 0) % (N_cces / aggregation));
|
|
LOG_T(NR_MAC_DCI,
|
|
"Candidate %d of %d first_cce %d (L %d N_cces %d Y %d)\n",
|
|
j,
|
|
max_number_of_candidates,
|
|
first_cce,
|
|
aggregation,
|
|
N_cces,
|
|
Y);
|
|
// to avoid storing more than one candidate with the same aggregation and starting CCE (duplicated candidate)
|
|
bool duplicated = false;
|
|
for (int k = 0; k < i; k++) {
|
|
if (rel15->CCE[k] == first_cce && rel15->L[k] == aggregation) {
|
|
duplicated = true;
|
|
LOG_T(NR_MAC_DCI, "Candidate %d of %d is duplicated\n", j, max_number_of_candidates);
|
|
}
|
|
}
|
|
if (!duplicated) {
|
|
rel15->CCE[i] = first_cce;
|
|
rel15->L[i] = aggregation;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
rel15->number_of_candidates = i;
|
|
}
|
|
|
|
NR_ControlResourceSet_t *ue_get_coreset(const NR_BWP_PDCCH_t *config, const int coreset_id)
|
|
{
|
|
if (config->commonControlResourceSet && coreset_id == config->commonControlResourceSet->controlResourceSetId)
|
|
return config->commonControlResourceSet;
|
|
NR_ControlResourceSet_t *coreset = NULL;
|
|
for (int i = 0; i < config->list_Coreset.count; i++) {
|
|
if (config->list_Coreset.array[i]->controlResourceSetId == coreset_id) {
|
|
coreset = config->list_Coreset.array[i];
|
|
break;
|
|
}
|
|
}
|
|
AssertFatal(coreset, "Couldn't find coreset with id %d\n", coreset_id);
|
|
return coreset;
|
|
}
|
|
|
|
static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
|
|
fapi_nr_dl_config_request_t *dl_config,
|
|
const int rnti_type,
|
|
const int slot,
|
|
const NR_SearchSpace_t *ss)
|
|
{
|
|
const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
|
|
const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
|
|
NR_BWP_Id_t dl_bwp_id = current_DL_BWP ? current_DL_BWP->bwp_id : 0;
|
|
NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[dl_bwp_id];
|
|
|
|
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15;
|
|
|
|
const int coreset_id = *ss->controlResourceSetId;
|
|
NR_ControlResourceSet_t *coreset;
|
|
if(coreset_id > 0) {
|
|
coreset = ue_get_coreset(pdcch_config, coreset_id);
|
|
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
|
|
} else {
|
|
coreset = mac->coreset0;
|
|
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
|
}
|
|
|
|
rel15->coreset.duration = coreset->duration;
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i];
|
|
rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present ==
|
|
NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED;
|
|
if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) {
|
|
struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved;
|
|
rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize);
|
|
rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize);
|
|
rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : mac->physCellId;
|
|
} else {
|
|
rel15->coreset.RegBundleSize = 0;
|
|
rel15->coreset.InterleaverSize = 0;
|
|
rel15->coreset.ShiftIndex = 0;
|
|
}
|
|
|
|
rel15->coreset.precoder_granularity = coreset->precoderGranularity;
|
|
|
|
// Scrambling RNTI
|
|
rel15->coreset.scrambling_rnti = 0;
|
|
if (coreset->pdcch_DMRS_ScramblingID) {
|
|
rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID;
|
|
if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
|
|
rel15->coreset.scrambling_rnti = mac->crnti;
|
|
} else {
|
|
rel15->coreset.pdcch_dmrs_scrambling_id = mac->physCellId;
|
|
}
|
|
|
|
int temp_num_dci_options = (mac->ra.ra_state == nrRA_WAIT_RAR || rnti_type == TYPE_SI_RNTI_) ? 1 : 2;
|
|
int dci_format[2] = {0};
|
|
if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
|
|
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats ==
|
|
NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0) {
|
|
dci_format[0] = NR_DL_DCI_FORMAT_1_0;
|
|
dci_format[1] = NR_UL_DCI_FORMAT_0_0;
|
|
}
|
|
else {
|
|
dci_format[0] = NR_DL_DCI_FORMAT_1_1;
|
|
dci_format[1] = NR_UL_DCI_FORMAT_0_1;
|
|
}
|
|
}
|
|
else { // common
|
|
AssertFatal(ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0,
|
|
"Only supporting format 10 and 00 for common SS\n");
|
|
dci_format[0] = NR_DL_DCI_FORMAT_1_0;
|
|
dci_format[1] = NR_UL_DCI_FORMAT_0_0;
|
|
}
|
|
|
|
NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info;
|
|
// loop over DCI options and configure resource allocation
|
|
// need to configure mac->def_dci_pdu_rel15 for all possible format options
|
|
for (int i = 0; i < temp_num_dci_options; i++) {
|
|
rel15->ss_type_options[i] = ss->searchSpaceType->present;
|
|
if (dci_format[i] == NR_DL_DCI_FORMAT_1_0 || dci_format[i] == NR_UL_DCI_FORMAT_0_0)
|
|
rel15->dci_format_options[i] = NFAPI_NR_FORMAT_0_0_AND_1_0;
|
|
else
|
|
rel15->dci_format_options[i] = NFAPI_NR_FORMAT_0_1_AND_1_1;
|
|
uint16_t alt_size = 0;
|
|
if(current_DL_BWP) {
|
|
// computing alternative size for padding or truncation
|
|
dci_pdu_rel15_t temp_pdu;
|
|
if (dci_format[i] == NR_DL_DCI_FORMAT_1_0)
|
|
alt_size = nr_dci_size(current_DL_BWP,
|
|
current_UL_BWP,
|
|
sc_info,
|
|
mac->pdsch_HARQ_ACK_Codebook,
|
|
&temp_pdu,
|
|
NR_UL_DCI_FORMAT_0_0,
|
|
rnti_type,
|
|
coreset,
|
|
dl_bwp_id,
|
|
ss->searchSpaceType->present,
|
|
mac->type0_PDCCH_CSS_config.num_rbs,
|
|
0);
|
|
if (dci_format[i] == NR_UL_DCI_FORMAT_0_0)
|
|
alt_size = nr_dci_size(current_DL_BWP,
|
|
current_UL_BWP,
|
|
sc_info,
|
|
mac->pdsch_HARQ_ACK_Codebook,
|
|
&temp_pdu,
|
|
NR_DL_DCI_FORMAT_1_0,
|
|
rnti_type,
|
|
coreset,
|
|
dl_bwp_id,
|
|
ss->searchSpaceType->present,
|
|
mac->type0_PDCCH_CSS_config.num_rbs,
|
|
0);
|
|
}
|
|
|
|
uint16_t dci_size = nr_dci_size(current_DL_BWP,
|
|
current_UL_BWP,
|
|
sc_info,
|
|
mac->pdsch_HARQ_ACK_Codebook,
|
|
&mac->def_dci_pdu_rel15[dl_config->slot][dci_format[i]],
|
|
dci_format[i],
|
|
rnti_type,
|
|
coreset,
|
|
dl_bwp_id,
|
|
ss->searchSpaceType->present,
|
|
mac->type0_PDCCH_CSS_config.num_rbs,
|
|
alt_size);
|
|
if (dci_size == 0)
|
|
return;
|
|
rel15->dci_length_options[i] = dci_size;
|
|
}
|
|
|
|
// DCI 0_0 and 1_0 are same size, L1 just needs to look for 1 option
|
|
// L2 decides format based on format indicator in payload
|
|
if (rel15->dci_format_options[0] == NFAPI_NR_FORMAT_0_0_AND_1_0)
|
|
rel15->num_dci_options = 1;
|
|
else
|
|
rel15->num_dci_options = 2;
|
|
|
|
rel15->BWPStart = coreset_id == 0 ? mac->type0_PDCCH_CSS_config.cset_start_rb : current_DL_BWP->BWPStart;
|
|
rel15->BWPSize = coreset_id == 0 ? mac->type0_PDCCH_CSS_config.num_rbs : current_DL_BWP->BWPSize;
|
|
|
|
uint16_t monitoringSymbolsWithinSlot = 0;
|
|
int sps = 0;
|
|
|
|
switch(rnti_type) {
|
|
case TYPE_C_RNTI_:
|
|
// we use DL BWP dedicated
|
|
sps = current_DL_BWP->cyclicprefix ? 12 : 14;
|
|
// for SPS=14 8 MSBs in positions 13 down to 6
|
|
monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
|
rel15->rnti = mac->crnti;
|
|
rel15->SubcarrierSpacing = current_DL_BWP->scs;
|
|
break;
|
|
case TYPE_RA_RNTI_:
|
|
// we use the initial DL BWP
|
|
sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12;
|
|
monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
|
rel15->rnti = mac->ra.ra_rnti;
|
|
rel15->SubcarrierSpacing = current_DL_BWP->scs;
|
|
break;
|
|
case TYPE_MSGB_RNTI_:
|
|
// we use the initial DL BWP
|
|
sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12;
|
|
monitoringSymbolsWithinSlot =
|
|
(ss->monitoringSymbolsWithinSlot->buf[0] << (sps - 8)) | (ss->monitoringSymbolsWithinSlot->buf[1] >> (16 - sps));
|
|
rel15->rnti = mac->ra.MsgB_rnti;
|
|
rel15->SubcarrierSpacing = current_DL_BWP->scs;
|
|
break;
|
|
case TYPE_P_RNTI_:
|
|
break;
|
|
case TYPE_CS_RNTI_:
|
|
break;
|
|
case TYPE_TC_RNTI_:
|
|
// we use the initial DL BWP
|
|
sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12;
|
|
monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
|
rel15->rnti = mac->ra.t_crnti;
|
|
rel15->SubcarrierSpacing = current_DL_BWP->scs;
|
|
break;
|
|
case TYPE_SP_CSI_RNTI_:
|
|
break;
|
|
case TYPE_SI_RNTI_:
|
|
sps = 14;
|
|
// for SPS=14 8 MSBs in positions 13 down to 6
|
|
monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
|
rel15->rnti = SI_RNTI; // SI-RNTI - 3GPP TS 38.321 Table 7.1-1: RNTI values
|
|
rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon;
|
|
if(mac->frequency_range == FR2)
|
|
rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2;
|
|
break;
|
|
case TYPE_SFI_RNTI_:
|
|
break;
|
|
case TYPE_INT_RNTI_:
|
|
break;
|
|
case TYPE_TPC_PUSCH_RNTI_:
|
|
break;
|
|
case TYPE_TPC_PUCCH_RNTI_:
|
|
break;
|
|
case TYPE_TPC_SRS_RNTI_:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
rel15->coreset.StartSymbolBitmap = monitoringSymbolsWithinSlot;
|
|
uint32_t Y = 0;
|
|
if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
|
|
Y = get_Y(ss, slot, rel15->rnti);
|
|
fill_dci_search_candidates(ss, rel15, Y);
|
|
// not scheduling DCI reception if there are no candidates
|
|
if (rel15->number_of_candidates == 0) {
|
|
LOG_E(NR_MAC, "No candidates in this DCI, not scheduling it");
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG_DCI
|
|
for (int i = 0; i < rel15->num_dci_options; i++) {
|
|
LOG_T(NR_MAC_DCI,
|
|
"[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d "
|
|
"rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n",
|
|
rnti_type,
|
|
rel15->BWPSize,
|
|
rel15->BWPStart,
|
|
rel15->SubcarrierSpacing,
|
|
rel15->dci_format_options[i],
|
|
rel15->dci_length_options[i],
|
|
sps,
|
|
monitoringSymbolsWithinSlot);
|
|
}
|
|
#endif
|
|
// add DCI
|
|
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI;
|
|
dl_config->number_pdus += 1;
|
|
}
|
|
|
|
bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss)
|
|
{
|
|
if (!ss)
|
|
return false;
|
|
const int duration = ss->duration ? *ss->duration : 1;
|
|
bool monitor = false;
|
|
int period, offset;
|
|
get_monitoring_period_offset(ss, &period, &offset);
|
|
// The UE monitors PDCCH candidates for search space set ss for 'duration' consecutive slots
|
|
for (int i = 0; i < duration; i++) {
|
|
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
|
|
monitor = true;
|
|
break;
|
|
}
|
|
}
|
|
return monitor;
|
|
}
|
|
|
|
bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
|
|
const NR_SearchSpace_t *ss,
|
|
const int abs_slot,
|
|
const int frame,
|
|
const int slot,
|
|
const int slots_per_frame)
|
|
{
|
|
const int duration = ss->duration ? *ss->duration : 1;
|
|
int period, offset;
|
|
get_monitoring_period_offset(ss, &period, &offset);
|
|
for (int i = 0; i < duration; i++) {
|
|
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
|
|
int N = mac->ssb_list.nb_tx_ssb;
|
|
int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb];
|
|
// numbering current frame and slot in terms of monitoring occasions in window
|
|
int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start;
|
|
int current_monitor_occasion = (rel_slot % period) + (duration * rel_slot / period);
|
|
return current_monitor_occasion % N == K;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot, int slots_per_frame)
|
|
{
|
|
if (mac->si_SchedInfo.si_window_start == -1) {
|
|
// out of window
|
|
return false;
|
|
} else if ((abs_slot - mac->si_SchedInfo.si_window_start + MAX_FRAME_NUMBER * slots_per_frame)
|
|
% (MAX_FRAME_NUMBER * slots_per_frame)
|
|
>= window_slots) {
|
|
// window expired
|
|
mac->si_SchedInfo.si_window_start = -1;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
|
|
const NR_SearchSpace_t *ss,
|
|
const int si_idx,
|
|
const int slots_per_frame,
|
|
const int frame,
|
|
const int slot)
|
|
{
|
|
// according to 5.2.2.3.2 in 331
|
|
const int abs_slot = frame * slots_per_frame + slot;
|
|
const si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx];
|
|
const int window_slots = 5 << mac->si_SchedInfo.si_WindowLength;
|
|
const int x = (config->si_WindowPosition - 1) * window_slots;
|
|
const int T = 8 << config->si_Periodicity; // radio frame periodicity
|
|
|
|
if (mac->si_SchedInfo.si_window_start == -1) {
|
|
if ((frame % T) == (x / slots_per_frame) && (slot == x % slots_per_frame))
|
|
mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number
|
|
}
|
|
if (is_window_valid(mac, window_slots, abs_slot, slots_per_frame))
|
|
return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame);
|
|
|
|
return false;
|
|
}
|
|
|
|
void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot)
|
|
{
|
|
const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
|
|
NR_BWP_Id_t dl_bwp_id = current_DL_BWP ? current_DL_BWP->bwp_id : 0;
|
|
NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[dl_bwp_id];
|
|
int scs = current_DL_BWP ? current_DL_BWP->scs : get_softmodem_params()->numerology;
|
|
const int slots_per_frame = get_slots_per_frame_from_scs(scs);
|
|
if (mac->get_sib1) {
|
|
int ssb_sc_offset_norm;
|
|
if (mac->ssb_subcarrier_offset < 24 && mac->frequency_range == FR1)
|
|
ssb_sc_offset_norm = mac->ssb_subcarrier_offset >> scs;
|
|
else
|
|
ssb_sc_offset_norm = mac->ssb_subcarrier_offset;
|
|
uint16_t ssb_offset_point_a = (mac->ssb_start_subcarrier - ssb_sc_offset_norm) / 12;
|
|
int ssb_start_symbol = get_ssb_start_symbol(mac->nr_band, scs, mac->mib_ssb);
|
|
get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config,
|
|
mac->mib_frame,
|
|
mac->mib,
|
|
slots_per_frame,
|
|
ssb_sc_offset_norm,
|
|
ssb_start_symbol,
|
|
scs,
|
|
mac->frequency_range,
|
|
mac->nr_band,
|
|
mac->mib_ssb,
|
|
1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame
|
|
ssb_offset_point_a);
|
|
if (mac->search_space_zero == NULL)
|
|
mac->search_space_zero = calloc(1, sizeof(*mac->search_space_zero));
|
|
if (mac->coreset0 == NULL)
|
|
mac->coreset0 = calloc(1, sizeof(*mac->coreset0));
|
|
fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config);
|
|
fill_searchSpaceZero(mac->search_space_zero, slots_per_frame, &mac->type0_PDCCH_CSS_config);
|
|
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, mac->search_space_zero)) {
|
|
LOG_D(NR_MAC_DCI, "Monitoring DCI for SIB1 in frame %d slot %d\n", frame, slot);
|
|
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, mac->search_space_zero);
|
|
}
|
|
}
|
|
for (int i = 0; i < MAX_SI_GROUPS; i++) {
|
|
if (!mac->get_otherSI[i])
|
|
continue;
|
|
// If searchSpaceOtherSystemInformation is set to zero,
|
|
// PDCCH monitoring occasions for SI message reception in SI-window
|
|
// are same as PDCCH monitoring occasions for SIB1
|
|
const NR_SearchSpace_t *ss = get_common_search_space(mac, pdcch_config->otherSI_SS_id == -1 ? 0 : pdcch_config->otherSI_SS_id);
|
|
// TODO configure SI-window
|
|
if (monitor_dci_for_other_SI(mac, ss, i, slots_per_frame, frame, slot)) {
|
|
LOG_D(NR_MAC_DCI, "Monitoring DCI for other SIs in frame %d slot %d\n", frame, slot);
|
|
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss);
|
|
}
|
|
}
|
|
RA_config_t *ra = &mac->ra;
|
|
if (mac->state == UE_PERFORMING_RA && ra->ra_state >= nrRA_WAIT_RAR) {
|
|
const NR_SearchSpace_t *ra_SS = get_common_search_space(mac, pdcch_config->ra_SS_id);
|
|
// if RA is ongoing use RA search space
|
|
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ra_SS)) {
|
|
nr_rnti_type_t rnti_type = 0;
|
|
if (ra->ra_type == RA_4_STEP) {
|
|
rnti_type = ra->ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_;
|
|
} else {
|
|
rnti_type = TYPE_MSGB_RNTI_;
|
|
}
|
|
config_dci_pdu(mac, dl_config, rnti_type, slot, ra_SS);
|
|
}
|
|
// If Msg3 has C-RNTI MAC CE, also monitor dedicated search spaces during contention resolution
|
|
// according to TS 38.321 section 5.1.5
|
|
if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION && mac->msg3_C_RNTI) {
|
|
for (int i = 0; i < pdcch_config->list_SS.count; i++) {
|
|
NR_SearchSpace_t *ss = pdcch_config->list_SS.array[i];
|
|
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ss))
|
|
config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, ss);
|
|
}
|
|
}
|
|
} else if (mac->state == UE_CONNECTED) {
|
|
/*
|
|
In RRC Connected state, the UE monitors for fallback DCI with C-RNTI in common and UE-specific SS.
|
|
First the UE check all UE specific SS. If no fallback DCI is configured, it configures one of following
|
|
common SS with the shown priority
|
|
1. RA SS
|
|
2. Other SI SS
|
|
3. Paging SS
|
|
4. SIB1 SS
|
|
|
|
There is a possibility that gNB could configure multiple UE-specific SS for fallback DCI or/and common SS,
|
|
and in a given slot more than one SS become active. For the moment, we assume such configuration wouldn't happen
|
|
and hence don't handle it for the sake of implementation simplicity.
|
|
*/
|
|
bool configured_fallback_dci = false;
|
|
for (int i = 0; i < pdcch_config->list_SS.count; i++) {
|
|
NR_SearchSpace_t *ss = pdcch_config->list_SS.array[i];
|
|
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ss)) {
|
|
config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, ss);
|
|
configured_fallback_dci |= (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common);
|
|
}
|
|
}
|
|
const NR_SearchSpace_t *css = NULL;
|
|
if (!configured_fallback_dci) {
|
|
#define CSS_VALID_CUR_SLOT(CSS) \
|
|
((CSS > -1) && is_ss_monitor_occasion(frame, slot, slots_per_frame, get_common_search_space(mac, CSS)))
|
|
if (CSS_VALID_CUR_SLOT(pdcch_config->ra_SS_id))
|
|
css = get_common_search_space(mac, pdcch_config->ra_SS_id);
|
|
else if (CSS_VALID_CUR_SLOT(pdcch_config->otherSI_SS_id))
|
|
css = get_common_search_space(mac, pdcch_config->otherSI_SS_id);
|
|
else if (CSS_VALID_CUR_SLOT(pdcch_config->paging_SS_id))
|
|
css = get_common_search_space(mac, pdcch_config->paging_SS_id);
|
|
#undef CSS_VALID_CUR_SLOT
|
|
else
|
|
css = mac->search_space_zero;
|
|
AssertFatal(css, "Atleast one CSS should be present in connected state\n");
|
|
config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, css);
|
|
}
|
|
}
|
|
}
|