Merge remote-tracking branch 'origin/fapi-beamid' into integration_2025_w51 (!3715)

Pass beam ID as per FAPI v222.10

This MR
1. Sets MSB of beam ID when passing beam ID to 7.2 radio
2. Modifies phytest scheduler to allocate SSBs on different beams
3. Introduce new MAC config parameter for beam mode to specify HiPHY or LoPHY
   beamforming
This commit is contained in:
Jaroslava Fiedlerova
2025-12-17 10:11:22 +01:00
31 changed files with 239 additions and 308 deletions
@@ -172,7 +172,7 @@ MACRLCs = ({
tr_n_preference = "local_RRC"; tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 200; pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200;
set_analog_beamforming = 1; set_analog_beamforming = 2;
beam_duration = 1; beam_duration = 1;
beams_per_period = 1; beams_per_period = 1;
beam_weights = [0]; // single SSB -> one analog beam beam_weights = [0]; // single SSB -> one analog beam
+2 -2
View File
@@ -33,8 +33,8 @@ extern "C" {
__typeof__ (b) _b = (b); \ __typeof__ (b) _b = (b); \
_a < _b ? _a : _b; }) _a < _b ? _a : _b; })
#define IS_BIT_SET(a, b) ((a >> b) & 1)
#define SET_BIT(a, b) (a | (1 << b))
#ifdef __cplusplus #ifdef __cplusplus
#ifdef min #ifdef min
+14 -5
View File
@@ -34,17 +34,26 @@ To this goal, we extended the virtual resource block (VRB) map by one dimension
It is important to note that in current implementation, there are several periodical channels, e.g. PRACH or PUCCH for CSI et cetera, that have the precendence in being assigned a beam, that is because the scheduling is automatic, set in RRC configuration, and not up to the scheduler. For these instances, we assume the beam is available (if not there are assertions to stop the process). For data channels, the currently implemented PF scheduler is used. The only modification is that a UE can be served only if there is a free beam available or the one of the beams already in use correspond to that UE beam. It is important to note that in current implementation, there are several periodical channels, e.g. PRACH or PUCCH for CSI et cetera, that have the precendence in being assigned a beam, that is because the scheduling is automatic, set in RRC configuration, and not up to the scheduler. For these instances, we assume the beam is available (if not there are assertions to stop the process). For data channels, the currently implemented PF scheduler is used. The only modification is that a UE can be served only if there is a free beam available or the one of the beams already in use correspond to that UE beam.
## Beams in phy-test scheduler
In phy-test mode, beams are assigned to PDSCH slots in the same manner as SSB slots with the only addition that it repeats for every TDD period in a frame. For example if PDSCH is scheduled on all DL slot for TDD format DDDDDDDSUU, and with SSB bit map = `0b1010101` and the following beam parameters in config file,
- `beam_weights` = [10,11,12,13]
- `beam_duration` = 1
- `beams_per_period` = 1
The DL slots in every TDD period will have beams 10,11,12,13,0,0,0
# FAPI implementation # FAPI implementation
To be noted that in our implementation analog beamforming is only supported in non-split/monolithic mode because we don't support yet SCF P19 interface that would be needed to manage these procedure in a split scenario with SCF FAPI. To be noted that in our implementation analog beamforming is only partially supported in split mode.
The index based beamforming relies on the Tx precoding and beamforming PDU definition of beam-ID, where MSB is used to signal if the ID can be directly used or is it a pointer to a pre-stored vector of weights.
This definition of beam-ID is present only in the most recent versions of SCF PHY API specifications (at least from v8 and later, possibly from v6).
In `config_request` structure, a vendor extension (`nfapi_nr_analog_beamforming_ve_t`) configures the lower layers at initialization with the following information: In addition to that, a `config_request` structure defined as vendor extension (`nfapi_nr_analog_beamforming_ve_t`) configures the lower layers at initialization with the following information:
- `analog_bf_vendor_ext` which can assume values 1 or 0 for enabling or disabling analog beamforming - `analog_bf_vendor_ext` which can assume values 1 or 0 for enabling or disabling analog beamforming
- `num_beams_period_vendor_ext` which corresponds to the configuration parameter `beams_per_period` - `num_beams_period_vendor_ext` which corresponds to the configuration parameter `beams_per_period`
- `total_num_beams_vendor_ext` which corresponds to the number of beams configured in `beam_weights`
- `analog_beam_list` which contains the RU beamforming indices configured in `beam_weights`
Additionally, L2 provides in each channel FAPI message information about the beam index. Small Cell Forum (SCF) FAPI provides in its PHY API specifications for the channels only a field for digital beamforming as part of the `precoding_and_beamforming` stucture. Therefore without a better option, we are currently using that one to store the internal analog beamforming index. This is the index used internally by the code to progressively identify the beam with a value from 0 to `total_num_beams_vendor_ext`. Therefore, in case of analog beamforming, L2 provides in each channel FAPI message information about the beam index via the beam-ID parameter with MSB set to 1.
# L1 implementation # L1 implementation
+3 -4
View File
@@ -117,10 +117,9 @@ static void tx_func(processingData_L1tx_t *info)
pushNotifiedFIFO(&gNB->resp_L1, res); pushNotifiedFIFO(&gNB->resp_L1, res);
int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx); int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx);
// TODO check for analog_beam_list is a workaround while no beam API for beam // TODO check for analog_bf_vendor_ext set to 1 is a workaround while no beam API for beam selection is implemented
// selection is implemented if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_RFSIM || cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) {
|| cfg->analog_beamforming_ve.analog_beam_list) {
start_meas(&info->gNB->phy_proc_tx); start_meas(&info->gNB->phy_proc_tx);
phy_procedures_gNB_TX(info->gNB, phy_procedures_gNB_TX(info->gNB,
&sched_response.DL_req, &sched_response.DL_req,
+6 -47
View File
@@ -1229,33 +1229,6 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
// only increase if it was set // only increase if it was set
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG; numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
AssertFatal(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == 0,
"Total num beams Vendor extension shouldn't be set!");
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
retval &= pack_nr_tlv(NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
// only increase if it was set
numTLVs +=
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
for (int beam = 0; beam < pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value; beam++) {
AssertFatal(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam].tl.tag == 0,
"Analog beams list Vendor extension shouldn't be set!");
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
retval &= pack_nr_tlv(NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam]),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
// only increase if it was set
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
}
pNfapiMsg->num_tlv = numTLVs; pNfapiMsg->num_tlv = numTLVs;
retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end); retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end);
return retval; return retval;
@@ -1357,7 +1330,6 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
int tdd_periodicity_idx = 0; int tdd_periodicity_idx = 0;
int symbol_per_slot_idx = 0; int symbol_per_slot_idx = 0;
#endif #endif
int beam_ve_idx = 0;
nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg; nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
// unpack TLVs // unpack TLVs
@@ -1417,10 +1389,12 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
{NFAPI_NR_CONFIG_TDD_TABLE, NULL, &unpack_nr_tdd_table_10_04}, {NFAPI_NR_CONFIG_TDD_TABLE, NULL, &unpack_nr_tdd_table_10_04},
#endif #endif
#endif #endif
{NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext), &unpack_uint8_tlv_value}, {NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG,
{NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext), &unpack_uint8_tlv_value}, &(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext),
{NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value}, &unpack_uint8_tlv_value},
{NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value}, {NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext),
&unpack_uint8_tlv_value},
{NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value}, {NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
{NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value}, {NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value},
{NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_tlv_value}, {NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_tlv_value},
@@ -1463,21 +1437,6 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
} }
int result = 0; int result = 0;
switch (generic_tl.tag) { switch (generic_tl.tag) {
case NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG:
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = generic_tl.tag;
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.length = generic_tl.length;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext, ppReadPackedMsg, end);
pNfapiMsg->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
beam_ve_idx = 0;
break;
case NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG:
unpack_fns[idx].tlv = &pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx];
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.tag = generic_tl.tag;
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.length = generic_tl.length;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx], ppReadPackedMsg, end);
beam_ve_idx ++;
break;
case NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG: case NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG:
unpack_fns[idx].tlv = &generic_tl; unpack_fns[idx].tlv = &generic_tl;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end); result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end);
@@ -315,12 +315,6 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const
EQ_TLV(unpacked_req->analog_beamforming_ve.analog_bf_vendor_ext, req->analog_beamforming_ve.analog_bf_vendor_ext); EQ_TLV(unpacked_req->analog_beamforming_ve.analog_bf_vendor_ext, req->analog_beamforming_ve.analog_bf_vendor_ext);
EQ_TLV(unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext, req->analog_beamforming_ve.total_num_beams_vendor_ext);
for (int i = 0; i < unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
EQ_TLV(unpacked_req->analog_beamforming_ve.analog_beam_list[i], req->analog_beamforming_ve.analog_beam_list[i]);
}
return true; return true;
} }
@@ -464,10 +458,6 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg)
free(msg->dbt_config.dig_beam_list); free(msg->dbt_config.dig_beam_list);
free(msg->pmi_list.pmi_pdu); free(msg->pmi_list.pmi_pdu);
if (msg->analog_beamforming_ve.analog_beam_list) {
free(msg->analog_beamforming_ve.analog_beam_list);
}
} }
void free_config_response(nfapi_nr_config_response_scf_t *msg) void free_config_response(nfapi_nr_config_response_scf_t *msg)
@@ -895,17 +885,6 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf
COPY_TLV(dst->analog_beamforming_ve.num_beams_period_vendor_ext, src->analog_beamforming_ve.num_beams_period_vendor_ext); COPY_TLV(dst->analog_beamforming_ve.num_beams_period_vendor_ext, src->analog_beamforming_ve.num_beams_period_vendor_ext);
COPY_TLV(dst->analog_beamforming_ve.analog_bf_vendor_ext, src->analog_beamforming_ve.analog_bf_vendor_ext); COPY_TLV(dst->analog_beamforming_ve.analog_bf_vendor_ext, src->analog_beamforming_ve.analog_bf_vendor_ext);
COPY_TLV(dst->analog_beamforming_ve.total_num_beams_vendor_ext, src->analog_beamforming_ve.total_num_beams_vendor_ext);
if (dst->analog_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
dst->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
dst->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
for (int i = 0; i < src->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
COPY_TLV(dst->analog_beamforming_ve.analog_beam_list[i], src->analog_beamforming_ve.analog_beam_list[i]);
}
}
} }
void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst) void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst)
+13 -3
View File
@@ -236,6 +236,12 @@ bool fapi_nr_p7_message_unpack(void *pMessageBuf,
return true; return true;
} }
#ifndef ENABLE_AERIAL
#define PARSE_BEAMID(a) (a)
#else
#define PARSE_BEAMID(a) ((a) & 0x7fff)
#endif
static uint8_t pack_nr_tx_beamforming_pdu(const nfapi_nr_tx_precoding_and_beamforming_t *beamforming_pdu, static uint8_t pack_nr_tx_beamforming_pdu(const nfapi_nr_tx_precoding_and_beamforming_t *beamforming_pdu,
uint8_t **ppWritePackedMsg, uint8_t **ppWritePackedMsg,
uint8_t *end) uint8_t *end)
@@ -249,7 +255,9 @@ static uint8_t pack_nr_tx_beamforming_pdu(const nfapi_nr_tx_precoding_and_beamfo
return 0; return 0;
} }
for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interfaces; digBFInterface++) { for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interfaces; digBFInterface++) {
if (!push16(beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { if (!push16(PARSE_BEAMID(beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx),
ppWritePackedMsg,
end)) {
return 0; return 0;
} }
} }
@@ -715,7 +723,9 @@ static uint8_t pack_nr_rx_beamforming_pdu(const nfapi_nr_ul_beamforming_t *beamf
} }
for (int prg = 0; prg < beamforming_pdu->num_prgs; prg++) { for (int prg = 0; prg < beamforming_pdu->num_prgs; prg++) {
for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interface; digBFInterface++) { for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interface; digBFInterface++) {
if (!push16(beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { if (!push16(PARSE_BEAMID(beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx),
ppWritePackedMsg,
end)) {
return 0; return 0;
} }
} }
@@ -1400,7 +1410,7 @@ static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg,
return 0; return 0;
} }
for (int digInt = 0; digInt < beamforming->dig_bf_interfaces; digInt++) { for (int digInt = 0; digInt < beamforming->dig_bf_interfaces; digInt++) {
if (!push16(beamforming->prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, ppWritePackedMsg, end)) { if (!push16(PARSE_BEAMID(beamforming->prgs_list[prg].dig_bf_interface_list[digInt].beam_idx), ppWritePackedMsg, end)) {
return 0; return 0;
} }
} }
@@ -31,9 +31,6 @@
#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120 #define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120
#define NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG 0xA000 #define NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG 0xA000
#define NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG 0xA001 #define NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG 0xA001
#define NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG 0xA002
#define NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG 0xA003
typedef struct { typedef struct {
uint16_t phy_id; uint16_t phy_id;
@@ -512,8 +512,6 @@ typedef struct {
typedef struct { typedef struct {
nfapi_uint8_tlv_t num_beams_period_vendor_ext; nfapi_uint8_tlv_t num_beams_period_vendor_ext;
nfapi_uint8_tlv_t analog_bf_vendor_ext; nfapi_uint8_tlv_t analog_bf_vendor_ext;
nfapi_uint8_tlv_t total_num_beams_vendor_ext;
nfapi_uint8_tlv_t *analog_beam_list;
} nfapi_nr_analog_beamforming_ve_t; } nfapi_nr_analog_beamforming_ve_t;
// ERROR enums // ERROR enums
+5 -20
View File
@@ -285,12 +285,10 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap
FILL_TLV(nfapi_resp->nfapi_config.timing_info_period, NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, rand8()); FILL_TLV(nfapi_resp->nfapi_config.timing_info_period, NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, rand8());
nfapi_resp->num_tlv++; nfapi_resp->num_tlv++;
/* /*
// TODO: Uncomment this block when ready to enable the pack of the following VE TLVs in nr_fapi_p5.c // TODO: Uncomment this block when ready to enable the pack of the following VE TLVs in nr_fapi_p5.c
// NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG // NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG
// NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG // NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG
// NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG
// NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG
FILL_TLV(nfapi_resp->analog_beamforming_ve.num_beams_period_vendor_ext, FILL_TLV(nfapi_resp->analog_beamforming_ve.num_beams_period_vendor_ext,
NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG,
rand8()); rand8());
@@ -298,20 +296,7 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap
FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_bf_vendor_ext, NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, rand8()); FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_bf_vendor_ext, NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, rand8());
nfapi_resp->num_tlv++; nfapi_resp->num_tlv++;
*/
FILL_TLV(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext,
NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
rand8());
nfapi_resp->num_tlv++;
if (nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
nfapi_resp->analog_beamforming_ve.analog_beam_list =
(nfapi_uint8_tlv_t *)malloc(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
for (int i = 0; i < nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_beam_list[i], NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, rand8());
nfapi_resp->num_tlv++;
}
}*/
} }
static void test_pack_unpack(nfapi_nr_config_request_scf_t *req) static void test_pack_unpack(nfapi_nr_config_request_scf_t *req)
-1
View File
@@ -83,7 +83,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
int bitmap = SL_to_bitmap(cset_start_symb, pdcch_pdu_rel15->DurationSymbols); int bitmap = SL_to_bitmap(cset_start_symb, pdcch_pdu_rel15->DurationSymbols);
int beam_nb = beam_index_allocation(gNB->enable_analog_das, int beam_nb = beam_index_allocation(gNB->enable_analog_das,
dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx, dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,
&gNB->gNB_config.analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
frame_parms->symbols_per_slot, frame_parms->symbols_per_slot,
-1
View File
@@ -681,7 +681,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols); int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
int beam_nb = beam_index_allocation(gNB->enable_analog_das, int beam_nb = beam_index_allocation(gNB->enable_analog_das,
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
&gNB->gNB_config.analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
frame_parms->symbols_per_slot, frame_parms->symbols_per_slot,
-1
View File
@@ -103,7 +103,6 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n
int bitmap = SL_to_bitmap(start_symb, n_symb); int bitmap = SL_to_bitmap(start_symb, n_symb);
prach->beams[i] = beam_index_allocation(gNB->enable_analog_das, prach->beams[i] = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx, fapi_beam_idx,
&gNB->gNB_config.analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
Slot, Slot,
NR_NUMBER_OF_SYMBOLS_PER_SLOT, NR_NUMBER_OF_SYMBOLS_PER_SLOT,
-1
View File
@@ -158,7 +158,6 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t
int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols); int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols);
ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das, ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx, fapi_beam_idx,
&gNB->gNB_config.analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
NR_NUMBER_OF_SYMBOLS_PER_SLOT, NR_NUMBER_OF_SYMBOLS_PER_SLOT,
-1
View File
@@ -71,7 +71,6 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t
int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols);
pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das, pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx, fapi_beam_idx,
&gNB->gNB_config.analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
NR_NUMBER_OF_SYMBOLS_PER_SLOT, NR_NUMBER_OF_SYMBOLS_PER_SLOT,
-1
View File
@@ -60,7 +60,6 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu
int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
srs->beam_nb = beam_index_allocation(gNB->enable_analog_das, srs->beam_nb = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx, fapi_beam_idx,
&gNB->gNB_config.analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
NR_NUMBER_OF_SYMBOLS_PER_SLOT, NR_NUMBER_OF_SYMBOLS_PER_SLOT,
+2 -4
View File
@@ -66,7 +66,6 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB,
int beam_index_allocation(bool das, int beam_index_allocation(bool das,
int fapi_beam_index, int fapi_beam_index,
const nfapi_nr_analog_beamforming_ve_t *analog_bf,
NR_gNB_COMMON *common_vars, NR_gNB_COMMON *common_vars,
int slot, int slot,
int symbols_per_slot, int symbols_per_slot,
@@ -77,7 +76,8 @@ int beam_index_allocation(bool das,
if (das) if (das)
return fapi_beam_index; return fapi_beam_index;
int ru_beam_idx = analog_bf->analog_beam_list[fapi_beam_index].value; AssertFatal(IS_BIT_SET(fapi_beam_index, 15), "Can't handle preconfigured DBM yet\n");
int ru_beam_idx = fapi_beam_index & 0x7fff;
int idx = -1; int idx = -1;
for (int j = 0; j < common_vars->num_beams_period; j++) { for (int j = 0; j < common_vars->num_beams_period; j++) {
// L2 analog beam implementation is slot based, so we need to verify occupancy for the whole slot // L2 analog beam implementation is slot based, so we need to verify occupancy for the whole slot
@@ -160,7 +160,6 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols
int beam_nb = beam_index_allocation(gNB->enable_analog_das, int beam_nb = beam_index_allocation(gNB->enable_analog_das,
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
&cfg->analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
fp->symbols_per_slot, fp->symbols_per_slot,
@@ -229,7 +228,6 @@ static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB,
csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j]; csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j];
int beam_nb = beam_index_allocation(gNB->enable_analog_das, int beam_nb = beam_index_allocation(gNB->enable_analog_das,
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
&cfg->analog_beamforming_ve,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
gNB->frame_parms.symbols_per_slot, gNB->frame_parms.symbols_per_slot,
-1
View File
@@ -56,7 +56,6 @@ void nr_phy_free_RU(RU_t *ru);
void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot); void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot);
int beam_index_allocation(bool das, int beam_index_allocation(bool das,
int fapi_beam_index, int fapi_beam_index,
const nfapi_nr_analog_beamforming_ve_t *analog_bf,
NR_gNB_COMMON *common_vars, NR_gNB_COMMON *common_vars,
int slot, int slot,
int symbols_per_slot, int symbols_per_slot,
+2 -1
View File
@@ -1630,10 +1630,11 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n"); AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n");
NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info; 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; 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_allocation = malloc16(beams_per_period * sizeof(beam_info->beam_allocation));
beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAM_DURATION_IDX].u8ptr; beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAM_DURATION_IDX].u8ptr;
beam_info->beams_per_period = beams_per_period; 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_allocation_size = -1; // to be initialized once we have information on frame configuration
// TODO: Indicate this to MAC via FAPI TLV 0x0164.
beam_info->beam_mode = ab == 1 ? PRECONFIGURED_BEAM_IDX : LOPHY_BEAM_IDX; beam_info->beam_mode = ab == 1 ? PRECONFIGURED_BEAM_IDX : LOPHY_BEAM_IDX;
} else { } else {
RC.nrmac[j]->beam_info.beam_mode = NO_BEAM_MODE; RC.nrmac[j]->beam_info.beam_mode = NO_BEAM_MODE;
+2 -11
View File
@@ -708,7 +708,6 @@ static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR
// 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);
int nb_beams = config->nb_bfw[1]; // number of beams
if (nrmac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX) { if (nrmac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX) {
LOG_I(NR_MAC, "Configuring analog beamforming in config_request message\n"); 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.tl.tag = NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
@@ -717,14 +716,6 @@ static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR
cfg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG; cfg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 1; // analog BF enabled cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 1; // analog BF enabled
cfg->num_tlv++; cfg->num_tlv++;
cfg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
cfg->analog_beamforming_ve.total_num_beams_vendor_ext.value = nb_beams;
cfg->num_tlv++;
cfg->analog_beamforming_ve.analog_beam_list = malloc16(nb_beams * sizeof(*cfg->analog_beamforming_ve.analog_beam_list));
for (int i = 0; i < nb_beams; i++) {
cfg->analog_beamforming_ve.analog_beam_list[i].tl.tag = NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG;
cfg->analog_beamforming_ve.analog_beam_list[i].value = config->bw_list[i];
}
} else { } else {
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 0; // analog BF disabled cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 0; // analog BF disabled
if (NFAPI_MODE == NFAPI_MONOLITHIC) { if (NFAPI_MODE == NFAPI_MONOLITHIC) {
@@ -780,7 +771,7 @@ static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int s
slots_per_frame); slots_per_frame);
beam_info->beam_allocation_size = size / beam_info->beam_duration; beam_info->beam_allocation_size = size / beam_info->beam_duration;
for (int i = 0; i < beam_info->beams_per_period; i++) { for (int i = 0; i < beam_info->beams_per_period; i++) {
beam_info->beam_allocation[i] = malloc16(beam_info->beam_allocation_size * sizeof(int)); beam_info->beam_allocation[i] = malloc16(beam_info->beam_allocation_size * sizeof(*beam_info->beam_allocation));
for (int j = 0; j < beam_info->beam_allocation_size; j++) for (int j = 0; j < beam_info->beam_allocation_size; j++)
beam_info->beam_allocation[i][j] = -1; beam_info->beam_allocation[i][j] = -1;
} }
@@ -885,7 +876,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"); LOG_D(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
config_common(nrmac, config, scc); config_common(nrmac, config, scc);
fapi_beam_index_allocation(scc, config, nrmac); fill_beam_index_list(scc, config, nrmac);
if (NFAPI_MODE == NFAPI_MONOLITHIC) { if (NFAPI_MODE == NFAPI_MONOLITHIC) {
// nothing to be sent in the other cases // nothing to be sent in the other cases
+16 -23
View File
@@ -421,7 +421,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
// ordered ssb number // ordered ssb number
int n_ssb = (int) (prach_occasion_id / (int)(1 / num_ssb_per_RO)) % cc->num_active_ssb; int n_ssb = (int) (prach_occasion_id / (int)(1 / num_ssb_per_RO)) % cc->num_active_ssb;
// fapi beam index // fapi beam index
beam_index = get_fapi_beamforming_index(gNB, cc->ssb_index[n_ssb]); beam_index = get_beam_from_ssbidx(gNB, cc->ssb_index[n_ssb]);
// multi-beam allocation structure // multi-beam allocation structure
beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_frame); beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to %d SSB transmitted in any available beam\n", n_ssb + 1); AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to %d SSB transmitted in any available beam\n", n_ssb + 1);
@@ -429,7 +429,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
int first_ssb_index = (prach_occasion_id * (int)num_ssb_per_RO) % cc->num_active_ssb; int first_ssb_index = (prach_occasion_id * (int)num_ssb_per_RO) % cc->num_active_ssb;
for(int j = first_ssb_index; j < first_ssb_index + num_ssb_per_RO; j++) { for(int j = first_ssb_index; j < first_ssb_index + num_ssb_per_RO; j++) {
// fapi beam index // fapi beam index
beam_index = get_fapi_beamforming_index(gNB, cc->ssb_index[j]); beam_index = get_beam_from_ssbidx(gNB, cc->ssb_index[j]);
// multi-beam allocation structure // multi-beam allocation structure
beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_frame); beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to SSB %d in any available beam\n", j); AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to SSB %d in any available beam\n", j);
@@ -516,7 +516,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
prach_pdu->beamforming.num_prgs = 1; prach_pdu->beamforming.num_prgs = 1;
prach_pdu->beamforming.prg_size = n_ra_rb; prach_pdu->beamforming.prg_size = n_ra_rb;
prach_pdu->beamforming.dig_bf_interface = num_td_occ; 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; const uint16_t fapi_beam = convert_to_fapi_beam(beam_index, gNB->beam_info.beam_mode);
prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[num_td_occ - 1].beam_idx = fapi_beam;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n", "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
@@ -762,7 +763,7 @@ void nr_initiate_ra_proc(module_id_t module_idP,
configure_UE_BWP(nr_mac, scc, UE, true, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); configure_UE_BWP(nr_mac, scc, UE, true, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
// return current SSB order in the list of tranmitted SSBs // return current SSB order in the list of tranmitted SSBs
int n_ssb = ssb_index_from_prach(module_idP, frame, slot, preamble_index, freq_index, symbol); int n_ssb = ssb_index_from_prach(module_idP, frame, slot, preamble_index, freq_index, symbol);
UE->UE_beam_index = get_fapi_beamforming_index(nr_mac, cc->ssb_index[n_ssb]); UE->UE_beam_index = get_beam_from_ssbidx(nr_mac, cc->ssb_index[n_ssb]);
LOG_I(NR_MAC, "UE %04x: Sync beam index %d\n", UE->rnti, UE->UE_beam_index); LOG_I(NR_MAC, "UE %04x: Sync beam index %d\n", UE->rnti, UE->UE_beam_index);
NR_SCHED_UNLOCK(&nr_mac->sched_lock); NR_SCHED_UNLOCK(&nr_mac->sched_lock);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
@@ -900,7 +901,8 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
0, 0,
ra->msg3_round, ra->msg3_round,
ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping, ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping,
UE->rnti); UE->rnti,
nr_mac->beam_info.beam_mode);
future_ul_tti_req->n_pdus += 1; future_ul_tti_req->n_pdus += 1;
// generation of DCI 0_0 to schedule msg3 retransmission // generation of DCI 0_0 to schedule msg3 retransmission
@@ -933,14 +935,9 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
} }
// Fill PDCCH DL DCI PDU // Fill PDCCH DL DCI PDU
nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15, const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nr_mac->beam_info.beam_mode);
scc, nfapi_nr_dl_dci_pdu_t *dci_pdu =
ss, prepare_dci_pdu(pdcch_pdu_rel15, scc, ss, coreset, aggregation_level, CCEIndex, fapi_beam, UE->rnti);
coreset,
aggregation_level,
CCEIndex,
UE->UE_beam_index,
UE->rnti);
pdcch_pdu_rel15->numDlDci++; pdcch_pdu_rel15->numDlDci++;
dci_pdu_rel15_t uldci_payload = {0}; dci_pdu_rel15_t uldci_payload = {0};
@@ -1204,7 +1201,8 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_
0, 0,
0, 0,
ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping, ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping,
UE->rnti); UE->rnti,
mac->beam_info.beam_mode);
future_ul_tti_req->n_pdus += 1; future_ul_tti_req->n_pdus += 1;
// calling function to fill rar message // calling function to fill rar message
@@ -1326,6 +1324,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nr_mac->beam_info.beam_mode);
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = prepare_pdsch_pdu(dl_tti_pdsch_pdu, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = prepare_pdsch_pdu(dl_tti_pdsch_pdu,
nr_mac, nr_mac,
UE, UE,
@@ -1334,19 +1333,13 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
false, false,
round, round,
rnti, rnti,
UE->UE_beam_index, fapi_beam,
1, 1,
pduindex); pduindex);
/* Fill PDCCH DL DCI PDU */ /* Fill PDCCH DL DCI PDU */
nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15, nfapi_nr_dl_dci_pdu_t *dci_pdu =
scc, prepare_dci_pdu(pdcch_pdu_rel15, scc, sched_ctrl->search_space, coreset, aggregation_level, CCEIndex, fapi_beam, rnti);
sched_ctrl->search_space,
coreset,
aggregation_level,
CCEIndex,
UE->UE_beam_index,
rnti);
pdcch_pdu_rel15->numDlDci++; pdcch_pdu_rel15->numDlDci++;
dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(nr_mac, dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(nr_mac,
+66 -98
View File
@@ -114,6 +114,58 @@ static int encode_mib(NR_BCCH_BCH_Message_t *mib, frame_t frame, uint8_t *buffer
return encode_size; return encode_size;
} }
static void schedule_one_ssb(gNB_MAC_INST *gNB,
nfapi_nr_dl_tti_request_body_t *dl_req,
const long band,
const NR_SubcarrierSpacing_t scs,
const int i_ssb,
const int rel_slot,
const frame_t frameP,
const slot_t slotP,
const int CC_id,
const uint8_t ssb_frame_periodicity,
const frequency_range_t FR)
{
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
const int slots_per_frame = gNB->frame_structure.numb_slots_frame;
const uint16_t offset_pointa = gNB->ssb_OffsetPointA;
NR_COMMON_channels_t *cc = &gNB->common_channels[CC_id];
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
const NR_MIB_t *mib = cc->mib->message.choice.mib;
uint32_t mib_pdu = (*(uint32_t *)cc->MIB_pdu) & ((1 << 24) - 1);
uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset;
uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
NR_beam_alloc_t beam =
beam_allocation_procedure(&gNB->beam_info, frameP, slotP, get_beam_from_ssbidx(gNB, i_ssb), slots_per_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
const uint16_t beam_index =
convert_to_fapi_beam(get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx), gNB->beam_info.beam_mode);
const int prb_offset = (FR == FR2) ? offset_pointa >> (scs - 2) : offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc,
prb_offset,
(FR == FR2) ? ssbSubcarrierOffset >> (scs - 2) : ssbSubcarrierOffset,
ssb_start_symbol,
CC_id,
beam.idx);
if (IS_SA_MODE(get_softmodem_params())) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP,
mib,
slots_per_frame,
ssbSubcarrierOffset,
ssb_start_symbol,
scs,
FR,
band,
i_ssb,
ssb_frame_periodicity,
prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
}
}
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi_nr_dl_tti_request_t *DL_req) void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi_nr_dl_tti_request_t *DL_req)
{ {
gNB_MAC_INST *gNB = RC.nrmac[module_idP]; gNB_MAC_INST *gNB = RC.nrmac[module_idP];
@@ -121,8 +173,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
nfapi_nr_dl_tti_request_body_t *dl_req; nfapi_nr_dl_tti_request_body_t *dl_req;
for (int 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;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
const int slots_per_frame = gNB->frame_structure.numb_slots_frame; const int slots_per_frame = gNB->frame_structure.numb_slots_frame;
dl_req = &DL_req->dl_tti_request_body; dl_req = &DL_req->dl_tti_request_body;
@@ -143,8 +194,6 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
mib_sdu_length); mib_sdu_length);
} }
uint32_t mib_pdu = (*(uint32_t *)cc->MIB_pdu) & ((1 << 24) - 1);
int8_t ssb_period = *scc->ssb_periodicityServingCell; int8_t ssb_period = *scc->ssb_periodicityServingCell;
uint8_t ssb_frame_periodicity = 1; // every how many frames SSB are generated uint8_t ssb_frame_periodicity = 1; // every how many frames SSB are generated
@@ -162,8 +211,6 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing;
const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
const uint16_t offset_pointa = gNB->ssb_OffsetPointA;
uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset;
const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
const BIT_STRING_t *mediumBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; const BIT_STRING_t *mediumBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap;
@@ -175,30 +222,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
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) {
uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); uint16_t 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 ((ssb_start_symbol / 14) == rel_slot)
if ((ssb_start_symbol / 14) == rel_slot) { schedule_one_ssb(gNB, dl_req, band, scs, i_ssb, rel_slot, frameP, slotP, CC_id, ssb_frame_periodicity, FR1);
int beam_index = get_fapi_beamforming_index(gNB, i_ssb);
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_per_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
const int prb_offset = offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
if (IS_SA_MODE(get_softmodem_params())) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP,
mib,
slots_per_frame,
ssbSubcarrierOffset,
ssb_start_symbol,
scs,
FR1,
band,
i_ssb,
ssb_frame_periodicity,
prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
}
}
} }
} }
break; break;
@@ -207,30 +232,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
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) {
uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); uint16_t 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 ((ssb_start_symbol / 14) == rel_slot)
if ((ssb_start_symbol / 14) == rel_slot) { schedule_one_ssb(gNB, dl_req, band, scs, i_ssb, rel_slot, frameP, slotP, CC_id, ssb_frame_periodicity, FR1);
int beam_index = get_fapi_beamforming_index(gNB, i_ssb);
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_per_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
const int prb_offset = offset_pointa >> scs;
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
if (IS_SA_MODE(get_softmodem_params())) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP,
mib,
slots_per_frame,
ssbSubcarrierOffset,
ssb_start_symbol,
scs,
FR1,
band,
i_ssb,
ssb_frame_periodicity,
prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
}
}
} }
} }
break; break;
@@ -239,30 +242,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
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) {
uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); uint16_t 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 ((ssb_start_symbol / 14) == rel_slot)
if ((ssb_start_symbol / 14) == rel_slot) { schedule_one_ssb(gNB, dl_req, band, scs, i_ssb, rel_slot, frameP, slotP, CC_id, ssb_frame_periodicity, FR2);
int beam_index = get_fapi_beamforming_index(gNB, i_ssb);
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_per_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
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset >> (scs - 2), ssb_start_symbol, CC_id, beam.idx);
if (IS_SA_MODE(get_softmodem_params())) {
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
frameP,
mib,
slots_per_frame,
ssbSubcarrierOffset,
ssb_start_symbol,
scs,
FR2,
band,
i_ssb,
ssb_frame_periodicity,
prb_offset);
gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
}
}
} }
} }
break; break;
@@ -422,17 +403,9 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
dl_tti_pdsch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); dl_tti_pdsch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
dl_req->nPDUs += 1; dl_req->nPDUs += 1;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = prepare_pdsch_pdu(dl_tti_pdsch_pdu, const uint16_t fapi_beam = convert_to_fapi_beam(beam_index, gNB_mac->beam_info.beam_mode);
gNB_mac, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 =
NULL, prepare_pdsch_pdu(dl_tti_pdsch_pdu, gNB_mac, NULL, pdsch, NULL, is_sib1, 0, SI_RNTI, fapi_beam, 1, pdu_index);
pdsch,
NULL,
is_sib1,
0,
SI_RNTI,
beam_index,
1,
pdu_index);
LOG_D(NR_MAC, LOG_D(NR_MAC,
"OtherSI:bwpStart %d, bwpSize %d, rbStart %d, rbSize %d, dlDmrsSymbPos = 0x%x\n", "OtherSI:bwpStart %d, bwpSize %d, rbStart %d, rbSize %d, dlDmrsSymbPos = 0x%x\n",
pdsch_pdu_rel15->BWPStart, pdsch_pdu_rel15->BWPStart,
@@ -442,14 +415,8 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
pdsch_pdu_rel15->dlDmrsSymbPos); pdsch_pdu_rel15->dlDmrsSymbPos);
/* Fill PDCCH DL DCI PDU */ /* Fill PDCCH DL DCI PDU */
nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15, nfapi_nr_dl_dci_pdu_t *dci_pdu =
scc, prepare_dci_pdu(pdcch_pdu_rel15, scc, search_space, coreset, aggregation_level, cce_index, fapi_beam, SI_RNTI);
search_space,
coreset,
aggregation_level,
cce_index,
beam_index,
SI_RNTI);
pdcch_pdu_rel15->numDlDci++; pdcch_pdu_rel15->numDlDci++;
/* DCI payload */ /* DCI payload */
@@ -542,7 +509,7 @@ void schedule_nr_sib1(module_id_t module_idP,
"Trying to schedule SIB1 in slot %d which is not DL. Check searchSpaceZero configuration.\n", "Trying to schedule SIB1 in slot %d which is not DL. Check searchSpaceZero configuration.\n",
slotP); slotP);
const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
int beam_index = get_fapi_beamforming_index(gNB_mac, i); int beam_index = get_beam_from_ssbidx(gNB_mac, i);
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame); NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SIB1 corresponding to SSB %d in any available beam\n", i); 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);
@@ -650,6 +617,7 @@ static void other_sib_sched_control(module_id_t module_idP,
slot); slot);
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
beam_index = get_beam_from_ssbidx(gNB_mac, beam_index);
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame); NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index); AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index);
LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index); LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index);
@@ -1142,6 +1142,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
maxMIMO_Layers = 1; maxMIMO_Layers = 1;
} }
const int nl_tbslbrm = min(maxMIMO_Layers, 4); const int nl_tbslbrm = min(maxMIMO_Layers, 4);
const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nr_mac->beam_info.beam_mode);
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu,
nr_mac, nr_mac,
UE, UE,
@@ -1150,7 +1151,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
false, false,
harq->round, harq->round,
rnti, rnti,
UE->UE_beam_index, fapi_beam,
nl_tbslbrm, nl_tbslbrm,
pduindex); pduindex);
@@ -1163,7 +1164,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
sched_ctrl->coreset, sched_ctrl->coreset,
sched_ctrl->aggregation_level, sched_ctrl->aggregation_level,
sched_ctrl->cce_index, sched_ctrl->cce_index,
UE->UE_beam_index, fapi_beam,
rnti); rnti);
pdcch_pdu->numDlDci++; pdcch_pdu->numDlDci++;
@@ -92,14 +92,34 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch)
const int bwpSize = dl_bwp->BWPSize; const int bwpSize = dl_bwp->BWPSize;
const int BWPStart = dl_bwp->BWPStart; const int BWPStart = dl_bwp->BWPStart;
// TODO implement beam procedures for phy-test mode /* This is a primitive beam allocation procedure for PDSCH in phytest mode which is
int beam = 0; intended to be used to verify the beamformed signal in VSA. The beam allocation of PDSCH
slots follows the SSB slots even in slots that don't have SSB. */
uint8_t num_ssb = 0;
const uint64_t ssbBitmap = get_ssb_bitmap_and_len(scc, &num_ssb);
int ssb_idx_beam = 0;
for (int i_ssb = 0; i_ssb < num_ssb; i_ssb++) {
if (IS_BIT_SET(ssbBitmap, (63 - i_ssb))) {
NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing;
const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
// select beam for PDSCH in current slot based on SSB beam
if ((ssb_start_symbol / NR_NUMBER_OF_SYMBOLS_PER_SLOT) == (slot % mac->frame_structure.numb_slots_period)) {
ssb_idx_beam = i_ssb;
break;
}
}
}
int beam_idx = get_beam_from_ssbidx(mac, ssb_idx_beam);
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, frame, slot, beam_idx, mac->frame_structure.numb_slots_frame);
AssertFatal(beam.idx > -1, "Can't allocate beam %d in phytest scheduler\n", beam_idx);
UE->UE_beam_index = get_allocated_beam(&mac->beam_info, frame, slot, mac->frame_structure.numb_slots_frame, beam.idx);
int rbStart = 0; int rbStart = 0;
int rbSize = 0; int rbSize = 0;
if (target_dl_bw>bwpSize) if (target_dl_bw>bwpSize)
target_dl_bw = bwpSize; target_dl_bw = bwpSize;
uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map[beam]; uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map[beam.idx];
/* loop ensures that we allocate exactly target_dl_bw, or return */ /* loop ensures that we allocate exactly target_dl_bw, or return */
while (true) { while (true) {
/* advance to first free RB */ /* advance to first free RB */
@@ -132,9 +152,11 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch)
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
int CCEIndex = get_cce_index(mac, int CCEIndex = get_cce_index(mac,
CC_id, slot, UE->rnti, CC_id,
slot,
UE->rnti,
&sched_ctrl->aggregation_level, &sched_ctrl->aggregation_level,
beam, beam.idx,
sched_ctrl->search_space, sched_ctrl->search_space,
sched_ctrl->coreset, sched_ctrl->coreset,
&sched_ctrl->sched_pdcch, &sched_ctrl->sched_pdcch,
@@ -156,12 +178,7 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch)
sched_ctrl->cce_index = CCEIndex; sched_ctrl->cce_index = CCEIndex;
fill_pdcch_vrb_map(mac, fill_pdcch_vrb_map(mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam.idx);
CC_id,
&sched_ctrl->sched_pdcch,
CCEIndex,
sched_ctrl->aggregation_level,
beam);
NR_sched_pdsch_t sched_pdsch = { NR_sched_pdsch_t sched_pdsch = {
.rbSize = rbSize, .rbSize = rbSize,
@@ -1326,7 +1326,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu,
uint16_t O_csi, uint16_t O_csi,
uint16_t O_ack, uint16_t O_ack,
uint8_t O_sr, uint8_t O_sr,
int r_pucch) int r_pucch,
nr_beam_mode_t beam_mode)
{ {
NR_PUCCH_Resource_t *pucchres; NR_PUCCH_Resource_t *pucchres;
NR_PUCCH_FormatConfig_t *pucchfmt; NR_PUCCH_FormatConfig_t *pucchfmt;
@@ -1534,7 +1535,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu,
pucch_pdu->beamforming.num_prgs = 1; pucch_pdu->beamforming.num_prgs = 1;
pucch_pdu->beamforming.prg_size = pucch_pdu->prb_size; pucch_pdu->beamforming.prg_size = pucch_pdu->prb_size;
pucch_pdu->beamforming.dig_bf_interface = 1; pucch_pdu->beamforming.dig_bf_interface = 1;
pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, beam_mode);
pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = fapi_beam;
} }
void set_r_pucch_parms(int rsetindex, void set_r_pucch_parms(int rsetindex,
@@ -3246,7 +3248,8 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
csirs_pdu_rel15->precodingAndBeamforming.prg_size = resourceMapping.freqBand.nrofRBs; //1 PRG of max size csirs_pdu_rel15->precodingAndBeamforming.prg_size = resourceMapping.freqBand.nrofRBs; //1 PRG of max size
csirs_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1; csirs_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1;
csirs_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; csirs_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0;
csirs_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, gNB_mac->beam_info.beam_mode);
csirs_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = fapi_beam;
csirs_pdu_rel15->bwp_size = dl_bwp->BWPSize; csirs_pdu_rel15->bwp_size = dl_bwp->BWPSize;
csirs_pdu_rel15->bwp_start = dl_bwp->BWPStart; csirs_pdu_rel15->bwp_start = dl_bwp->BWPStart;
csirs_pdu_rel15->subcarrier_spacing = dl_bwp->scs; csirs_pdu_rel15->subcarrier_spacing = dl_bwp->scs;
@@ -3619,45 +3622,48 @@ void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t
} }
} }
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx) int get_beam_from_ssbidx(gNB_MAC_INST *mac, int ssb_idx)
{ {
int beam_idx = mac->fapi_beam_index[ssb_idx]; int beam_idx = mac->beam_index_list[ssb_idx];
AssertFatal(beam_idx >= 0, "Invalid beamforming index %d\n", beam_idx); AssertFatal(beam_idx >= 0, "Invalid beamforming index %d\n", beam_idx);
return beam_idx; return beam_idx;
} }
// TODO this is a placeholder for a possibly more complex function uint64_t get_ssb_bitmap_and_len(const NR_ServingCellConfigCommon_t *scc, uint8_t *len)
// 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, 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) { switch (scc->ssb_PositionsInBurst->present) {
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap:
len = 4; *len = 4;
buf = scc->ssb_PositionsInBurst->choice.shortBitmap.buf;
break; break;
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap:
len = 8; *len = 8;
buf = scc->ssb_PositionsInBurst->choice.mediumBitmap.buf;
break; break;
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap:
len = 64; *len = 64;
buf = scc->ssb_PositionsInBurst->choice.longBitmap.buf;
break; break;
default : default :
AssertFatal(false, "Invalid configuration\n"); AssertFatal(false, "Invalid configuration\n");
} }
return get_ssb_bitmap(scc);
}
// 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 fill_beam_index_list(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac)
{
if (mac->beam_info.beam_mode == NO_BEAM_MODE)
return;
uint8_t len = 0;
const uint64_t ssbBitmap = get_ssb_bitmap_and_len(scc, &len);
int index = 0; int index = 0;
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
if ((buf[i / 8] >> (7 - i % 8)) & 0x1) { if (IS_BIT_SET(ssbBitmap, (63 - i))) {
int fapi_index = mac->beam_info.beam_mode == LOPHY_BEAM_IDX ? config->bw_list[index] : index; int fapi_index = mac->beam_info.beam_mode == LOPHY_BEAM_IDX ? config->bw_list[index] : index;
mac->fapi_beam_index[i] = fapi_index; mac->beam_index_list[i] = fapi_index;
index++; index++;
} else } else
mac->fapi_beam_index[i] = -1; mac->beam_index_list[i] = -1;
} }
} }
@@ -3666,7 +3672,7 @@ static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int
return ((frame * slots_per_frame + slot) / beam_info->beam_duration) % beam_info->beam_allocation_size; 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) NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int16_t beam_index, int slots_per_frame)
{ {
// if no beam allocation for analog beamforming we always return beam index 0 (no multiple beams) // if no beam allocation for analog beamforming we always return beam index 0 (no multiple beams)
if (beam_info->beam_mode == NO_BEAM_MODE) if (beam_info->beam_mode == NO_BEAM_MODE)
@@ -3675,7 +3681,7 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame,
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame); const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
for (int i = 0; i < beam_info->beams_per_period; i++) { for (int i = 0; i < beam_info->beams_per_period; i++) {
NR_beam_alloc_t beam_struct = {.new_beam = false, .idx = i}; NR_beam_alloc_t beam_struct = {.new_beam = false, .idx = i};
int *beam = &beam_info->beam_allocation[i][index]; int16_t *beam = &beam_info->beam_allocation[i][index];
if (*beam == -1) { if (*beam == -1) {
beam_struct.new_beam = true; beam_struct.new_beam = true;
*beam = beam_index; *beam = beam_index;
@@ -3689,7 +3695,23 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame,
return (NR_beam_alloc_t) {.new_beam = false, .idx = -1}; 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) uint16_t convert_to_fapi_beam(const uint16_t beam_idx, const nr_beam_mode_t mode)
{
AssertFatal(beam_idx >= 0 && beam_idx < 32768, "Beam index out of range. Valid range is [0, 32767]\n");
return (mode == LOPHY_BEAM_IDX) ? SET_BIT(beam_idx, 15) : beam_idx;
}
int16_t get_allocated_beam(const NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame, int beam_number_in_period)
{
int16_t beam_idx = 0;
if (beam_info->beam_mode != NO_BEAM_MODE) {
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
beam_idx = beam_info->beam_allocation[beam_number_in_period][index];
}
return beam_idx;
}
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int16_t 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 if(!new_beam) // need to reset only if the beam was allocated specifically for this instance
return; return;
@@ -3707,7 +3729,7 @@ void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
return; return;
RSRP_report_t *rsrp_report = &UE->UE_sched_ctrl.CSI_report.ssb_rsrp_report; 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 // simple beam switching algorithm -> we select beam with highest RSRP from CSI report
int new_bf_index = get_fapi_beamforming_index(mac, rsrp_report->resource_id[0]); int new_bf_index = get_beam_from_ssbidx(mac, rsrp_report->resource_id[0]);
if (UE->UE_beam_index == new_bf_index) if (UE->UE_beam_index == new_bf_index)
return; // no beam change needed return; // no beam change needed
@@ -473,7 +473,8 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac,
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index]; srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size; 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; const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nrmac->beam_info.beam_mode);
srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = fapi_beam;
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame); NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n"); AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n");
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE]; uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE];
@@ -94,7 +94,8 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot,
pucch->csi_bits, pucch->csi_bits,
pucch->dai_c, pucch->dai_c,
pucch->sr_flag, pucch->sr_flag,
pucch->r_pucch); pucch->r_pucch,
nrmac->beam_info.beam_mode);
} }
#define MIN_RSRP_VALUE -141 #define MIN_RSRP_VALUE -141
@@ -2314,7 +2314,8 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti
int harq_id, int harq_id,
int harq_round, int harq_round,
int fh, int fh,
int rnti) int rnti,
nr_beam_mode_t beam_mode)
{ {
nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu;
memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));
@@ -2364,7 +2365,8 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti
pusch_pdu->beamforming.num_prgs = 1; pusch_pdu->beamforming.num_prgs = 1;
pusch_pdu->beamforming.prg_size = pusch_pdu->bwp_size; pusch_pdu->beamforming.prg_size = pusch_pdu->bwp_size;
pusch_pdu->beamforming.dig_bf_interface = 1; pusch_pdu->beamforming.dig_bf_interface = 1;
pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx =
convert_to_fapi_beam(UE->UE_beam_index, beam_mode);
/* TRANSFORM PRECODING --------------------------------------------------------*/ /* TRANSFORM PRECODING --------------------------------------------------------*/
if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) {
// U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled
@@ -2522,7 +2524,8 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
harq_id, harq_id,
cur_harq->round, cur_harq->round,
current_BWP->pusch_Config && current_BWP->pusch_Config->frequencyHopping, current_BWP->pusch_Config && current_BWP->pusch_Config->frequencyHopping,
UE->rnti); UE->rnti,
nr_mac->beam_info.beam_mode);
req->n_pdus += 1; req->n_pdus += 1;
// Calculate the normalized tx_power for PHR // Calculate the normalized tx_power for PHR
@@ -2564,7 +2567,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
coreset, coreset,
sched_ctrl->aggregation_level, sched_ctrl->aggregation_level,
sched_ctrl->cce_index, sched_ctrl->cce_index,
UE->UE_beam_index, convert_to_fapi_beam(UE->UE_beam_index, nr_mac->beam_info.beam_mode),
UE->rnti); UE->rnti);
pdcch_pdu->numDlDci++; pdcch_pdu->numDlDci++;
+14 -8
View File
@@ -213,14 +213,15 @@ int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset,
NR_PUCCH_Config_t *pucch_Config, NR_PUCCH_Config_t *pucch_Config,
int CCEIndex); int CCEIndex);
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu,
NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfigCommon_t *scc,
NR_UE_info_t* UE, NR_UE_info_t *UE,
uint8_t pucch_resource, uint8_t pucch_resource,
uint16_t O_csi, uint16_t O_csi,
uint16_t O_ack, uint16_t O_ack,
uint8_t O_sr, uint8_t O_sr,
int r_pucch); int r_pucch,
nr_beam_mode_t mode);
void find_search_space(int ss_type, void find_search_space(int ss_type,
NR_BWP_Downlink_t *bwp, NR_BWP_Downlink_t *bwp,
@@ -330,7 +331,8 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti
int harq_id, int harq_id,
int harq_round, int harq_round,
int fh, int fh,
int rnti); int rnti,
nr_beam_mode_t beam_mode);
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu,
const gNB_MAC_INST *mac, const gNB_MAC_INST *mac,
const NR_UE_info_t *UE, const NR_UE_info_t *UE,
@@ -445,10 +447,14 @@ 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); 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 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, const nr_mac_config_t *config, gNB_MAC_INST *mac); uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc);
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx); uint64_t get_ssb_bitmap_and_len(const NR_ServingCellConfigCommon_t *scc, uint8_t *len);
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 fill_beam_index_list(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac);
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam); int get_beam_from_ssbidx(gNB_MAC_INST *mac, int ssb_idx);
int16_t get_allocated_beam(const NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame, int beam_number_in_period);
uint16_t convert_to_fapi_beam(const uint16_t beam_idx, const nr_beam_mode_t mode);
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int16_t beam_index, int slots_per_frame);
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int16_t beam_index, int slots_per_frame, bool new_beam);
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE); void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE);
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP); void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP);
bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
+3 -3
View File
@@ -794,7 +794,7 @@ typedef struct NR_UE_info {
NR_UE_NR_Capability_t *capability; NR_UE_NR_Capability_t *capability;
measgap_config_t measgap_config; measgap_config_t measgap_config;
// UE selected beam index // UE selected beam index
uint8_t UE_beam_index; uint16_t UE_beam_index;
float ul_thr_ue; float ul_thr_ue;
float dl_thr_ue; float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook; long pdsch_HARQ_ACK_Codebook;
@@ -826,7 +826,7 @@ typedef enum {
typedef struct { typedef struct {
/// list of allocated beams per period /// list of allocated beams per period
int **beam_allocation; int16_t **beam_allocation;
int beam_duration; // in slots int beam_duration; // in slots
int beams_per_period; int beams_per_period;
int beam_allocation_size; int beam_allocation_size;
@@ -993,7 +993,7 @@ typedef struct gNB_MAC_INST_s {
uint16_t min_grant_prb; uint16_t min_grant_prb;
bool identity_pm; bool identity_pm;
int precoding_matrix_size[NR_MAX_NB_LAYERS]; int precoding_matrix_size[NR_MAX_NB_LAYERS];
int fapi_beam_index[MAX_NUM_OF_SSB]; int beam_index_list[MAX_NUM_OF_SSB];
/// dedicate UL TDA, common for all UEs /// dedicate UL TDA, common for all UEs
seq_arr_t ul_tda; seq_arr_t ul_tda;
+1 -1
View File
@@ -309,7 +309,7 @@ static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uin
return coreset; return coreset;
} }
static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc)
{ {
uint64_t bitmap=0; uint64_t bitmap=0;
switch (scc->ssb_PositionsInBurst->present) { switch (scc->ssb_PositionsInBurst->present) {