Merge remote-tracking branch 'origin/aerial_pbbf' into integration_2025_w33 (!3556)
Introduce support for Cat-B RU using Predefined-Beam BF with Aerial L1 This merge introduces the support for BeamID based Beamforming in OAI L2 using FAPI and leveraging Aerial L1. Support for OAI L1 is not in the scope of this MR. Main changes: - Introduced a third state for the analog_beamforming parameter. 0=disabled,1=analog_bf,2=oran_bf - Correctly populated the FAPI BF PDUs (prg_size, num_prgs, dig_bf_interfaces)
This commit is contained in:
@@ -17,11 +17,13 @@ Analog beamforming implementation also allows to enable distributed antenna syst
|
||||
A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf)
|
||||
|
||||
In the `MACRLC` section of configuration files, there are three new parameters: `set_analog_beamforming`, `beam_duration` and `beams_per_period`. The explanation of these parameters is here provided:
|
||||
- `set_analog_beamforming` can be set to 1 or 0 to activate or desactivate analog beamforming (default value is 0)
|
||||
- `set_analog_beamforming` can be set a value equal to 1 or 2 to activate or 0 to desactivate analog beamforming (default value is 0)
|
||||
- `beam_duration` is the number of slots (currently minimum duration of a beam) the scheduler is tied to a beam (default value is 1)
|
||||
- `beams_per_period` is the number of concurrent beams the RU can handle in the beam duration (default value is 1)
|
||||
- `beam_weights` is a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted
|
||||
|
||||
Setting analog beamforming to 1 or 2 changes the way FAPI beam index is treated. By setting 1, we instruct L1 to look up in Hi-PHY preconfigured DBM beam index. By setting 2, we instruct L2 to directly signal to Lo-PHY the beam index (e.g. over 7.2x fronthaul).
|
||||
|
||||
DAS is enabled by setting to 1 the parameter `enable_das` in the L1 section of the configuration file. In case of DAS enabled, the field `beam_weights` in `MACRLC` section can be omitted.
|
||||
|
||||
# Implementation in OAI scheduler
|
||||
|
||||
@@ -708,7 +708,7 @@ static uint8_t pack_nr_rx_beamforming_pdu(const nfapi_nr_ul_beamforming_t *beamf
|
||||
uint8_t **ppWritePackedMsg,
|
||||
uint8_t *end)
|
||||
{ // Pack RX Beamforming PDU
|
||||
if (!(push8(beamforming_pdu->trp_scheme, ppWritePackedMsg, end) && push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end)
|
||||
if (!(push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end)
|
||||
&& push16(beamforming_pdu->prg_size, ppWritePackedMsg, end)
|
||||
&& push8(beamforming_pdu->dig_bf_interface, ppWritePackedMsg, end))) {
|
||||
return 0;
|
||||
@@ -1033,7 +1033,7 @@ uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end,
|
||||
|
||||
static uint8_t unpack_nr_rx_beamforming_pdu(nfapi_nr_ul_beamforming_t *beamforming_pdu, uint8_t **ppReadPackedMsg, uint8_t *end)
|
||||
{ // Unpack RX Beamforming PDU
|
||||
if (!(pull8(ppReadPackedMsg, &beamforming_pdu->trp_scheme, end) && pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end)
|
||||
if (!(pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end)
|
||||
&& pull16(ppReadPackedMsg, &beamforming_pdu->prg_size, end)
|
||||
&& pull8(ppReadPackedMsg, &beamforming_pdu->dig_bf_interface, end))) {
|
||||
return 0;
|
||||
|
||||
@@ -214,7 +214,7 @@ bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti
|
||||
|
||||
static bool eq_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *a, const nfapi_nr_ul_beamforming_t *b)
|
||||
{
|
||||
EQ(a->trp_scheme, b->trp_scheme);
|
||||
// EQ(a->trp_scheme, b->trp_scheme);
|
||||
EQ(a->num_prgs, b->num_prgs);
|
||||
EQ(a->prg_size, b->prg_size);
|
||||
EQ(a->dig_bf_interface, b->dig_bf_interface);
|
||||
@@ -1174,7 +1174,7 @@ void copy_dl_tti_request(const nfapi_nr_dl_tti_request_t *src, nfapi_nr_dl_tti_r
|
||||
|
||||
static void copy_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *src, nfapi_nr_ul_beamforming_t *dst)
|
||||
{
|
||||
dst->trp_scheme = src->trp_scheme;
|
||||
// dst->trp_scheme = src->trp_scheme;
|
||||
dst->num_prgs = src->num_prgs;
|
||||
dst->prg_size = src->prg_size;
|
||||
dst->dig_bf_interface = src->dig_bf_interface;
|
||||
@@ -2201,7 +2201,7 @@ void dump_dl_tti_request(const nfapi_nr_dl_tti_request_t *msg)
|
||||
|
||||
static void dump_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *pdu, int depth)
|
||||
{
|
||||
INDENTED_PRINTF("TRP Scheme = %d\n", pdu->trp_scheme);
|
||||
// INDENTED_PRINTF("TRP Scheme = %d\n", pdu->trp_scheme);
|
||||
INDENTED_PRINTF("numPRGs = %d\n", pdu->num_prgs);
|
||||
INDENTED_PRINTF("prgSize = %d\n", pdu->prg_size);
|
||||
INDENTED_PRINTF("digBFInterface = %d\n", pdu->dig_bf_interface);
|
||||
|
||||
@@ -743,31 +743,31 @@ typedef struct {
|
||||
|
||||
// 3.4.2
|
||||
|
||||
//for pdcch_pdu:
|
||||
typedef struct {
|
||||
// Index of the digital beam weight vector pre-stored at cell configuration.
|
||||
// The vector maps this input port to output TXRUs. Value: 0->65535
|
||||
uint16_t beam_idx;
|
||||
} nfapi_nr_dig_bf_interface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t beam_idx;//Index of the digital beam weight vector pre-stored at cell configuration. The vector maps this input port to output TXRUs. Value: 0->65535
|
||||
|
||||
}nfapi_nr_dig_bf_interface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pm_idx;//Index to precoding matrix (PM) pre-stored at cell configuration. Note: If precoding is not used this parameter should be set to 0. Value: 0->65535.
|
||||
nfapi_nr_dig_bf_interface_t dig_bf_interface_list[NFAPI_MAX_NUM_BG_IF];//max dig_bf_interfaces
|
||||
|
||||
}nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t;
|
||||
typedef struct {
|
||||
// Index to precoding matrix (PM) pre-stored at cell configuration.
|
||||
// Note: If precoding is not used this parameter should be set to 0. Value: 0->65535.
|
||||
uint16_t pm_idx;
|
||||
nfapi_nr_dig_bf_interface_t dig_bf_interface_list[NFAPI_MAX_NUM_BG_IF]; // max dig_bf_interfaces
|
||||
} nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t;
|
||||
|
||||
//table 3-43
|
||||
typedef struct
|
||||
{
|
||||
uint16_t num_prgs;//Number of PRGs spanning this allocation. Value : 1->275
|
||||
uint16_t prg_size;//Size in RBs of a precoding resource block group (PRG) – to which same precoding and digital beamforming gets applied. Value: 1->275
|
||||
//watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface
|
||||
uint8_t dig_bf_interfaces;//Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255
|
||||
nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[NFAPI_MAX_NUM_PRGS];//max prg_size
|
||||
|
||||
}nfapi_nr_tx_precoding_and_beamforming_t;
|
||||
typedef struct {
|
||||
// Number of PRGs spanning this allocation. Value : 1->275
|
||||
uint16_t num_prgs;
|
||||
// Size in RBs of a precoding resource block group (PRG) to which same precoding and digital beamforming gets applied.
|
||||
// Value: 1->275
|
||||
uint16_t prg_size;
|
||||
// watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface
|
||||
uint8_t dig_bf_interfaces;
|
||||
// Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255
|
||||
nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[NFAPI_MAX_NUM_PRGS]; // max prg_size
|
||||
} nfapi_nr_tx_precoding_and_beamforming_t;
|
||||
|
||||
|
||||
//table 3-37
|
||||
@@ -1212,7 +1212,7 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used.
|
||||
// uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used. Not part of FAPI 10.02, thus removed
|
||||
uint16_t num_prgs; // Number of PRGs spanning this allocation. Value : 1->275
|
||||
uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->275
|
||||
uint8_t dig_bf_interface; // Number of logical antenna ports (parallel streams) resulting from the Rx combining. Value: 0->255
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
static void fill_ul_tti_request_beamforming(nfapi_nr_ul_beamforming_t *beamforming_pdu)
|
||||
{
|
||||
beamforming_pdu->trp_scheme = rand8();
|
||||
// beamforming_pdu->trp_scheme = rand8(); // not part of 10.02
|
||||
beamforming_pdu->num_prgs = rand16_range(1, NFAPI_MAX_NUM_PRGS);
|
||||
beamforming_pdu->prg_size = rand16_range(1, 275);
|
||||
beamforming_pdu->dig_bf_interface = rand8_range(1,NFAPI_MAX_NUM_BG_IF);
|
||||
|
||||
@@ -110,6 +110,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
common_vars->analog_bf = cfg->analog_beamforming_ve.analog_bf_vendor_ext.value;
|
||||
LOG_I(PHY, "L1 configured with%s analog beamforming\n", common_vars->analog_bf ? "" : "out");
|
||||
if (common_vars->analog_bf) {
|
||||
// True only if nrmac->beam_info.beam_mode == FAPI_ANALOG_BEAM, thus analog_beamforming=2
|
||||
common_vars->num_beams_period = cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value;
|
||||
LOG_I(PHY, "Max number of concurrent beams: %d\n", common_vars->num_beams_period);
|
||||
} else
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
{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_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_ANALOG_BEAMFORMING, HLP_MACRLC_AB, 0, .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}, \
|
||||
{CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY,0}, \
|
||||
|
||||
@@ -1787,15 +1787,19 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
LOG_I(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_ulprbbl);
|
||||
memcpy(RC.nrmac[j]->ulprbbl, prbbl, MAX_BWP_SIZE * sizeof(prbbl[0]));
|
||||
}
|
||||
bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
|
||||
if (ab) {
|
||||
AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n");
|
||||
int ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
|
||||
if (ab > 0) {
|
||||
if (ab == 1)
|
||||
AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n");
|
||||
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
|
||||
beam_info->beam_mode = ab == 1 ? PRECONFIGURED_BEAM_IDX : LOPHY_BEAM_IDX;
|
||||
} else {
|
||||
RC.nrmac[j]->beam_info.beam_mode = NO_BEAM_MODE;
|
||||
}
|
||||
// TODO config_isparamset doesn't seem to work for array types, checking numelt instead
|
||||
int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt;
|
||||
|
||||
@@ -711,7 +711,7 @@ static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR
|
||||
cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts);
|
||||
|
||||
int nb_beams = config->nb_bfw[1]; // number of beams
|
||||
if (nrmac->beam_info.beam_allocation) {
|
||||
if (nrmac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX) {
|
||||
LOG_I(NR_MAC, "Configuring analog beamforming in config_request message\n");
|
||||
cfg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag = NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value = nrmac->beam_info.beams_per_period;
|
||||
@@ -771,7 +771,7 @@ static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR
|
||||
|
||||
static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int slots_per_frame)
|
||||
{
|
||||
if (!beam_info->beam_allocation)
|
||||
if (beam_info->beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
|
||||
int size = mu == 0 ? slots_per_frame << 1 : slots_per_frame;
|
||||
@@ -848,7 +848,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
nrmac->vrb_map_UL_size = size;
|
||||
|
||||
int num_beams = 1;
|
||||
if(nrmac->beam_info.beam_allocation)
|
||||
if(nrmac->beam_info.beam_mode != NO_BEAM_MODE)
|
||||
num_beams = nrmac->beam_info.beams_per_period;
|
||||
for (int i = 0; i < num_beams; i++) {
|
||||
nrmac->common_channels[0].vrb_map_UL[i] = calloc(size * MAX_BWP_SIZE, sizeof(uint16_t));
|
||||
@@ -865,7 +865,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
LOG_D(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
|
||||
|
||||
config_common(nrmac, config, scc);
|
||||
fapi_beam_index_allocation(scc, nrmac);
|
||||
fapi_beam_index_allocation(scc, config, nrmac);
|
||||
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
// nothing to be sent in the other cases
|
||||
|
||||
@@ -108,7 +108,7 @@ static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slo
|
||||
{
|
||||
// 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)
|
||||
if (beam_info->beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
// initialization done only once
|
||||
AssertFatal(beam_info->beam_allocation_size >= 0, "Beam information not initialized\n");
|
||||
@@ -179,7 +179,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
|
||||
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
int num_beams = 1;
|
||||
if(gNB->beam_info.beam_allocation)
|
||||
if(gNB->beam_info.beam_mode != NO_BEAM_MODE)
|
||||
num_beams = gNB->beam_info.beams_per_period;
|
||||
// clear vrb_maps
|
||||
for (int i = 0; i < num_beams; i++)
|
||||
|
||||
@@ -368,6 +368,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
uint16_t RA_sfn_index = -1;
|
||||
frequency_range_t freq_range = get_freq_range_from_arfcn(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
|
||||
const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
if (get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type)) {
|
||||
uint16_t format0 = cc->prach_info.format & 0xff; // first column of format from table
|
||||
uint16_t format1 = (cc->prach_info.format >> 8) & 0xff; // second column of format from table
|
||||
@@ -505,8 +507,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
}
|
||||
}
|
||||
prach_pdu->num_prach_ocas = num_td_occ;
|
||||
prach_pdu->beamforming.num_prgs = 0;
|
||||
prach_pdu->beamforming.prg_size = 0;
|
||||
prach_pdu->beamforming.num_prgs = 1;
|
||||
prach_pdu->beamforming.prg_size = n_ra_rb;
|
||||
prach_pdu->beamforming.dig_bf_interface = num_td_occ;
|
||||
prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[num_td_occ - 1].beam_idx = beam_index;
|
||||
|
||||
@@ -527,8 +529,6 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
}
|
||||
|
||||
// block resources in vrb_map_UL
|
||||
const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
// mark PRBs as occupied for current and future slots if prach extends beyond current slot
|
||||
int total_prach_slots;
|
||||
uint32_t N_dur = cc->prach_info.N_dur;
|
||||
|
||||
@@ -79,7 +79,7 @@ static void schedule_ssb(frame_t frame,
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = payload;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size = 275; //1 PRG of max size for analogue beamforming
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size = 20; //SSB is always 20RBs
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
|
||||
@@ -993,10 +993,10 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu
|
||||
pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(pdsch_pdu->mcsTable[0], dl_bw_tbslbrm, nl_tbslbrm);
|
||||
pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pdsch->tb_size << 3, sched_pdsch->R);
|
||||
// Precoding and beamforming
|
||||
pdsch_pdu->precodingAndBeamforming.num_prgs = 0;
|
||||
pdsch_pdu->precodingAndBeamforming.num_prgs = 1;
|
||||
pdsch_pdu->precodingAndBeamforming.prg_size = pdsch_pdu->rbSize;
|
||||
pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 0;
|
||||
pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index;
|
||||
pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 1;
|
||||
pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index;
|
||||
pdsch_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
return pdsch_pdu;
|
||||
}
|
||||
|
||||
@@ -424,6 +424,27 @@ static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
|
||||
AssertFatal(false, "Couldn't find an adequate SearchSpace for target SearchSpace %d in ServingCellConfigCommon\n", target_ss);
|
||||
}
|
||||
|
||||
/// @brief Get CORESET resource block parameters from frequency domain resources bitmap.
|
||||
/// @param coreset Pointer to the CORESET configuratio
|
||||
/// @param n_rb Output parameter for total # of RBs in the CORESET
|
||||
/// @param rb_start Output parameter for the starting resource block index of the CORESET
|
||||
static void get_coreset_rb_params(const NR_ControlResourceSet_t *coreset, uint16_t *n_rb, uint16_t *rb_start)
|
||||
{
|
||||
*n_rb = 0;
|
||||
*rb_start = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int t = 0; t < 8; t++) {
|
||||
if ((coreset->frequencyDomainResources.buf[i] >> (7 - t)) & 1) {
|
||||
if (*n_rb == 0) {
|
||||
*rb_start = 48 * i + t * 6;
|
||||
}
|
||||
*n_rb += 6; // Each bit represents 6 RBs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac,
|
||||
NR_SearchSpace_t *ss,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
@@ -492,21 +513,7 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac,
|
||||
pdcch.ShiftIndex = 0;
|
||||
}
|
||||
|
||||
uint16_t N_rb = 0; // nb of rbs of coreset per symbol
|
||||
uint16_t rb_start = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int t = 0; t < 8; t++) {
|
||||
if (coreset->frequencyDomainResources.buf[i] >> (7 - t) & 1) {
|
||||
if (N_rb == 0) {
|
||||
rb_start = 48 * i + t * 6;
|
||||
}
|
||||
N_rb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdcch.rb_start = rb_start;
|
||||
pdcch.n_rb = N_rb *= 6; // each bit of frequencyDomainResources represents 6 PRBs
|
||||
get_coreset_rb_params(coreset, &pdcch.n_rb, &pdcch.rb_start);
|
||||
|
||||
return pdcch;
|
||||
}
|
||||
@@ -818,10 +825,15 @@ nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_
|
||||
dci_pdu->ScramblingId = *scc->physCellId;
|
||||
dci_pdu->ScramblingRNTI = 0;
|
||||
}
|
||||
|
||||
uint16_t N_rb = 0;
|
||||
uint16_t rb_start = 0;
|
||||
get_coreset_rb_params(coreset, &N_rb, &rb_start);
|
||||
|
||||
dci_pdu->beta_PDCCH_1_0 = 0;
|
||||
dci_pdu->powerControlOffsetSS = 1;
|
||||
dci_pdu->precodingAndBeamforming.num_prgs = 0;
|
||||
dci_pdu->precodingAndBeamforming.prg_size = 0;
|
||||
dci_pdu->precodingAndBeamforming.num_prgs = 1;
|
||||
dci_pdu->precodingAndBeamforming.prg_size = N_rb;
|
||||
dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1;
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0;
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
@@ -1245,9 +1257,9 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu,
|
||||
pucch_pdu->prb_size=1;
|
||||
}
|
||||
// Beamforming
|
||||
pucch_pdu->beamforming.num_prgs = 0;
|
||||
pucch_pdu->beamforming.prg_size = 0; // pucch_pdu->prb_size;
|
||||
pucch_pdu->beamforming.dig_bf_interface = 0;
|
||||
pucch_pdu->beamforming.num_prgs = 1;
|
||||
pucch_pdu->beamforming.prg_size = pucch_pdu->prb_size;
|
||||
pucch_pdu->beamforming.dig_bf_interface = 1;
|
||||
pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
|
||||
}
|
||||
|
||||
@@ -3342,8 +3354,10 @@ int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx)
|
||||
|
||||
// TODO this is a placeholder for a possibly more complex function
|
||||
// for now the fapi beam index is the number of SSBs transmitted before ssb_index i
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac)
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac)
|
||||
{
|
||||
if (mac->beam_info.beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
int len = 0;
|
||||
uint8_t* buf = NULL;
|
||||
switch (scc->ssb_PositionsInBurst->present) {
|
||||
@@ -3362,11 +3376,13 @@ void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST
|
||||
default :
|
||||
AssertFatal(false, "Invalid configuration\n");
|
||||
}
|
||||
int fapi_index = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if ((buf[i / 8] >> (7 - i % 8)) & 0x1)
|
||||
mac->fapi_beam_index[i] = fapi_index++;
|
||||
else
|
||||
if ((buf[i / 8] >> (7 - i % 8)) & 0x1) {
|
||||
int fapi_index = mac->beam_info.beam_mode == LOPHY_BEAM_IDX ? config->bw_list[index] : index;
|
||||
mac->fapi_beam_index[i] = fapi_index;
|
||||
index++;
|
||||
} else
|
||||
mac->fapi_beam_index[i] = -1;
|
||||
}
|
||||
}
|
||||
@@ -3379,7 +3395,7 @@ static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int
|
||||
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)
|
||||
if (beam_info->beam_mode == NO_BEAM_MODE)
|
||||
return (NR_beam_alloc_t) {.new_beam = false, .idx = 0};
|
||||
|
||||
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
|
||||
@@ -3413,7 +3429,7 @@ void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_
|
||||
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
|
||||
{
|
||||
// do not perform beam procedures if there is no beam information
|
||||
if (!mac->beam_info.beam_allocation)
|
||||
if (mac->beam_info.beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
RSRP_report_t *rsrp_report = &UE->UE_sched_ctrl.CSI_report.ssb_rsrp_report;
|
||||
// simple beam switching algorithm -> we select beam with highest RSRP from CSI report
|
||||
|
||||
@@ -463,9 +463,9 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac,
|
||||
srs_pdu->srs_parameters_v4.prg_size = 1;
|
||||
srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1 << srs_pdu->num_ant_ports;
|
||||
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) {
|
||||
srs_pdu->beamforming.trp_scheme = 0;
|
||||
// srs_pdu->beamforming.trp_scheme = 0;
|
||||
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
|
||||
srs_pdu->beamforming.prg_size = 1;
|
||||
srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size;
|
||||
}
|
||||
srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame);
|
||||
|
||||
@@ -2311,8 +2311,8 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti
|
||||
pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size;
|
||||
pusch_pdu->pusch_data.num_cb = 0; // CBG not supported
|
||||
// Beamforming
|
||||
pusch_pdu->beamforming.num_prgs = 0;
|
||||
pusch_pdu->beamforming.prg_size = 0; // bwp_size;
|
||||
pusch_pdu->beamforming.num_prgs = 1;
|
||||
pusch_pdu->beamforming.prg_size = pusch_pdu->bwp_size;
|
||||
pusch_pdu->beamforming.dig_bf_interface = 1;
|
||||
pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
|
||||
/* TRANSFORM PRECODING --------------------------------------------------------*/
|
||||
|
||||
@@ -451,7 +451,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
|
||||
int ul_buffer_index(int frame, int slot, int slots_per_frame, int size);
|
||||
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac);
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac);
|
||||
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx);
|
||||
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);
|
||||
|
||||
@@ -787,12 +787,19 @@ typedef struct {
|
||||
uid_allocator_t uid_allocator;
|
||||
} NR_UEs_t;
|
||||
|
||||
typedef enum {
|
||||
NO_BEAM_MODE,
|
||||
PRECONFIGURED_BEAM_IDX,
|
||||
LOPHY_BEAM_IDX,
|
||||
} nr_beam_mode_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_mode_t beam_mode;
|
||||
} NR_beam_info_t;
|
||||
|
||||
#define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
|
||||
|
||||
Reference in New Issue
Block a user