This commit is contained in:
2026-03-04 23:41:00 +09:00
parent 817e04cc29
commit 2244eb8e99
5 changed files with 139 additions and 103 deletions
+106 -81
View File
@@ -462,92 +462,117 @@ static inline void do_txdataF(c16_t **txdataF,
int start_sc,
int txdataF_offset_per_symbol)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
int rb = 0;
uint16_t subCarrier = start_sc;
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
while (rb < rel15->rbSize) {
// get pmi info
const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0;
const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1;
const int pmi3 = (rb < (rel15->rbSize - 2) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 2) / pb->prg_size].pm_idx) : -1;
const int pmi4 = (rb < (rel15->rbSize - 3) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 3) / pb->prg_size].pm_idx) : -1;
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
int rb = 0;
uint16_t subCarrier = start_sc;
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
// If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row
// if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row
int rb_step0 = pmi == pmi2 ? 2 : 1;
const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0;
const int re_cnt = NR_NB_SC_PER_RB * rb_step;
if (pmi == 0) { // unitary Precoding
if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC
if (ant < rel15->nrOfLayers)
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
&txdataF_precoding[ant][subCarrier],
re_cnt * sizeof(**txdataF));
else
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF));
} else { // RB does cross DC
const int neg_length = symbol_sz - subCarrier;
const int pos_length = re_cnt - neg_length;
if (ant < rel15->nrOfLayers) {
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
&txdataF_precoding[ant][subCarrier],
neg_length * sizeof(**txdataF));
memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF));
// Compute which layer this antenna carries under identity precoding.
// Standard identity maps layer N → antenna N, but when antennas are muted
// we must remap layers to active antennas. Otherwise layer data sent to a
// muted antenna is lost (RU blanks it) while active antennas sit idle.
// E.g. mask=0x0D (ant 1 muted, 3 layers): ant0→L0, ant2→L1, ant3→L2.
int identity_layer = -1;
{
const nr_antenna_state_t *ast = &gNB->antenna_state;
int active_count = nr_get_active_tx_antenna_count(ast);
if (active_count > 0 && active_count < frame_parms->nb_antennas_tx) {
if (nr_is_tx_antenna_active(ast, ant)) {
identity_layer = 0;
for (int a = 0; a < ant; a++)
if (nr_is_tx_antenna_active(ast, a))
identity_layer++;
if (identity_layer >= rel15->nrOfLayers)
identity_layer = -1;
}
} else {
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF));
memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF));
// No muting: standard identity (layer N = antenna N)
identity_layer = (ant < rel15->nrOfLayers) ? ant : -1;
}
}
subCarrier += re_cnt;
if (subCarrier >= symbol_sz) {
subCarrier -= symbol_sz;
}
} else { // non-unitary Precoding
AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n");
// get the precoding matrix weights:
nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix
AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx);
AssertFatal(ant < pmi_pdu->num_ant_ports,
"Antenna port index %d exceeds precoding matrix AP size %d\n",
ant,
pmi_pdu->num_ant_ports);
AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers,
"Number of layers %d doesn't match to the one in precoding matrix %d\n",
rel15->nrOfLayers,
pmi_pdu->numLayers);
if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe
nr_layer_precoder_simd(rel15->nrOfLayers,
symbol_sz,
txdataF_precoding,
ant,
pmi_pdu,
subCarrier,
re_cnt,
&txdataF[ant][txdataF_offset_per_symbol]);
subCarrier += re_cnt;
} else { // crossing ofdm_symbol_size, use simple arithmetic operations
for (int i = 0; i < re_cnt; i++) {
txdataF[ant][txdataF_offset_per_symbol + subCarrier] =
nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier);
#ifdef DEBUG_DLSCH_MAPPING
printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n",
ant,
l_symbol,
subCarrier,
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r,
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i);
#endif
if (++subCarrier >= symbol_sz) {
subCarrier -= symbol_sz;
}
}
} // else{ // crossing ofdm_symbol_size, use simple arithmetic operations
} // else { // non-unitary Precoding
}
rb += rb_step;
} // RB loop: while(rb < rel15->rbSize)
while (rb < rel15->rbSize) {
// get pmi info
const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0;
const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1;
const int pmi3 = (rb < (rel15->rbSize - 2) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 2) / pb->prg_size].pm_idx) : -1;
const int pmi4 = (rb < (rel15->rbSize - 3) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 3) / pb->prg_size].pm_idx) : -1;
// If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row
// if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row
int rb_step0 = pmi == pmi2 ? 2 : 1;
const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0;
const int re_cnt = NR_NB_SC_PER_RB * rb_step;
if (pmi == 0) { // unitary Precoding
if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC
if (identity_layer >= 0)
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
&txdataF_precoding[identity_layer][subCarrier],
re_cnt * sizeof(**txdataF));
else
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF));
} else { // RB does cross DC
const int neg_length = symbol_sz - subCarrier;
const int pos_length = re_cnt - neg_length;
if (identity_layer >= 0) {
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
&txdataF_precoding[identity_layer][subCarrier],
neg_length * sizeof(**txdataF));
memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[identity_layer], pos_length * sizeof(**txdataF));
} else {
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF));
memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF));
}
}
subCarrier += re_cnt;
if (subCarrier >= symbol_sz) {
subCarrier -= symbol_sz;
}
} else { // non-unitary Precoding
AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n");
// get the precoding matrix weights:
nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix
AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx);
AssertFatal(ant < pmi_pdu->num_ant_ports,
"Antenna port index %d exceeds precoding matrix AP size %d\n",
ant,
pmi_pdu->num_ant_ports);
AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers,
"Number of layers %d doesn't match to the one in precoding matrix %d\n",
rel15->nrOfLayers,
pmi_pdu->numLayers);
if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe
nr_layer_precoder_simd(rel15->nrOfLayers,
symbol_sz,
txdataF_precoding,
ant,
pmi_pdu,
subCarrier,
re_cnt,
&txdataF[ant][txdataF_offset_per_symbol]);
subCarrier += re_cnt;
} else { // crossing ofdm_symbol_size, use simple arithmetic operations
for (int i = 0; i < re_cnt; i++) {
txdataF[ant][txdataF_offset_per_symbol + subCarrier] =
nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier);
#ifdef DEBUG_DLSCH_MAPPING
printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n",
ant,
l_symbol,
subCarrier,
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r,
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i);
#endif
if (++subCarrier >= symbol_sz) {
subCarrier -= symbol_sz;
}
}
} // else{ // crossing ofdm_symbol_size, use simple arithmetic operations
} // else { // non-unitary Precoding
rb += rb_step;
} // RB loop: while(rb < rel15->rbSize)
}
static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot)
{
const int16_t amp = gNB->TX_AMP;
+16 -16
View File
@@ -264,25 +264,25 @@ void nr_feptx(void *arg)
// If there is no digital beamforming we just need to copy the data to RU
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) {
// Check antenna muting state for energy saving
const nr_antenna_state_t *ant_state = &ru->gNB_list[0]->antenna_state;
bool is_active = nr_is_tx_antenna_active(ant_state, aa);
if (!is_active) {
// Antenna is muted - zero out the buffer (transmission blanking)
memset((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], 0, numSamples * sizeof(int32_t));
if (startSymbol == 0) {
LOG_I(PHY, "[ANTENNA_MUTE] TX ant %d muted (mask=0x%02X, num_tx=%d), blanking slot %d\n",
aa, nr_get_tx_antenna_bitmask(ant_state), ant_state->num_tx_antennas, slot);
// Check antenna muting state for energy saving
const nr_antenna_state_t *ant_state = &ru->gNB_list[0]->antenna_state;
bool is_active = nr_is_tx_antenna_active(ant_state, aa);
if (!is_active) {
// Antenna is muted - zero out the buffer (transmission blanking)
memset((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], 0, numSamples * sizeof(int32_t));
/* if (startSymbol == 0) { */
/* LOG_I(PHY, "[ANTENNA_MUTE] TX ant %d muted (mask=0x%02X, num_tx=%d), blanking slot %d\n", */
/* aa, nr_get_tx_antenna_bitmask(ant_state), ant_state->num_tx_antennas, slot); */
/* } */
} else {
// Antenna is active - copy data normally
memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset],
(void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset],
numSamples * sizeof(int32_t));
}
} else {
// Antenna is active - copy data normally
memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset],
(void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset],
numSamples * sizeof(int32_t));
}
}
else {
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
}
/* const c16_t *dst = (const c16_t *)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset]; */
@@ -108,7 +108,10 @@ bool read_pdcp_sm(void* data)
}
num_ues++;
AssertFatal(num_ues < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n");
if (num_ues >= MAX_MOBILES_PER_GNB) {
LOG_W(PDCP, "num_ues %zu >= MAX_MOBILES_PER_GNB %d, skipping remaining UEs\n", num_ues, MAX_MOBILES_PER_GNB);
break;
}
}
#elif defined (NGRAN_GNB_CUUP)
@@ -178,7 +178,7 @@ static void capture_sst_sd(test_cond_value_t* test_cond_value, uint8_t *sst, uin
*sd = malloc(sizeof(uint32_t));
**sd = buf[1] << 16 | buf[2] << 8 | buf[3];
}
printf("[E2 AGENT][E2SM-KPM] Condition NSSAI (%d, %x).\n", *sst, (*sd) ? **sd : 0xffffff);
/* printf("[E2 AGENT][E2SM-KPM] Condition NSSAI (%d, %x).\n", *sst, (*sd) ? **sd : 0xffffff); */
break;
}
default:
@@ -226,7 +226,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info)
break;
}
}
AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n");
if (arr_ue_id.sz >= MAX_MOBILES_PER_GNB) {
LOG_W(NR_MAC, "arr_ue_id.sz %zu >= MAX_MOBILES_PER_GNB %d, skipping remaining UEs\n", arr_ue_id.sz, MAX_MOBILES_PER_GNB);
break;
}
}
free(sd); // if NULL, nothing happens
@@ -319,7 +322,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst
break;
}
}
AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n");
if (arr_ue_id.sz >= MAX_MOBILES_PER_GNB) {
LOG_W(NR_MAC, "arr_ue_id.sz %zu >= MAX_MOBILES_PER_GNB %d, skipping remaining UEs\n", arr_ue_id.sz, MAX_MOBILES_PER_GNB);
break;
}
}
node_stats[1].mac_stats.dl.total_prb_aggregate = mac->mac_stats.dl.total_prb_aggregate;
@@ -3898,8 +3898,10 @@ bool nr_mac_ue_is_active(const NR_UE_info_t *ue)
return true;
}
#define UL_FAILURE_REQ_GRACE 10000
#define UL_FAILURE_TIMEOUT 30000
/* #define UL_FAILURE_REQ_GRACE 10000 */
/* #define UL_FAILURE_TIMEOUT 30000 */
#define UL_FAILURE_REQ_GRACE 2000
#define UL_FAILURE_TIMEOUT 2500
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
{
if (sched_ctrl->ul_failure) {