Commit db0f6696 authored by Robert Schmidt's avatar Robert Schmidt

Reimplement (PUSCH) power control

Introduce new data structures to track the average SNR and RSSI, and
that allow to dynamically modify the target SNR (per UE) as well as
continuously get TPC updates based on the average SNR. The target SNR is
per power control loop (which a future commit will extend to use for
PUCCH).

Concretely, it maintains an average of measured SNR and RSSI.  It also
updates "tpc_in_flight", which tracks TPC changes that don't show up in
the average yet. For instance, imagine that the target SNR of 15 changes
to 20. Three successive TPC commands need to be sent (+3, +1, +1), but
it will take time to show up in the average SNR. To account for this,
tpc_in_flight is updated by the TPCs sent, and an average will make it
go down back to zero at the same pace as the average SNR approaches the
target SNR.  The sum of average SNR and tpc_in_flight sums up to the
actual, current SNR, which approximates the target SNR.

The SNR is kept within -1<=targetSNR<=+2dB to avoid too many TPC
changes.

The current average SNR (sum of average SNR and tpc_in_flight) is used
to continuously get TPC updates, taking into account recent TPCs sent,
the difference to target SNR, and RSSI.

If there is DTX, tpc_in_flight is modified to artificially introduce TPC
commands which increase the currently used SNR of the UE. This is
temporary, as tpc_in_flight eventually will go back to zero. If the DTX
was due to sudden SNR drop (e.g., higher path loss), this will allow to
quickly adapt the UE's SNR to new conditions.

