mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
1269 lines
41 KiB
C
1269 lines
41 KiB
C
/*
|
||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||
*/
|
||
|
||
/*!
|
||
* \brief MAC data structures, constant, and function prototype
|
||
*/
|
||
|
||
/*@}*/
|
||
|
||
#ifndef __LAYER2_NR_MAC_GNB_H__
|
||
#define __LAYER2_NR_MAC_GNB_H__
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <complex.h>
|
||
#include <pthread.h>
|
||
#include "fsn.h"
|
||
#include "common/utils/ds/seq_arr.h"
|
||
#include "common/utils/nr/nr_common.h"
|
||
#include "common/utils/ds/byte_array.h"
|
||
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
|
||
|
||
#define NR_SCHED_LOCK(lock) \
|
||
do { \
|
||
int rc = pthread_mutex_lock(lock); \
|
||
AssertFatal(rc == 0, "error while locking scheduler mutex, pthread_mutex_lock() returned %d\n", rc); \
|
||
} while (0)
|
||
|
||
#define NR_SCHED_UNLOCK(lock) \
|
||
do { \
|
||
int rc = pthread_mutex_unlock(lock); \
|
||
AssertFatal(rc == 0, "error while locking scheduler mutex, pthread_mutex_unlock() returned %d\n", rc); \
|
||
} while (0)
|
||
|
||
#define NR_SCHED_ENSURE_LOCKED(lock)\
|
||
do {\
|
||
int rc = pthread_mutex_trylock(lock); \
|
||
AssertFatal(rc == EBUSY, "this function should be called with the scheduler mutex locked, pthread_mutex_trylock() returned %d\n", rc);\
|
||
} while (0)
|
||
|
||
/* Commmon */
|
||
#include "radio/COMMON/common_lib.h"
|
||
#include "common/platform_constants.h"
|
||
#include "common/ran_context.h"
|
||
#include "collection/linear_alloc.h"
|
||
|
||
/* RRC */
|
||
#include "NR_BCCH-BCH-Message.h"
|
||
#include "NR_CellGroupConfig.h"
|
||
#include "NR_BCCH-DL-SCH-Message.h"
|
||
#include "nr_radio_config.h"
|
||
|
||
/* PHY */
|
||
#include "time_meas.h"
|
||
|
||
/* Interface */
|
||
#include "nfapi_nr_interface_scf.h"
|
||
#include "nfapi_nr_interface.h"
|
||
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
|
||
#include "mac_rrc_ul.h"
|
||
|
||
/* MAC */
|
||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||
#include "LAYER2/NR_MAC_gNB/mac_config.h"
|
||
#include "NR_TAG.h"
|
||
|
||
/* Defs */
|
||
#define MAX_NUM_BWP 5
|
||
#define MAX_NUM_CORESET 12
|
||
/*!\brief Maximum number of random access process */
|
||
#define NR_NB_RA_PROC_MAX 4
|
||
#define MAX_NUM_OF_SSB 64
|
||
#define MAX_NUM_NR_PRACH_PREAMBLES 64
|
||
|
||
uint8_t nr_get_rv(int rel_round);
|
||
|
||
/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...).
|
||
* Especially useful in the scheduler and to keep "classes" of users. */
|
||
typedef struct {
|
||
int head;
|
||
int *next;
|
||
int tail;
|
||
int len;
|
||
} NR_list_t;
|
||
|
||
typedef enum {
|
||
nrRA_gNB_IDLE,
|
||
nrRA_Msg2,
|
||
nrRA_WAIT_MsgA_PUSCH,
|
||
nrRA_WAIT_Msg3,
|
||
nrRA_Msg3_retransmission,
|
||
nrRA_Msg4,
|
||
nrRA_MsgB,
|
||
nrRA_WAIT_Msg4_MsgB_ACK,
|
||
} RA_gNB_state_t;
|
||
|
||
static const char *const nrra_text[] =
|
||
{"IDLE", "Msg2", "WAIT_MsgA_PUSCH", "WAIT_Msg3", "Msg3_retransmission", "Msg4", "MsgB", "WAIT_Msg4_MsgB_ACK"};
|
||
|
||
typedef struct {
|
||
int idx;
|
||
bool new_beam;
|
||
} NR_beam_alloc_t;
|
||
|
||
typedef struct nr_pdsch_AntennaPorts_t {
|
||
int N1;
|
||
int N2;
|
||
int XP;
|
||
} nr_pdsch_AntennaPorts_t;
|
||
|
||
typedef struct nr_mac_timers {
|
||
int sr_ProhibitTimer;
|
||
int sr_TransMax;
|
||
int sr_ProhibitTimer_v1700;
|
||
int t300;
|
||
int t301;
|
||
int t310;
|
||
int n310;
|
||
int t311;
|
||
int n311;
|
||
int t319;
|
||
} nr_mac_timers_t;
|
||
|
||
typedef struct nr_redcap_config {
|
||
int8_t cellBarredRedCap1Rx_r17;
|
||
int8_t cellBarredRedCap2Rx_r17;
|
||
uint8_t intraFreqReselectionRedCap_r17;
|
||
} nr_redcap_config_t;
|
||
|
||
typedef struct {
|
||
int dl_FreqDensity0_0;
|
||
int dl_FreqDensity1_0;
|
||
int dl_TimeDensity0_0;
|
||
int dl_TimeDensity1_0;
|
||
int dl_TimeDensity2_0;
|
||
int dl_EpreRatio_0;
|
||
int dl_ReOffset_0;
|
||
int ul_FreqDensity0_0;
|
||
int ul_FreqDensity1_0;
|
||
int ul_TimeDensity0_0;
|
||
int ul_TimeDensity1_0;
|
||
int ul_TimeDensity2_0;
|
||
int ul_ReOffset_0;
|
||
int ul_MaxPorts_0;
|
||
int ul_Power_0;
|
||
} nr_ptrs_config_t;
|
||
|
||
typedef struct {
|
||
int id;
|
||
int scs;
|
||
int location_and_bw;
|
||
} nr_bwp_config_t;
|
||
|
||
typedef enum {
|
||
SSB_RSRP,
|
||
CRI_RSRP,
|
||
SSB_SINR,
|
||
} nr_config_report_type_t;
|
||
|
||
typedef struct nr_beam_table {
|
||
int num_weights_per_beam;
|
||
int num_beams;
|
||
uint16_t *beam_ids;
|
||
double complex **beam_weights;
|
||
} nr_beam_table_t;
|
||
|
||
typedef struct nr_power_config {
|
||
/// target SNR
|
||
int target_snrx10;
|
||
/// RSSI threshold for power control. Limits power control commands when RSSI reaches threshold.
|
||
int rssi_threshold;
|
||
/// Failure threshold (compared to consecutive PUSCH DTX)
|
||
int failure_thres;
|
||
} nr_power_config_t;
|
||
|
||
typedef struct nr_mac_config_s {
|
||
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts;
|
||
int pusch_AntennaPorts;
|
||
int minRXTXTIME;
|
||
int do_CSIRS;
|
||
int do_SRS;
|
||
int do_TCI;
|
||
int max_num_rsrp;
|
||
bool force_256qam_off;
|
||
bool force_UL256qam_off;
|
||
bool use_deltaMCS;
|
||
int maxMIMO_layers;
|
||
bool disable_harq;
|
||
nr_power_config_t pusch;
|
||
/// SNR threshold needed to put or not a PRB in the black list
|
||
int ul_prbblack_SNR_threshold;
|
||
nr_power_config_t pucch;
|
||
nr_mac_timers_t timer_config;
|
||
int num_dlharq;
|
||
int num_ulharq;
|
||
// BWP information
|
||
int num_additional_bwps;
|
||
int first_active_bwp;
|
||
nr_bwp_config_t bwp_config[4];
|
||
/// beamforming weight matrix size
|
||
int nb_bfw[2];
|
||
int32_t *bw_list;
|
||
int num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
|
||
nr_redcap_config_t *redcap;
|
||
nr_ptrs_config_t *ptrs;
|
||
nr_config_report_type_t report_type;
|
||
nr_beam_table_t bt;
|
||
} nr_mac_config_t;
|
||
|
||
typedef struct NR_preamble_ue {
|
||
uint8_t num_preambles;
|
||
uint8_t preamble_list[MAX_NUM_NR_PRACH_PREAMBLES];
|
||
} NR_preamble_ue_t;
|
||
|
||
typedef struct NR_sched_pdcch {
|
||
uint16_t BWPSize;
|
||
uint16_t BWPStart;
|
||
uint8_t CyclicPrefix;
|
||
uint8_t SubcarrierSpacing;
|
||
uint8_t StartSymbolIndex;
|
||
uint8_t CceRegMappingType;
|
||
uint8_t RegBundleSize;
|
||
uint8_t InterleaverSize;
|
||
uint16_t ShiftIndex;
|
||
uint8_t DurationSymbols;
|
||
uint16_t n_rb;
|
||
uint16_t rb_start;
|
||
} NR_sched_pdcch_t;
|
||
|
||
/*! \brief gNB template for the Random access information */
|
||
typedef struct {
|
||
/// Flag to indicate this process is active
|
||
RA_gNB_state_t ra_state;
|
||
/// CORESET0 configured flag
|
||
int coreset0_configured;
|
||
/// Frame where preamble was received
|
||
int preamble_frame;
|
||
/// Slot where preamble was received
|
||
uint8_t preamble_slot;
|
||
/// Received preamble_index
|
||
uint8_t preamble_index;
|
||
/// Timing offset indicated by PHY
|
||
int16_t timing_offset;
|
||
/// Subframe where Msg2 is to be sent
|
||
uint8_t Msg2_slot;
|
||
/// Frame where Msg2 is to be sent
|
||
frame_t Msg2_frame;
|
||
/// Subframe where Msg3 is to be sent
|
||
slot_t Msg3_slot;
|
||
/// Frame where Msg3 is to be sent
|
||
frame_t Msg3_frame;
|
||
/// Msg3 time domain allocation index
|
||
int Msg3_tda_id;
|
||
/// Msg3 beam matrix index
|
||
NR_beam_alloc_t Msg3_beam;
|
||
/// harq_pid used for Msg4 transmission
|
||
uint8_t harq_pid;
|
||
/// RA RNTI allocated from received PRACH
|
||
uint16_t RA_rnti;
|
||
/// MsgB RNTI allocated from received MsgA
|
||
uint16_t MsgB_rnti;
|
||
/// Received UE Contention Resolution Identifier
|
||
uint8_t cont_res_id[6];
|
||
/// Msg3 first RB
|
||
int msg3_first_rb;
|
||
/// Msg3 number of RB
|
||
int msg3_nb_rb;
|
||
/// Msg3 BWP start
|
||
int msg3_bwp_start;
|
||
/// Msg3 TPC command
|
||
uint8_t msg3_TPC;
|
||
/// Round of Msg3 HARQ
|
||
uint8_t msg3_round;
|
||
int msg3_startsymb;
|
||
int msg3_nbSymb;
|
||
/// MAC PDU length for Msg4
|
||
int mac_pdu_length;
|
||
/// Preambles for contention-free access
|
||
NR_preamble_ue_t preambles;
|
||
int contention_resolution_timer;
|
||
nr_ra_type_t ra_type;
|
||
/// CFRA flag
|
||
bool cfra;
|
||
} NR_RA_t;
|
||
|
||
/*! \brief gNB common channels */
|
||
typedef struct {
|
||
frame_type_t frame_type;
|
||
NR_BCCH_BCH_Message_t *mib;
|
||
NR_BCCH_DL_SCH_Message_t *sib1;
|
||
seq_arr_t *du_SIBs;
|
||
NR_ServingCellConfigCommon_t *ServingCellConfigCommon;
|
||
/// Outgoing MIB PDU for PHY
|
||
uint8_t MIB_pdu[3];
|
||
/// Outgoing BCCH pdu for PHY
|
||
uint8_t sib1_bcch_pdu[NR_MAX_SIB_LENGTH / 8];
|
||
int sib1_bcch_length;
|
||
/// used for otherSIB data
|
||
uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8];
|
||
int other_sib_bcch_length[2];
|
||
/// VRB map for common channels
|
||
uint16_t vrb_map[MAX_NUM_BEAM_PERIODS][275];
|
||
/// VRB map for common channels and PUSCH, dynamically allocated because
|
||
/// length depends on number of slots and RBs
|
||
uint16_t *vrb_map_UL[MAX_NUM_BEAM_PERIODS];
|
||
///Number of active SSBs
|
||
int num_active_ssb;
|
||
//Total available prach occasions per configuration period
|
||
int total_prach_occasions_per_config_period;
|
||
//Total available prach occasions
|
||
int total_prach_occasions;
|
||
//Max Association period
|
||
int association_period;
|
||
//SSB index
|
||
uint8_t ssb_index[MAX_NUM_OF_SSB];
|
||
//CB preambles for each SSB
|
||
int cb_preambles_per_ssb;
|
||
/// Max prach length in slots
|
||
int prach_len;
|
||
nr_prach_info_t prach_info;
|
||
} NR_COMMON_channels_t;
|
||
|
||
// SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE
|
||
typedef struct sp_zp_csirs {
|
||
bool is_scheduled; //ZP CSI-RS ACT/Deact MAC CE is scheduled
|
||
bool act_deact; //Activation/Deactivation indication
|
||
uint8_t serv_cell_id; //Identity of Serving cell for which MAC CE applies
|
||
uint8_t bwpid; //Downlink BWP id
|
||
uint8_t rsc_id; //SP ZP CSI-RS resource set
|
||
} sp_zp_csirs_t;
|
||
|
||
//SP CSI-RS / CSI-IM Resource Set Activation/Deactivation MAC CE
|
||
#define MAX_CSI_RESOURCE_SET 64
|
||
typedef struct csi_rs_im {
|
||
bool is_scheduled;
|
||
bool act_deact;
|
||
uint8_t serv_cellid;
|
||
uint8_t bwp_id;
|
||
bool im;
|
||
uint8_t csi_im_rsc_id;
|
||
uint8_t nzp_csi_rsc_id;
|
||
uint8_t nb_tci_resource_set_id;
|
||
uint8_t tci_state_id [ MAX_CSI_RESOURCE_SET ];
|
||
} csi_rs_im_t;
|
||
|
||
typedef struct tciStateInd {
|
||
bool is_scheduled;
|
||
uint32_t coresetId;
|
||
uint32_t tciStateId;
|
||
} tciStateInd_t;
|
||
|
||
typedef struct pucchSpatialRelation {
|
||
bool is_scheduled;
|
||
uint8_t servingCellId;
|
||
uint8_t bwpId;
|
||
uint8_t pucchResourceId;
|
||
bool s0tos7_actDeact[8];
|
||
} pucchSpatialRelation_t;
|
||
|
||
typedef struct SPCSIReportingpucch {
|
||
bool is_scheduled;
|
||
uint8_t servingCellId;
|
||
uint8_t bwpId;
|
||
bool s0tos3_actDeact[4];
|
||
} SPCSIReportingpucch_t;
|
||
|
||
#define MAX_APERIODIC_TRIGGER_STATES 128 //38.331
|
||
typedef struct aperiodicCSI_triggerStateSelection {
|
||
bool is_scheduled;
|
||
uint8_t servingCellId;
|
||
uint8_t bwpId;
|
||
uint8_t highestTriggerStateSelected;
|
||
bool triggerStateSelection[MAX_APERIODIC_TRIGGER_STATES];
|
||
} aperiodicCSI_triggerStateSelection_t;
|
||
|
||
#define MAX_TCI_STATES 128 //38.331
|
||
typedef struct pdschTciStatesActDeact {
|
||
bool is_scheduled;
|
||
uint8_t servingCellId;
|
||
uint8_t bwpId;
|
||
uint8_t highestTciStateActivated;
|
||
bool tciStateActDeact[MAX_TCI_STATES];
|
||
uint8_t codepoint[8];
|
||
} pdschTciStatesActDeact_t;
|
||
|
||
typedef struct UE_info {
|
||
sp_zp_csirs_t sp_zp_csi_rs;
|
||
csi_rs_im_t csi_im;
|
||
tciStateInd_t tci_state_ind;
|
||
pucchSpatialRelation_t pucch_spatial_relation;
|
||
SPCSIReportingpucch_t SP_CSI_reporting_pucch;
|
||
aperiodicCSI_triggerStateSelection_t aperi_CSI_trigger;
|
||
pdschTciStatesActDeact_t pdsch_TCI_States_ActDeact;
|
||
} NR_UE_mac_ce_ctrl_t;
|
||
|
||
typedef struct NR_sched_pucch {
|
||
bool active;
|
||
int frame;
|
||
int ul_slot;
|
||
bool sr_flag;
|
||
int csi_bits;
|
||
bool simultaneous_harqcsi;
|
||
uint8_t dai_c;
|
||
uint8_t timing_indicator;
|
||
uint8_t resource_indicator;
|
||
int r_pucch;
|
||
int prb_start;
|
||
int second_hop_prb;
|
||
int nr_of_symb;
|
||
int start_symb;
|
||
} NR_sched_pucch_t;
|
||
|
||
typedef struct NR_pusch_dmrs {
|
||
uint8_t N_PRB_DMRS;
|
||
uint8_t num_dmrs_symb;
|
||
uint16_t ul_dmrs_symb_pos;
|
||
uint8_t num_dmrs_cdm_grps_no_data;
|
||
nfapi_nr_dmrs_type_e dmrs_config_type;
|
||
int dmrs_scrambling_id;
|
||
int pusch_identity;
|
||
int scid;
|
||
int low_papr_sequence_number;
|
||
NR_PTRS_UplinkConfig_t *ptrsConfig;
|
||
} NR_pusch_dmrs_t;
|
||
|
||
typedef struct NR_sched_pusch {
|
||
int frame;
|
||
int slot;
|
||
|
||
/// RB allocation within active uBWP
|
||
uint16_t rbSize;
|
||
uint16_t rbStart;
|
||
|
||
/// MCS
|
||
uint8_t mcs;
|
||
|
||
/// TBS-related info
|
||
uint16_t R;
|
||
uint8_t Qm;
|
||
uint32_t tb_size;
|
||
|
||
/// UL HARQ PID to use for this UE, or -1 for "any new"
|
||
int8_t ul_harq_pid;
|
||
uint8_t nrOfLayers;
|
||
int tpmi;
|
||
|
||
// time_domain_allocation is the index of a list of tda
|
||
int time_domain_allocation;
|
||
NR_tda_info_t tda_info;
|
||
NR_pusch_dmrs_t dmrs_info;
|
||
bwp_info_t bwp_info;
|
||
int phr_txpower_calc;
|
||
|
||
/// TPC command for this PUSCH
|
||
int tpc_pusch;
|
||
} NR_sched_pusch_t;
|
||
|
||
typedef struct NR_pdsch_dmrs {
|
||
uint8_t dmrs_ports_id;
|
||
uint8_t N_PRB_DMRS;
|
||
uint8_t N_DMRS_SLOT;
|
||
uint16_t dl_dmrs_symb_pos;
|
||
uint8_t numDmrsCdmGrpsNoData;
|
||
uint32_t scrambling_id;
|
||
int n_scid;
|
||
nfapi_nr_dmrs_type_e dmrsConfigType;
|
||
NR_PTRS_DownlinkConfig_t *phaseTrackingRS;
|
||
} NR_pdsch_dmrs_t;
|
||
|
||
struct NR_UE_info;
|
||
struct gNB_MAC_INST_s;
|
||
typedef void (*feedback_action_t)(struct gNB_MAC_INST_s *mac, struct NR_UE_info *ue);
|
||
typedef struct NR_sched_pdsch {
|
||
/// RB allocation within active BWP
|
||
uint16_t rbSize;
|
||
uint16_t rbStart;
|
||
|
||
/// MCS-related infos
|
||
uint8_t mcs;
|
||
|
||
/// TBS-related info
|
||
uint16_t R;
|
||
uint8_t Qm;
|
||
uint32_t tb_size;
|
||
|
||
/// DL HARQ PID to use for this UE, or -1 for "any new"
|
||
int8_t dl_harq_pid;
|
||
|
||
// pucch format allocation
|
||
int16_t pucch_allocation;
|
||
|
||
uint16_t pm_index;
|
||
uint8_t nrOfLayers;
|
||
bwp_info_t bwp_info;
|
||
NR_pdsch_dmrs_t dmrs_parms;
|
||
// time_domain_allocation is the index of a list of tda
|
||
int time_domain_allocation;
|
||
NR_tda_info_t tda_info;
|
||
feedback_action_t action;
|
||
} NR_sched_pdsch_t;
|
||
|
||
typedef struct NR_UE_harq {
|
||
bool is_waiting;
|
||
uint8_t ndi;
|
||
uint8_t round;
|
||
uint16_t feedback_frame;
|
||
uint16_t feedback_slot;
|
||
|
||
/* Transport block to be sent using this HARQ process */
|
||
byte_array_t transportBlock;
|
||
uint32_t tb_size; // size of currently stored TB
|
||
bool start_tci_timer;
|
||
/// sched_pdsch keeps information on MCS etc used for the initial transmission
|
||
NR_sched_pdsch_t sched_pdsch;
|
||
} NR_UE_harq_t;
|
||
|
||
//! fixme : need to enhace for the multiple TB CQI report
|
||
|
||
typedef struct NR_bler_stats {
|
||
frame_t last_frame;
|
||
float bler;
|
||
uint8_t mcs;
|
||
uint64_t rounds[8];
|
||
int last_num_sched; // scheduling count at last BLER update (for activity guard)
|
||
} NR_bler_stats_t;
|
||
|
||
//
|
||
/*! As per spec 38.214 section 5.2.1.4.2
|
||
* - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE shall report in
|
||
a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting.
|
||
* - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE shall report in a
|
||
single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB
|
||
resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
|
||
multiple simultaneous spatial domain receive filter
|
||
*/
|
||
#define MAX_NR_OF_REPORTED_RS 4
|
||
|
||
struct CRI_RI_LI_PMI_CQI {
|
||
uint8_t cri;
|
||
uint8_t ri;
|
||
uint8_t li;
|
||
uint8_t pmi_x1;
|
||
uint8_t pmi_x2;
|
||
uint8_t wb_cqi_1tb;
|
||
uint8_t wb_cqi_2tb;
|
||
uint8_t cqi_table;
|
||
uint8_t csi_report_id;
|
||
bool print_report;
|
||
};
|
||
|
||
typedef struct {
|
||
uint8_t resource_id;
|
||
int RSRP;
|
||
int SINRx10;
|
||
} RSRP_report_t;
|
||
|
||
typedef struct {
|
||
int nb;
|
||
RSRP_report_t r[MAX_NR_OF_REPORTED_RS];
|
||
} RSRP_report_list_t;
|
||
|
||
typedef struct CSI_Report {
|
||
struct CRI_RI_LI_PMI_CQI cri_ri_li_pmi_cqi_report;
|
||
RSRP_report_list_t ssb_rsrp_report;
|
||
RSRP_report_list_t csirs_rsrp_report;
|
||
} CSI_report_t;
|
||
|
||
typedef enum {
|
||
INACTIVE = 0,
|
||
ACTIVE_NOT_SCHED,
|
||
ACTIVE_SCHED
|
||
} NR_UL_harq_states_t;
|
||
|
||
typedef struct NR_UE_ul_harq {
|
||
bool is_waiting;
|
||
uint8_t ndi;
|
||
uint8_t round;
|
||
uint16_t feedback_slot;
|
||
|
||
/// sched_pusch keeps information on MCS etc used for the initial transmission
|
||
NR_sched_pusch_t sched_pusch;
|
||
} NR_UE_ul_harq_t;
|
||
|
||
typedef struct NR_QoS_config_s {
|
||
int fiveQI;
|
||
int priority;
|
||
} NR_QoS_config_t;
|
||
|
||
typedef struct nr_lc_config {
|
||
uint8_t lcid;
|
||
/// flag if corresponding RB is suspended
|
||
bool suspended;
|
||
/// priority as specified in 38.321
|
||
int priority;
|
||
/// associated NSSAI for DRB
|
||
nssai_t nssai;
|
||
/// QoS config for DRB
|
||
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
|
||
NR_SearchSpace_t *search_space;
|
||
NR_ControlResourceSet_t *coreset;
|
||
NR_sched_pdcch_t sched_pdcch;
|
||
|
||
/// CCE index and Aggr. Level are shared for PUSCH/PDSCH allocation decisions
|
||
/// corresponding to the sched_pusch/sched_pdsch structures below
|
||
int cce_index;
|
||
int aggregation_level;
|
||
uint32_t dl_cce_fail, ul_cce_fail;
|
||
|
||
/// Array of PUCCH scheduling information
|
||
/// Its size depends on TDD configuration and max feedback time
|
||
/// There will be a structure for each UL slot in the active period determined by the size
|
||
NR_sched_pucch_t *sched_pucch;
|
||
int sched_pucch_size;
|
||
|
||
/// uplink bytes that are currently scheduled
|
||
int sched_ul_bytes;
|
||
/// estimation of the UL buffer size
|
||
int estimated_ul_buffer;
|
||
|
||
/// PHR info: power headroom level (dB)
|
||
int ph;
|
||
|
||
/// PHR info: nominal UE transmit power levels (dBm)
|
||
int pcmax;
|
||
|
||
/// UE-estimated maximum MCS (from CSI-RS)
|
||
uint8_t dl_max_mcs;
|
||
|
||
/// For UL synchronization: store last UL scheduling grant
|
||
frame_t last_ul_frame;
|
||
slot_t last_ul_slot;
|
||
|
||
/// total amount of data awaiting for this UE
|
||
uint32_t num_total_bytes;
|
||
/// per-LC status data
|
||
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID];
|
||
|
||
/// Estimation of HARQ from BLER
|
||
NR_bler_stats_t dl_bler_stats;
|
||
NR_bler_stats_t ul_bler_stats;
|
||
|
||
uint16_t ta_frame;
|
||
int16_t ta_update;
|
||
bool ta_apply;
|
||
int pusch_consecutive_dtx_cnt;
|
||
int pucch_consecutive_dtx_cnt;
|
||
bool ul_failure;
|
||
int ul_failure_timer;
|
||
int release_timer;
|
||
CSI_report_t CSI_report;
|
||
bool SR;
|
||
/// information about every HARQ process
|
||
NR_UE_harq_t harq_processes[NR_MAX_HARQ_PROCESSES];
|
||
/// HARQ processes that are free
|
||
NR_list_t available_dl_harq;
|
||
/// HARQ processes that await feedback
|
||
NR_list_t feedback_dl_harq;
|
||
/// HARQ processes that await retransmission
|
||
NR_list_t retrans_dl_harq;
|
||
/// information about every UL HARQ process
|
||
NR_UE_ul_harq_t ul_harq_processes[NR_MAX_HARQ_PROCESSES];
|
||
/// UL HARQ processes that are free
|
||
NR_list_t available_ul_harq;
|
||
/// UL HARQ processes that await feedback
|
||
NR_list_t feedback_ul_harq;
|
||
/// UL HARQ processes that await retransmission
|
||
NR_list_t retrans_ul_harq;
|
||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl; // MAC CE related information
|
||
|
||
/// Timer for RRC processing procedures and transmission activity
|
||
NR_timer_t transm_interrupt;
|
||
NR_timer_t tci_beam_switch;
|
||
|
||
/// Timer for timeout before UE is set to UL failure (e.g.,
|
||
/// "TransmissionActionIndicator" handling
|
||
NR_timer_t transm_timeout;
|
||
|
||
/// sri, ul_ri and tpmi based on SRS
|
||
nr_srs_feedback_t srs_feedback;
|
||
|
||
/// per-LC configuration
|
||
seq_arr_t lc_config;
|
||
|
||
// 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_power_control_t pucch_pc;
|
||
} NR_UE_sched_ctrl_t;
|
||
|
||
typedef struct NR_mac_dir_stats {
|
||
uint64_t lc_bytes[64];
|
||
uint64_t rounds[8];
|
||
uint64_t errors;
|
||
uint64_t total_bytes;
|
||
uint32_t current_bytes;
|
||
uint64_t total_sdu_bytes;
|
||
uint32_t total_rbs;
|
||
uint32_t total_rbs_retx;
|
||
uint32_t num_mac_sdu;
|
||
uint32_t current_rbs;
|
||
uint64_t prev_sdu_bytes;
|
||
frame_t last_goodput_frame;
|
||
} NR_mac_dir_stats_t;
|
||
|
||
typedef struct NR_mac_stats {
|
||
NR_mac_dir_stats_t dl;
|
||
NR_mac_dir_stats_t ul;
|
||
uint32_t ulsch_DTX;
|
||
uint64_t ulsch_total_bytes_scheduled;
|
||
uint32_t pucch0_DTX;
|
||
int cumul_rsrp;
|
||
uint8_t num_rsrp_meas;
|
||
int cumul_sinrx10;
|
||
uint8_t num_sinr_meas;
|
||
char srs_stats[50]; // Statistics may differ depending on SRS usage
|
||
int deltaMCS;
|
||
int NPRB;
|
||
} NR_mac_stats_t;
|
||
|
||
typedef struct NR_bler_options {
|
||
double upper;
|
||
double lower;
|
||
uint8_t min_mcs;
|
||
uint8_t max_mcs;
|
||
uint8_t harq_round_max;
|
||
} NR_bler_options_t;
|
||
|
||
typedef struct nr_mac_rrc_ul_if_s {
|
||
f1_reset_du_initiated_func_t f1_reset;
|
||
f1_reset_acknowledge_cu_initiated_func_t f1_reset_acknowledge;
|
||
f1_setup_request_func_t f1_setup_request;
|
||
gnb_du_configuration_update_t gnb_du_configuration_update;
|
||
ue_context_setup_response_func_t ue_context_setup_response;
|
||
ue_context_modification_response_func_t ue_context_modification_response;
|
||
ue_context_modification_required_func_t ue_context_modification_required;
|
||
ue_context_release_request_func_t ue_context_release_request;
|
||
ue_context_release_complete_func_t ue_context_release_complete;
|
||
initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer;
|
||
} nr_mac_rrc_ul_if_t;
|
||
|
||
typedef struct measgap_config {
|
||
bool enable;
|
||
int mgrp_ms;
|
||
long mgrp;
|
||
long gapOffset;
|
||
long mgta;
|
||
int n_slots_mgta;
|
||
int n_slots_advance;
|
||
float mgl_ms;
|
||
long mgl;
|
||
int mgl_slots;
|
||
} measgap_config_t;
|
||
|
||
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
|
||
typedef struct NR_UE_info {
|
||
rnti_t rnti;
|
||
uid_t uid; // unique ID of this UE
|
||
/// scheduling control info
|
||
nr_csi_report_t csi_report_template[MAX_CSI_REPORTCONFIG];
|
||
NR_UE_sched_ctrl_t UE_sched_ctrl;
|
||
NR_UE_DL_BWP_t current_DL_BWP;
|
||
NR_UE_UL_BWP_t current_UL_BWP;
|
||
NR_UE_ServingCell_Info_t sc_info;
|
||
NR_mac_stats_t mac_stats;
|
||
/// currently active CellGroupConfig
|
||
NR_CellGroupConfig_t *CellGroup;
|
||
/// in case of reconfiguration, new CellConfig to apply
|
||
NR_CellGroupConfig_t *reconfigCellGroup;
|
||
NR_UE_NR_Capability_t *capability;
|
||
measgap_config_t measgap_config;
|
||
// UE selected beam index
|
||
uint16_t UE_beam_index;
|
||
/// Per-SSB L1-RSRP table, indexed by SSB index (resource_id from CSI report).
|
||
/// INT16_MIN means no measurement received yet for that beam.
|
||
int16_t beam_rsrp[MAX_NUM_OF_SSB];
|
||
/// Per-SSB L1-SINR×10 table, same indexing. INT16_MIN means no data.
|
||
int16_t beam_sinr[MAX_NUM_OF_SSB];
|
||
float ul_thr_ue;
|
||
float dl_thr_ue;
|
||
float ul_thr_ue_display; ///< slow EWMA for stable display (alpha=0.001)
|
||
float dl_thr_ue_display; ///< slow EWMA for stable display (alpha=0.001)
|
||
long pdsch_HARQ_ACK_Codebook;
|
||
bool is_redcap;
|
||
bool reestablish_rlc;
|
||
NR_RA_t *ra;
|
||
// 3GPP mandates that BWPs are enumerated consecutively, but we only send one (dedicated)
|
||
// BWP to the UE (and modify that BWP on reconfiguration); consequently, the BWP ID for a
|
||
// dedicated BWP is always 1 from the UE's point of view, even if the gNB has multiple BWPs.
|
||
// The below ID is the "true" (non-consecutive) BWP ID from the gNB's point of view
|
||
NR_BWP_Id_t local_bwp_id;
|
||
} NR_UE_info_t;
|
||
|
||
typedef struct {
|
||
/// scheduling control info
|
||
// last element always NULL
|
||
NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1];
|
||
NR_UE_info_t *access_ue_list[NR_NB_RA_PROC_MAX + 1];
|
||
// bitmap of CSI-RS already scheduled in current slot
|
||
int sched_csirs;
|
||
uid_allocator_t uid_allocator;
|
||
} NR_UEs_t;
|
||
|
||
typedef enum {
|
||
NO_BEAM_MODE,
|
||
PRECONFIGURED_BEAM_IDX,
|
||
LOPHY_BEAM_IDX,
|
||
} nr_beam_mode_t;
|
||
|
||
typedef struct {
|
||
/// list of allocated beams per period
|
||
int16_t **beam_allocation;
|
||
int beam_duration; // in slots
|
||
int beams_per_period;
|
||
int beam_allocation_size;
|
||
nr_beam_mode_t beam_mode;
|
||
} NR_beam_info_t;
|
||
|
||
#define UE_iterator(BaSe, VaR) for (NR_UE_info_t **VaR##pptr = BaSe, *VaR = *VaR##pptr; VaR; VaR = *(++VaR##pptr))
|
||
#define FOR_EACH_CANDIDATE(VaR, ArR, N) for (__typeof__(*(ArR)) *VaR = (ArR); VaR < (ArR) + (N); VaR++)
|
||
|
||
typedef struct {
|
||
/// current frame
|
||
frame_t frame;
|
||
/// current slot
|
||
slot_t slot;
|
||
/// FAPI DL req in which allocations are made
|
||
nfapi_nr_dl_tti_request_body_t *dl_req;
|
||
/// TX_data request holds the actual data
|
||
nfapi_nr_tx_data_request_t *TX_req;
|
||
} post_process_pdsch_t;
|
||
|
||
typedef struct {
|
||
/// current frame for DCI
|
||
frame_t frame;
|
||
/// current slot for DCI
|
||
slot_t slot;
|
||
/// FAPI UL_DCI.request in which allocations are to be made
|
||
nfapi_nr_ul_dci_request_t *ul_dci_req;
|
||
/// group PDCCH PDU per CORESET
|
||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_coreset[MAX_NUM_CORESET];
|
||
} post_process_pusch_t;
|
||
|
||
/* forward declarations for scheduling types */
|
||
struct gNB_MAC_INST_s;
|
||
typedef struct nr_dl_candidate nr_dl_candidate_t;
|
||
|
||
/// Scheduling context passed to the RB allocation policy.
|
||
/// Contains per-beam VRB maps so the policy can handle beam partitioning
|
||
/// internally (e.g. for MU-MIMO cross-beam scheduling).
|
||
typedef struct nr_dl_sched_params nr_dl_sched_params_t;
|
||
struct nr_dl_sched_params {
|
||
struct gNB_MAC_INST_s *mac; ///< MAC instance (for CCE/PUCCH validation)
|
||
int CC_id;
|
||
frame_t frame;
|
||
slot_t slot;
|
||
int num_beams; ///< number of beams
|
||
int max_num_ue; ///< max UEs to schedule
|
||
uint16_t *vrb_map[MAX_NUM_BEAM_PERIODS]; ///< per-beam VRB maps [275], mutable
|
||
int n_rb_avail[MAX_NUM_BEAM_PERIODS]; ///< available RBs per beam
|
||
int min_mcs; ///< minimum MCS from BLER config
|
||
float bler_lower; ///< BLER lower threshold (increase MCS if below)
|
||
float bler_upper; ///< BLER upper threshold (decrease MCS if above)
|
||
};
|
||
|
||
/// Per-UE scheduling candidate — read-only inputs for the policy function.
|
||
struct nr_dl_candidate {
|
||
/* ── UE identity / scheduling state (set by collect, never modified after) ── */
|
||
NR_UE_info_t *UE;
|
||
uint16_t rnti; ///< UE RNTI (convenience, avoids UE pointer dereference)
|
||
bool is_retx; ///< true = HARQ retransmission pending
|
||
int8_t retx_harq_pid; ///< HARQ PID for retx, -1 if none
|
||
int retx_rbSize; ///< RBs needed for retx, 0 for new tx
|
||
uint32_t pending_bytes; ///< total bytes waiting in RLC buffers
|
||
uint32_t pending_bytes_per_lcid[NR_MAX_NUM_LCID]; ///< per-LCID bytes waiting in RLC buffers
|
||
uint64_t hol_delay_ms[NR_MAX_NUM_LCID]; ///< per-LCID head-of-line delay in milliseconds (age of oldest SDU)
|
||
float avg_throughput; ///< EWMA goodput in bps (dl_thr_ue)
|
||
float bler; ///< current BLER estimate
|
||
int current_mcs; ///< current MCS state (retx: from HARQ, new tx: from BLER tracker)
|
||
int max_mcs; ///< max allowed MCS (config + UE capability)
|
||
int last_num_sched; ///< scheduled occasions in last BLER window
|
||
bool bler_updated; ///< true if BLER was refreshed this frame
|
||
int mcs_table; ///< MCS table index (from BWP config)
|
||
int bwp_start; ///< UE's BWP start
|
||
int bwp_size; ///< UE's BWP size
|
||
uint64_t fiveQI; ///< 5QI from first DRB's QoS config (0 if none)
|
||
int priority; ///< LC priority from first DRB (lower = higher priority, 0 if none)
|
||
nssai_t nssai; ///< slice/service type/differentiator from first DRB
|
||
|
||
bool skipped; ///< true if dropped by TDA/beam select (skip in downstream stages)
|
||
bool scheduled; ///< true if accepted by the RB-allocation policy
|
||
|
||
/* ── UE CSI observations (set by collect, read-only after) ─────────────── */
|
||
uint16_t cqi; ///< UE-reported wideband CQI
|
||
uint8_t csi_ri; ///< UE-reported rank indicator (0 = rank-1); forced to 0 for DCI 1_0
|
||
int csi_pm_index; ///< PM index derived from UE-reported PMI + antenna config
|
||
const int16_t *beam_rsrp; ///< per-SSB L1-RSRP; points into NR_UE_info_t::beam_rsrp. INT16_MIN = no data
|
||
const int16_t *beam_sinr; ///< per-SSB L1-SINR×10; same indexing. INT16_MIN = no data
|
||
|
||
/* ── gNB decisions (written by the named pipeline stage) ───────────────── */
|
||
/* Use NR_sched_pdsch_t for fields shared with HARQ/dispatch (mcs, rbStart,
|
||
* rbSize, nrOfLayers, pm_index, tda, tda_info, pucch_allocation).*/
|
||
NR_sched_pdsch_t sched_pdsch;
|
||
uint16_t alloc_slbitmap; ///< symbol bitmap derived from sched_pdsch.tda_info
|
||
/* dl_beam_select: beam selection */
|
||
int alloc_beam_dir; ///< beam direction index (initialised from UE->UE_beam_index; may be overridden)
|
||
int alloc_beam_idx; ///< hardware beam structure index, set by beam_allocation_procedure
|
||
bool alloc_new_beam; ///< true if beam alloc claimed a fresh slot (release via reset_beam_status if unscheduled)
|
||
/* commit_alloc: CCE/PUCCH validation */
|
||
int alloc_cce_index; ///< CCE index for PDCCH
|
||
int alloc_aggregation_level; ///< PDCCH aggregation level
|
||
NR_sched_pdcch_t alloc_sched_pdcch; ///< PDCCH scheduling info
|
||
};
|
||
|
||
/* forward declaration to use in nr_pp_impl_dl */
|
||
struct gNB_MAC_INST_s;
|
||
typedef struct gNB_MAC_INST_s gNB_MAC_INST;
|
||
|
||
typedef void (*nr_pp_impl_dl)(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pp_pdsch);
|
||
typedef void (*nr_pp_impl_ul)(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch);
|
||
|
||
/// RI/PMI selection: sets nrOfLayers and pm_index per candidate from CSI feedback.
|
||
/// For retransmissions, nrOfLayers must match the original transmission.
|
||
/// Custom implementations may use SRS reciprocity to override the UE's reported RI/PMI.
|
||
typedef void (*nr_dl_ri_pmi_select_fn)(const gNB_MAC_INST *mac, nr_dl_candidate_t *candidates, int n_candidates);
|
||
|
||
/// MCS adaptation: sets sched_pdsch.mcs from BLER state for every candidate.
|
||
/// Called for all candidates (including those that won't get scheduled) so
|
||
/// BLER-based MCS ramps even for UEs that fail CCE. Also persists the
|
||
/// decision to dl_bler_stats.mcs for continuity across slots.
|
||
typedef void (*nr_dl_mcs_select_fn)(const gNB_MAC_INST *mac, nr_dl_candidate_t *candidates, int n_candidates);
|
||
|
||
/// Beam allocation: assigns beam structure index to each candidate.
|
||
/// beam_index_list maps SSB id -> beam index (same as mac->beam_index_list);
|
||
/// custom implementations can use it with cand->beam_rsrp[] to pick the best beam.
|
||
typedef int (*nr_dl_beam_select_fn)(NR_beam_info_t *beam_info,
|
||
const int16_t *beam_index_list,
|
||
nr_dl_candidate_t *candidates,
|
||
int n_candidates,
|
||
frame_t frame,
|
||
slot_t slot,
|
||
int slots_per_frame);
|
||
|
||
/// TDA selection: assigns tda/tda_info/slbitmap per candidate.
|
||
/// Returns the number of candidates with a valid TDA (compacts invalids out).
|
||
typedef int (
|
||
*nr_dl_tda_select_fn)(const gNB_MAC_INST *mac, nr_dl_candidate_t *candidates, int n_candidates, frame_t frame, slot_t slot);
|
||
|
||
/// Scheduling policy: decides PRB + MCS for candidates across all beams.
|
||
/// The beam loop is inside the policy so it can do cross-beam scheduling (e.g. MU-MIMO).
|
||
/// Writes sched_pdsch.rbStart/rbSize/mcs and cce/pucch fields on scheduled candidates.
|
||
/// Sets candidate->scheduled = true for each accepted UE; returns the count.
|
||
typedef int (*nr_dl_rb_alloc_fn)(const nr_dl_sched_params_t *params, nr_dl_candidate_t *candidates, int n_candidates);
|
||
|
||
/// Per-LCID byte allocation: decides how many bytes each LCID gets within
|
||
/// the available TBS for an initial transmission. Called during MAC PDU
|
||
/// generation. Writes lcid_alloc[lcid] = max data bytes for that LCID.
|
||
/// The execution loop caps actual RLC requests to these budgets.
|
||
typedef void (*nr_dl_lcid_alloc_fn)(const gNB_MAC_INST *mac,
|
||
const nr_dl_candidate_t *candidate,
|
||
int tbs_available,
|
||
int lcid_alloc[NR_MAX_NUM_LCID]);
|
||
|
||
/* UL scheduling refactored data structures */
|
||
struct nr_ul_sched_params;
|
||
typedef struct nr_ul_candidate nr_ul_candidate_t;
|
||
|
||
typedef struct nr_ul_sched_params {
|
||
struct gNB_MAC_INST_s *mac;
|
||
int CC_id;
|
||
frame_t dci_frame; ///< DCI slot frame (current DL slot)
|
||
slot_t dci_slot; ///< DCI slot (current DL slot)
|
||
frame_t frame; ///< scheduled PUSCH frame (future UL slot)
|
||
slot_t slot; ///< scheduled PUSCH slot (future UL slot)
|
||
int num_beams;
|
||
int max_num_ue;
|
||
uint16_t *vrb_map_UL[MAX_NUM_BEAM_PERIODS]; ///< per-beam VRB maps, mutable
|
||
int n_rb_avail[MAX_NUM_BEAM_PERIODS]; ///< available RBs per beam
|
||
int min_rb;
|
||
int min_mcs;
|
||
float bler_lower;
|
||
float bler_upper;
|
||
const NR_ServingCellConfigCommon_t *scc;
|
||
const NR_bler_options_t *bler_opts; ///< UL BLER options (for adapt_ul_mcs)
|
||
} nr_ul_sched_params_t;
|
||
|
||
struct nr_ul_candidate {
|
||
/* ── UE identity / scheduling state (set by collect, never modified after) ── */
|
||
NR_UE_info_t *UE;
|
||
uint16_t rnti; ///< UE RNTI (convenience)
|
||
bool is_retx;
|
||
int8_t retx_harq_pid;
|
||
int retx_rbSize;
|
||
bool sched_inactive;
|
||
uint32_t pending_bytes;
|
||
float avg_throughput;
|
||
float bler;
|
||
int current_mcs;
|
||
int max_mcs;
|
||
int last_num_sched; ///< scheduling count at last BLER update (activity guard)
|
||
bool bler_updated; ///< true if BLER was refreshed this frame
|
||
int mcs_table;
|
||
int bwp_start;
|
||
int bwp_size;
|
||
uint64_t fiveQI; ///< 5QI from first DRB's QoS config (0 if none)
|
||
int priority; ///< LC priority from first DRB (0 if none)
|
||
nssai_t nssai; ///< slice/service type/differentiator from first DRB
|
||
int beam_index;
|
||
|
||
/* ── Power control (set by collect, read-only after) ─────────────────────── */
|
||
int ph; ///< power headroom
|
||
int pcmax; ///< configured max TX power
|
||
int snrx10; ///< PUSCH SINR × 10 (for SINR-based MCS in harq_round_max==1)
|
||
|
||
bool skipped; ///< true if dropped by TDA/beam select (skip in downstream stages)
|
||
bool scheduled; ///< true if accepted by the RB-allocation policy
|
||
|
||
/* ── UE CSI observations (set by collect, read-only after) ─────────────── */
|
||
uint16_t cqi; ///< wideband CQI (from CSI report)
|
||
const int16_t *beam_rsrp; ///< per-SSB L1-RSRP; points into NR_UE_info_t::beam_rsrp. INT16_MIN = no data.
|
||
const int16_t *beam_sinr; ///< per-SSB L1-SINR×10; same indexing. INT16_MIN = no data.
|
||
|
||
/* ── gNB decisions (written by the named pipeline stage) ───────────────── */
|
||
/* Use NR_sched_pusch_t for fields shared with HARQ/dispatch (mcs, rbStart,
|
||
* rbSize, nrOfLayers, tpmi, tda, tda_info).
|
||
* Remaining dispatch-only fields (R, Qm, tb_size, dmrs_info, bwp_info) are
|
||
* filled at dispatch time. Mirrors DL sched_pdsch pattern. */
|
||
NR_sched_pusch_t sched_pusch;
|
||
uint16_t alloc_slbitmap; ///< symbol bitmap derived from sched_pusch.tda_info
|
||
/* ul_beam_select: beam assignment (DCI slot + PUSCH slot) */
|
||
int alloc_dci_beam_idx; ///< beam idx for the DCI slot; -1 = failed
|
||
int alloc_beam_idx; ///< beam idx for the scheduled PUSCH slot; -1 = failed
|
||
bool alloc_dci_beam_new; ///< true if dci_beam was newly allocated
|
||
bool alloc_sched_beam_new; ///< true if sched_beam was newly allocated
|
||
/* commit_ul_alloc: CCE validation */
|
||
int alloc_cce_index;
|
||
int alloc_aggregation_level;
|
||
NR_sched_pdcch_t alloc_sched_pdcch;
|
||
};
|
||
|
||
typedef struct {
|
||
uint16_t rbSize;
|
||
uint8_t mcs;
|
||
bool valid;
|
||
} nr_ul_phr_suggestion_t;
|
||
|
||
typedef struct {
|
||
nr_ul_phr_suggestion_t max_mcs_min_rb;
|
||
nr_ul_phr_suggestion_t same_rb_min_mcs;
|
||
} nr_ul_phr_advice_t;
|
||
|
||
typedef int (*nr_ul_beam_select_fn)(NR_beam_info_t *beam_info,
|
||
const int16_t *beam_index_list,
|
||
nr_ul_candidate_t *candidates,
|
||
int n_candidates,
|
||
frame_t frame,
|
||
slot_t slot,
|
||
frame_t sched_frame,
|
||
slot_t sched_slot,
|
||
int slots_per_frame);
|
||
|
||
/// UL RI/TPMI selection: sets sched_pusch.nrOfLayers and tpmi per candidate from SRS feedback.
|
||
/// Default: reads from srs_feedback (current OAI behavior).
|
||
/// Custom: joint rank/TPMI search from H matrix, ML-based, etc.
|
||
typedef void (*nr_ul_ri_tpmi_select_fn)(gNB_MAC_INST *mac, nr_ul_candidate_t *cands, int n_cand);
|
||
|
||
/// UL TDA selection: picks TDA per candidate (default: same TDA for all), validates retx
|
||
/// feasibility, drops infeasible cands (compact). Returns surviving cand count.
|
||
/// Each surviving cand has sched_pusch.time_domain_allocation/tda_info and alloc_slbitmap populated. Retx cands have retx_rbSize
|
||
/// set.
|
||
typedef int (
|
||
*nr_ul_tda_select_fn)(gNB_MAC_INST *mac, nr_ul_candidate_t *cands, int n_cand, frame_t sched_frame, slot_t sched_slot, int k2);
|
||
|
||
/// MCS selection: sets sched_pusch.mcs from BLER/SINR state for every candidate.
|
||
/// Runs after beam_select so sched_pusch.nrOfLayers (for SINR lookup) and beam info are available.
|
||
/// Also persists the decision to ul_bler_stats.mcs for continuity across slots.
|
||
typedef void (*nr_ul_mcs_select_fn)(const gNB_MAC_INST *mac, nr_ul_candidate_t *candidates, int n_candidates);
|
||
|
||
/// UL scheduling policy: beam loop is inside the policy for cross-beam scheduling.
|
||
/// Sets candidate->scheduled = true for each accepted UE; returns the count.
|
||
typedef int (*nr_ul_rb_alloc_fn)(const nr_ul_sched_params_t *params, nr_ul_candidate_t *candidates, int n_candidates);
|
||
|
||
typedef struct f1_config_t {
|
||
f1ap_setup_req_t *setup_req;
|
||
f1ap_setup_resp_t *setup_resp;
|
||
uint32_t gnb_id; // associated gNB's ID, not used in DU itself
|
||
} f1_config_t;
|
||
|
||
typedef struct {
|
||
char *nvipc_shm_prefix;
|
||
int8_t nvipc_poll_core;
|
||
} nvipc_params_t;
|
||
|
||
typedef struct {
|
||
uint64_t total_prb_aggregate;
|
||
uint64_t used_prb_aggregate;
|
||
} mac_stats_t;
|
||
|
||
typedef struct dlul_mac_stats {
|
||
mac_stats_t dl;
|
||
mac_stats_t ul;
|
||
} dlul_mac_stats_t;
|
||
|
||
typedef struct {
|
||
NR_SearchSpace_t search_space[MAX_NUM_OF_SSB];
|
||
NR_ControlResourceSet_t coreset;
|
||
} NR_sched_ctrl_sib1_t;
|
||
|
||
typedef struct NR_du_stats {
|
||
/// cell-wide wide-band CQI distribution, see 28.552 5.1.1.11.1;
|
||
/// 0-15 CQI, 1-8 RI, 1-3 CQI table
|
||
uint32_t wb_cqi_dist[16][8][3];
|
||
|
||
/// cell-wide MCS distribution in PDSCH, see 28.552 5.1.1.12.1
|
||
/// 1-8 RI, 1-3 MCS table, 0-31 MCS value
|
||
uint32_t pdsch_mcs_dist[8][3][32];
|
||
|
||
/// cell-wide MCS distribution in PUSCH, see 28.552 5.1.1.12.1
|
||
/// 1-8 RI, 1-2 MCS table, 0-31 MCS value
|
||
uint32_t pusch_mcs_dist[8][2][32];
|
||
} NR_du_stats_t;
|
||
|
||
/*! \brief top level eNB MAC structure */
|
||
typedef struct gNB_MAC_INST_s {
|
||
/// Ethernet parameters for northbound midhaul interface
|
||
eth_params_t eth_params_n;
|
||
/// address for F1U to bind, ports in eth_params_n
|
||
char *f1u_addr;
|
||
/// Nvipc parameters for FAPI interface with Aerial
|
||
nvipc_params_t nvipc_params_s;
|
||
/// Module
|
||
module_id_t Mod_id;
|
||
/// timing advance group
|
||
NR_TAG_t *tag;
|
||
/// Pointer to IF module instance for PHY
|
||
NR_IF_Module_t *if_inst;
|
||
pthread_t stats_thread;
|
||
/// Subcarrier Offset
|
||
int ssb_SubcarrierOffset;
|
||
int ssb_OffsetPointA;
|
||
|
||
/// Common cell resources
|
||
NR_COMMON_channels_t common_channels[NFAPI_CC_MAX];
|
||
/// current PDU index (BCH,DLSCH)
|
||
uint16_t pdu_index[NFAPI_CC_MAX];
|
||
/// UL PRBs blacklist
|
||
uint16_t ulprbbl[MAX_BWP_SIZE];
|
||
/// NFAPI Config Request Structure
|
||
nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX];
|
||
/// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure
|
||
/// keeps pointers to PDCCH PDUs within DL_req so that we can easily track
|
||
/// PDCCH PDUs per CC/BWP/CORESET
|
||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_CORESET];
|
||
/// NFAPI UL TTI Request Structure for future TTIs, dynamically allocated
|
||
/// because length depends on number of slots
|
||
nfapi_nr_ul_tti_request_t *UL_tti_req_ahead[NFAPI_CC_MAX];
|
||
int UL_tti_req_ahead_size;
|
||
int vrb_map_UL_size;
|
||
|
||
NR_UEs_t UE_info;
|
||
|
||
// MAC function execution peformance profiler
|
||
/// processing time of gNB scheduler
|
||
time_stats_t gNB_scheduler;
|
||
/// processing time of gNB scheduler for Random access
|
||
time_stats_t schedule_ra;
|
||
/// processing time of gNB DLSCH scheduler
|
||
time_stats_t schedule_ulsch; // include preprocessor
|
||
/// processing time of gNB DLSCH scheduler
|
||
time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor
|
||
/// processing time of rlc_data_req
|
||
time_stats_t rlc_data_req;
|
||
/// processing time of nr_srs_ri_computation
|
||
time_stats_t nr_srs_ri_computation_timer;
|
||
/// processing time of nr_srs_tpmi_estimation
|
||
time_stats_t nr_srs_tpmi_computation_timer;
|
||
/// processing time of gNB ULSCH reception
|
||
time_stats_t rx_ulsch_sdu; // include rlc_data_ind
|
||
|
||
NR_beam_info_t beam_info;
|
||
|
||
/// maximum number of slots before a UE will be scheduled ULSCH automatically
|
||
uint32_t ulsch_max_frame_inactivity;
|
||
/// instance of the frame structure configuration
|
||
frame_structure_t frame_structure;
|
||
|
||
/// DL preprocessor for differentiated scheduling
|
||
nr_pp_impl_dl pre_processor_dl;
|
||
/// UL preprocessor for differentiated scheduling
|
||
nr_pp_impl_ul pre_processor_ul;
|
||
|
||
/// DL scheduling pipeline function pointers
|
||
nr_dl_ri_pmi_select_fn dl_ri_pmi_select;
|
||
nr_dl_tda_select_fn dl_tda_select;
|
||
nr_dl_beam_select_fn dl_beam_select;
|
||
nr_dl_mcs_select_fn dl_mcs_select;
|
||
nr_dl_rb_alloc_fn dl_rb_alloc;
|
||
nr_dl_lcid_alloc_fn dl_lcid_alloc;
|
||
|
||
/// UL RI/TPMI + TDA selection + beam selection + MCS selection + RB allocation
|
||
nr_ul_ri_tpmi_select_fn ul_ri_tpmi_select;
|
||
nr_ul_tda_select_fn ul_tda_select;
|
||
nr_ul_beam_select_fn ul_beam_select;
|
||
nr_ul_mcs_select_fn ul_mcs_select;
|
||
nr_ul_rb_alloc_fn ul_rb_alloc;
|
||
|
||
/// Optional state persistence for scheduling policies.
|
||
void *sched_stateful_data;
|
||
|
||
nr_mac_config_t radio_config;
|
||
nr_rlc_configuration_t rlc_config;
|
||
|
||
NR_sched_ctrl_sib1_t *sched_ctrlSIB1;
|
||
NR_sched_pdcch_t *sched_pdcch_otherSI;
|
||
uint16_t cset0_bwp_start;
|
||
uint16_t cset0_bwp_size;
|
||
NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[MAX_NUM_OF_SSB];
|
||
|
||
bool first_MIB;
|
||
NR_bler_options_t dl_bler;
|
||
NR_bler_options_t ul_bler;
|
||
uint16_t min_grant_prb;
|
||
bool identity_pm;
|
||
int precoding_matrix_size[NR_MAX_NB_LAYERS];
|
||
int16_t beam_index_list[MAX_NUM_OF_SSB];
|
||
NR_sched_pdsch_t sib1_pdsch[MAX_NUM_OF_SSB];
|
||
|
||
/// dedicate UL TDA, common for all UEs
|
||
seq_arr_t ul_tda;
|
||
/// next UL slot to schedule
|
||
fsn_t ul_next;
|
||
|
||
nr_mac_rrc_ul_if_t mac_rrc;
|
||
f1_config_t f1_config;
|
||
int16_t frame;
|
||
|
||
/// number of UEs to exceed to disable stats
|
||
int stats_max_ue;
|
||
/// if stats are currently enabled
|
||
bool print_ue_stats;
|
||
|
||
pthread_mutex_t sched_lock;
|
||
|
||
dlul_mac_stats_t mac_stats;
|
||
uint64_t num_scheduled_prach_rx;
|
||
|
||
NR_du_stats_t du_stats;
|
||
|
||
} gNB_MAC_INST;
|
||
|
||
#endif /*__LAYER2_NR_MAC_GNB_H__ */
|
||
/** @}*/
|