The periodical logs are extended to not only show the current SNR, but
also the difference from the target for better analysis.
Co-authored-by: default avatarMaxime Elkael <m.elkael@northeastern.edu>
parent ffae5942
......@@ -82,7 +82,7 @@ UE RNTI 2460 CU-UE-ID 2 in-sync PH 28 dB PCMAX 24 dBm, average RSRP -74 (8 meas)
UE 2460: CQI 15, RI 2, PMI (14,1)
UE 2460: UL-RI 2 TPMI 0
UE 2460: dlsch_rounds 32917/5113/1504/560, dlsch_errors 211, pucch0_DTX 1385, BLER 0.19557 MCS (1) 23 CCE fail 3
UE 2460: ulsch_rounds 3756/353/182/179, ulsch_errors 170, ulsch_DTX 285, BLER 0.33021 MCS (1) 27 (Qm 8 dB) NPRB 5 SNR 31.0 dB CCE fail 0
UE 2460: ulsch_rounds 3756/353/182/179, ulsch_errors 170, ulsch_DTX 285, BLER 0.33021 MCS (1) 27 (Qm 8 dB) NPRB 5 SNR 31.0 (-1.0) dB CCE fail 0
UE 2460: MAC: TX 1530943191 RX 194148 bytes
UE 2460: LCID 1: TX 651 RX 3031 bytes
UE 2460: LCID 2: TX 0 RX 0 bytes
......@@ -162,10 +162,9 @@ The fourth and fifth line show HARQ-related information:
fluctuate a lot but when doing high throughput with iperf, it indicates the
number of PRBs that the UE is actually able to use with its power budget and
should be high.
* ULSCH `SNR`: the current SNR that the gNB receives the UE signal with. It
should be close to the target in the gNB configuration file,
`pusch_TargetSNRx10`, which should be around 10 times the value shown in the
log
* ULSCH `SNR`: the current SNR that the gNB receives the UE PUSCH signal with.
This value should be close to the target SNR; in paranthesis, the difference
to the target SNR.
* Both ULSCH/DLSCH `CCE fail`: lists the number of failed CCE attempts. If this
number gets high, it signifies that the scheduler tried to scheduled this UE,
but could not allocate the DCI.
......
......@@ -81,7 +81,7 @@ bool read_mac_sm(void* data)
rd->dl_aggr_sdus = UE->mac_stats.dl.num_mac_sdu;
rd->ul_aggr_sdus = UE->mac_stats.ul.num_mac_sdu;
rd->pusch_snr = (float) sched_ctrl->pusch_snrx10 / 10; //: float = -64;
rd->pusch_snr = sched_ctrl->pusch_pc.avg_snr; //: float = -64;
rd->pucch_snr = (float) sched_ctrl->pucch_snrx10 / 10; //: float = -64;
rd->wb_cqi = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
......
......@@ -1143,7 +1143,7 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
DevAssert(get_softmodem_params()->phy_test);
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup);
NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup, &nrmac->radio_config);
DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // physical simulators: we assume we can always create a UE
free_and_zero(UE->ra); // physical simulators: UE will not do RA
UE->local_bwp_id = 1; // for physical simulators
......
......@@ -604,7 +604,7 @@ int nr_fill_successrar(const NR_UE_sched_ctrl_t *ue_sched_ctl,
successRAR->CONT_RES_6 = ue_cont_res_id[5];
successRAR->R = 0;
successRAR->CH_ACESS_CPEXT = 1;
successRAR->TPC = ue_sched_ctl->tpc0;
successRAR->TPC = 1; // 0dB change, don't know how to determine this.
successRAR->HARQ_FTI = timing_indicator;
successRAR->PUCCH_RI = resource_indicator;
successRAR->TA1 = (uint8_t)(timing_advance_cmd >> 8); // 4 MSBs of timing advance;
......@@ -718,7 +718,7 @@ void nr_initiate_ra_proc(module_id_t module_idP,
return;
}
UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL);
UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL, &nr_mac->radio_config);
if (!add_new_UE_RA(nr_mac, UE)) {
LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index);
delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator);
......
......@@ -2973,7 +2973,7 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats
* It will be typically added to the access_ue_list, but not always (e.g.,
* phytest mode), so this is not done in this function (and also, to allow
* error handling). Remove with delete_nr_ue_data(). */
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup)
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup, const nr_mac_config_t *config)
{
NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t));
UE->uid = uid_linear_allocator_new(uia);
......@@ -2983,6 +2983,10 @@ NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroup
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->ta_update = 31;
nr_mac_set_target_snrx10(&sched_ctrl->pusch_pc, config->pusch.target_snrx10);
sched_ctrl->pusch_pc.avg_snr = config->pusch.target_snrx10 / 10.0f; // set initial SNR to what we would expect on average
nr_mac_set_rssi_threshold(&sched_ctrl->pusch_pc, config->pusch.rssi_threshold);
/* Set default BWPs */
AssertFatal(UE->sc_info.n_ul_bwp <= NR_MAX_NUM_BWP, "uplinkBWP_ToAddModList has %d BWP!\n", UE->sc_info.n_ul_bwp);
......@@ -3134,6 +3138,19 @@ uint8_t nr_get_tpc(int target, uint8_t cqi, int incr, int tx_power)
return 1; // no change
}
/**
* @brief Returns the number of dBs for given transmit power control (TPC)
* command. Asserts on illegal TPC.
* @param tpc TPC command in range 0..3
* @return The dB value expressed by the TPC command
*/
static int tpc_to_db(int tpc)
{
DevAssert(tpc >= 0 && tpc <= 3);
const int db[] = {-1, 0, 1, 3};
return db[tpc];
}
/**
* @brief Limits the power control commands (TPC) in NR by checking the RSSI threshold.
*
......@@ -3156,11 +3173,10 @@ uint8_t nr_limit_tpc(int tpc, int rssi, int rssi_threshold)
const int fapi_rssi_0dBm_or_0dBFS = 1280;
int rssi_fapi_threshold = fapi_rssi_0dBm_or_0dBFS + rssi_threshold;
// Further limit TPC if above or near RSSI threshold
int tpc_to_db[] = {-1, 0, 1, 3};
if (rssi > rssi_fapi_threshold) {
// RSSI above theshold, reduce power
return 0;
} else if (rssi + tpc_to_db[tpc] * 10 > rssi_fapi_threshold) {
} else if (rssi + tpc_to_db(tpc) * 10 > rssi_fapi_threshold) {
// Cannot apply required TPC, check 1 dB increment
if (rssi + 10 > rssi_fapi_threshold) {
// Still cannot apply required TPC, keep power
......@@ -4134,3 +4150,127 @@ void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool
sched_ctrl->pdcch_cl_adjust = max(0, sched_ctrl->pdcch_cl_adjust - 0.01);
}
}
/**
* @brief Calculate the current average SNR for the given power control loop.
* @param pc the power control loop
* @return the current average SNR
*/
float nr_mac_get_snr(const nr_power_control_t *pc)
{
return pc->avg_snr + pc->tpc_in_flight;
}
/**
* @brief Calculates the difference of current average SNR to the target SNR
* set in the power control loop.
* @param pc the power control loop
* @return the SNR difference
*/
static float get_snr_diff(const nr_power_control_t *pc)
{
float snr = nr_mac_get_snr(pc);
float delta = (snr * 10.0f - pc->target_snrx10) / 10.0f;
LOG_D(NR_MAC, "target %.2f snr %.2f delta %.2f\n", pc->target_snrx10 / 10.0f, snr, delta);
return delta;
}
/// averaging constant for power control (used for SNR, RSSI).
#define PC_AVG_CNST 0.975f
/**
* @brief Enter new SNR and RSSI value for the latest UL transmission, and
* update the average SNR and average RSSI of the corresponding UE.
*
* Since the SNR is averaged, any changes through transmit power control (TPC)
* commands will take time to reflect in the averaged SNR. To allow a
* continuous tracking of necessary TPC, as well as a continuous adjustment of
* the target SNR, the algorithm keeps track of "TPC in flight" which is a
* moving average of the last TPC commands sent to the UE. The sum of the
* averaged SNR and "TPC in flight" is the actual, current SNR. The RSSI in
* turn is used to limit TPC commands (see also nr_limit_tpc()).
*
* @param pc the power control loop
* @param snrx10 the current SNR measurement multiplied by 10
* @param rssi the current RSSI measurement
*/
void nr_mac_pc_snr(nr_power_control_t *pc, int snrx10, int rssi)
{
pc->avg_snr = PC_AVG_CNST * pc->avg_snr + (1.0f - PC_AVG_CNST) * 0.1 * snrx10;
pc->avg_rssi = PC_AVG_CNST * pc->avg_rssi + (1.0f - PC_AVG_CNST) * rssi;
// use an EMA to average out tpc_in_flight as fast as EMA for avg_snr.
// this will ensure that on TPC change, avg_snr approximates real SNR as
// fast as tpc_in_flight returns to 0.
pc->tpc_in_flight = PC_AVG_CNST * pc->tpc_in_flight; // + (1 - PC_AVG_CNST) * 0.0f
}
/**
* @brief Set a new target SNR for this power control loop, which can be
* updated on a continuous basis, and will be reflected immediately upon
* calls to nr_mac_get_tpc() (no "settle time" necessary).
*
* @param pc the power control loop
* @param target_snrx10 the target SNR to be set times 10.
*/
void nr_mac_set_target_snrx10(nr_power_control_t *pc, int target_snrx10)
{
pc->target_snrx10 = target_snrx10;
}
/**
* @brif Set a new RSSI threshold for this power control loop. Will be used to
* limit TPCs, see also nr_limit_tpc().
*
* @param pc the power control loop
* @param rssi_threshold the RSSI threshold
*/
void nr_mac_set_rssi_threshold(nr_power_control_t *pc, int rssi_threshold)
{
pc->rssi_threshold = rssi_threshold;
}
/**
* @brief Signal that this power control loop experienced a discontinuous
* transmission (DTC), aka "no reception".. This will decrease the "TPC in
* flight" to artificially reduce the current SNR, which will trigger a TPC
* command to increase the power. Repeated DTX will lead to more TPC.
*
* @param pc the power control loop
*/
void nr_mac_signal_dtx(nr_power_control_t *pc)
{
// repeated DTX will make nr_mac_get_tpc() return positive TPCs, see
// nr_mac_pc_snr(). The more DTX, the more TPC increase, which will
// eventually zero out and return back to target SNR (change is temporary).
// Also, this will only send positive TPC changes.
pc->tpc_in_flight = max(pc->tpc_in_flight - 1.0f, -5.0f); // TODO threshold good?
}
/**
* @brief Get a transmit power control (TPC) command for the given power
* control loop according to current and target SNR. This function can be
* called continuously on every UL transmission occasion, and keeps track of
* past TPC commands. It also limits TPC commands according to RSSI, see
* nr_limit_tpc() for more information.
*
* @param pc the power control loop
* @return the next TPC command.
*/
int nr_mac_get_tpc(nr_power_control_t *pc)
{
float diff = get_snr_diff(pc);
int tpc = 1;
if (diff <= -3.0f) {
tpc = 3; // increase 3dB
} else if (diff <= -1.0f) {
tpc = 2; // increase 1dB
} else if (diff >= 2.0f) {
tpc = 0; // decrease 1dB
} else {
tpc = 1; // within -1<=target<=2dB => is ok.
}
tpc = nr_limit_tpc(tpc, pc->avg_rssi, pc->rssi_threshold);
int change = tpc_to_db(tpc);
pc->tpc_in_flight += change;
LOG_D(NR_MAC, "tpc %d => %d\n", tpc, change);
return tpc;
}
......@@ -850,13 +850,11 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
DevAssert(harq_pid >= 0 && harq_pid < 8);
if (ul_cqi != 0xff) {
NR_UE_ul_harq_t *harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
DevAssert(harq->sched_pusch.phr_txpower_calc == 0);
UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, harq->sched_pusch.phr_txpower_calc);
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - harq->sched_pusch.phr_txpower_calc * 10;
DevAssert(harq->sched_pusch.phr_txpower_calc == 0); // TODO remove from here
UE_scheduling_control->pusch_pc.avg_snr = 0.1 * (ul_cqi * 5 - 640);
}
if (timing_advance != 0xffff)
UE_scheduling_control->ta_update = timing_advance;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
for (uint32_t k = 0; k < sdu_len; k++) {
......@@ -944,8 +942,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];
const int current_rnti = rntiP;
LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti);
const int target_snrx10 = gNB_mac->radio_config.pusch.target_snrx10;
const int rssi_threshold = gNB_mac->radio_config.pusch.rssi_threshold;
const int pusch_failure_thres = gNB_mac->radio_config.pusch.failure_thres;
NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti);
if (UE) {
......@@ -977,21 +973,18 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
int txpower_calc = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.phr_txpower_calc;
UE->mac_stats.deltaMCS = txpower_calc;
UE->mac_stats.NPRB = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.rbSize;
if (ul_cqi != 0xff)
UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, txpower_calc);
if (UE_scheduling_control->ph < 0 && UE_scheduling_control->tpc0 > 1)
UE_scheduling_control->tpc0 = 1;
UE_scheduling_control->tpc0 = nr_limit_tpc(UE_scheduling_control->tpc0, rssi, rssi_threshold);
int pusch_snrx10 = ul_cqi * 5 - 640 - txpower_calc * 10; // TODO don't log T?
if (ul_cqi != 0xff)
nr_mac_pc_snr(&UE_scheduling_control->pusch_pc, pusch_snrx10, rssi);
if (timing_advance != 0xffff)
UE_scheduling_control->ta_update = timing_advance;
int pusch_snrx10 = ul_cqi * 5 - 640;
UE_scheduling_control->pusch_snrx10 = pusch_snrx10 - (txpower_calc * 10);
const NR_sched_pusch_t *sched_pusch = &UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch;
(void) sched_pusch; // avoids warnings of unused sched_pusch when compiling without T
T(T_GNB_MAC_PUSCH_POWER_CONTROL, T_INT(rntiP), T_INT(frameP), T_INT(slotP),
T_INT(UE_scheduling_control->pusch_snrx10),
T_INT(pusch_snrx10),
T_INT(UE_scheduling_control->ph),
T_INT(sched_pusch->tpc_pusch),
T_INT(sched_pusch->tb_size),
......@@ -999,27 +992,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
T_INT(sched_pusch->rbSize),
T_INT(sched_pusch->mcs),
T_INT(rssi));
if (false)
LOG_I(NR_MAC,
"[UE %04x] %4d.%2d. rssi %4d snr %3d txp_calc %3d PHR %2d RB %2d MCS %2d\n",
UE->rnti,
frameP,
slotP,
rssi,
pusch_snrx10 / 10,
txpower_calc,
UE_scheduling_control->ph,
UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.rbSize,
UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.mcs);
NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
if (cur_harq->round == 0)
UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
}
else{
LOG_D(NR_MAC,"[UE %04x] Detected DTX : increasing UE TX power\n",UE->rnti);
UE_scheduling_control->tpc0 = 1;
}
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
......@@ -1046,6 +1018,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
if (ul_cqi == 0xff || ul_cqi <= 128) {
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt++;
UE->mac_stats.ulsch_DTX++;
nr_mac_signal_dtx(&UE_scheduling_control->pusch_pc);
}
if (!get_softmodem_params()->phy_test && UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt >= pusch_failure_thres) {
......@@ -2092,7 +2065,7 @@ static int pf_ul(gNB_MAC_INST *nrmac,
int selected_mcs;
int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format);
if (bo->harq_round_max == 1) {
selected_mcs = get_mcs_from_SINRx10(current_BWP->mcs_table, sched_ctrl->pusch_snrx10, nrOfLayers);
selected_mcs = get_mcs_from_SINRx10(current_BWP->mcs_table, sched_ctrl->pusch_pc.avg_snr * 10, nrOfLayers);
selected_mcs = min(max_mcs, selected_mcs);
selected_mcs = max(bo->min_mcs, selected_mcs);
sched_ctrl->ul_bler_stats.mcs = selected_mcs;
......@@ -2513,6 +2486,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
deltaMCS,
false);
int tpc = nr_mac_get_tpc(&sched_ctrl->pusch_pc);
LOG_D(NR_MAC,
"ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d TDA %2d dmrs_pos %x MCS "
"Table %2d MCS %2d nrOfLayers %2d num_dmrs_cdm_grps_no_data %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d est %6d sched "
......@@ -2539,7 +2513,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
sched_ctrl->estimated_ul_buffer,
sched_ctrl->sched_ul_bytes,
sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes,
sched_ctrl->tpc0);
tpc);
/* Save information on MCS, TBS etc for the current initial transmission
* so we have access to it when retransmitting */
......@@ -2599,14 +2573,12 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
&sched_ctrl->srs_feedback,
tpmi,
sched_pusch->time_domain_allocation,
UE->UE_sched_ctrl.tpc0,
tpc,
cur_harq->ndi,
current_BWP,
ss->searchSpaceType->present);
// Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR
cur_harq->sched_pusch.tpc_pusch = sched_ctrl->tpc0;
sched_ctrl->tpc0 = 1;
cur_harq->sched_pusch.tpc_pusch = tpc;
fill_dci_pdu_rel15(&UE->sc_info,
&UE->current_DL_BWP,
......
......@@ -321,7 +321,7 @@ bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
bool nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success);
void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti);
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup);
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup, const nr_mac_config_t *config);
int nr_get_default_pucch_res(int pucch_ResourceCommon);
nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti_req,
const NR_UE_info_t *UE,
......@@ -502,4 +502,12 @@ void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group);
void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE_info_t *UE, NR_sched_pdsch_t *sched_pdsch);
void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch);
float nr_mac_get_snr(const nr_power_control_t *pc);
void nr_mac_pc_snr(nr_power_control_t *pc, int snrx10, int rssi);
void nr_mac_set_target_snrx10(nr_power_control_t *pc, int target_snrx10);
void nr_mac_set_rssi_threshold(nr_power_control_t *pc, int rssi_threshold);
void nr_mac_signal_dtx(nr_power_control_t *pc);
int nr_mac_get_tpc(nr_power_control_t *pc);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
......@@ -560,7 +560,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
bool success = du_add_f1_ue_data(rnti, &new_ue_data);
DevAssert(success);
NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL);
NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL, &mac->radio_config);
AssertFatal(UE->uid < MAX_MOBILES_PER_GNB, "cannot create UE context, UE context setup failure not implemented\n");
NR_CellGroupConfig_t *cellGroupConfig = NULL;
......
......@@ -219,9 +219,11 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
for (int i = 1; i < gNB->ul_bler.harq_round_max; i++)
output = st_append(output, end, "/%"PRIu64, stats->ul.rounds[i]);
float snr = nr_mac_get_snr(&sched_ctrl->pusch_pc);
float diff_target = (snr * 10.0f - sched_ctrl->pusch_pc.target_snrx10) / 10.0f;
output = st_append(output,
end,
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB CCE fail %d\n",
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %.1f (%+.1f) dB CCE fail %d\n",
stats->ul.errors,
stats->ulsch_DTX,
sched_ctrl->ul_bler_stats.bler,
......@@ -230,8 +232,8 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
nr_get_Qm_ul(sched_ctrl->ul_bler_stats.mcs,UE->current_UL_BWP.mcs_table),
UE->mac_stats.deltaMCS,
UE->mac_stats.NPRB,
sched_ctrl->pusch_snrx10 / 10,
sched_ctrl->pusch_snrx10 % 10,
snr,
diff_target,
sched_ctrl->ul_cce_fail);
output = st_append(output,
end,
......
......@@ -616,6 +616,14 @@ typedef struct nr_lc_config {
NR_QoS_config_t qos_config[NR_MAX_NUM_QFI];
} nr_lc_config_t;
typedef struct nr_power_control {
float avg_snr; /// average SNR (in dB)
int target_snrx10; /// UE-specific target SNR x10
float avg_rssi; /// average RSSI
int rssi_threshold; /// UE-specific RSSI threshld in 0.1dBm/dBFS, range -1280 to 0
float tpc_in_flight; /// TPCs applied by UE but not yet in average SNR
} nr_power_control_t;
/*! \brief scheduling control information set through an API */
typedef struct {
/// CCE index and aggregation, should be coherent with cce_list
......@@ -665,9 +673,7 @@ typedef struct {
uint16_t ta_frame;
int16_t ta_update;
bool ta_apply;
uint8_t tpc0;
uint8_t tpc1;
int pusch_snrx10;
int pucch_snrx10;
int pusch_consecutive_dtx_cnt;
int pucch_consecutive_dtx_cnt;
......@@ -711,6 +717,8 @@ typedef struct {
// pdcch closed loop adjust for PDCCH aggregation level, range <0, 1>
// 0 - good channel, 1 - bad channel
float pdcch_cl_adjust;
nr_power_control_t pusch_pc;
} NR_UE_sched_ctrl_t;
typedef struct NR_mac_dir_stats {
......@@ -737,7 +745,6 @@ typedef struct NR_mac_stats {
int cumul_sinrx10;
uint8_t num_sinr_meas;
char srs_stats[50]; // Statistics may differ depending on SRS usage
int pusch_snrx10;
int deltaMCS;
int NPRB;
} NR_mac_stats_t;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment