mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 05:00:31 +00:00
Compare commits
26 Commits
develop
...
sl-eurecom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
435bbc1abe | ||
|
|
77b7fd6255 | ||
|
|
075482e673 | ||
|
|
02919e9fa6 | ||
|
|
a2760cdeac | ||
|
|
32b2398b02 | ||
|
|
cf0e037708 | ||
|
|
73e3abed4e | ||
|
|
ffad2609dd | ||
|
|
4854f772b5 | ||
|
|
78fc85c2f3 | ||
|
|
bc94bd04f0 | ||
|
|
61ea4c4ec3 | ||
|
|
e67fb077ad | ||
|
|
3ad16c4071 | ||
|
|
75695da903 | ||
|
|
63da9c4794 | ||
|
|
62a594e137 | ||
|
|
e962382498 | ||
|
|
e698bb284f | ||
|
|
56f8fa77bc | ||
|
|
9369728b3d | ||
|
|
d3e501c827 | ||
|
|
e161d2c9ae | ||
|
|
23e74c5c8c | ||
|
|
b77a6f202d |
@@ -1253,6 +1253,8 @@ set (MAC_NR_SRC_UE
|
||||
${NR_UE_MAC_DIR}/nr_ue_procedures_sl.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_scheduler.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_scheduler_sl.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_sci_slsch.c
|
||||
${NR_UE_MAC_DIR}/nr_slsch_scheduler.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c
|
||||
)
|
||||
|
||||
|
||||
@@ -147,7 +147,11 @@ typedef enum ip_traffic_type_e {
|
||||
TRAFFIC_IPV4_TYPE_BROADCAST = 7,
|
||||
TRAFFIC_IPV4_TYPE_UNKNOWN = 8,
|
||||
TRAFFIC_PC5S_SIGNALLING = 9,
|
||||
TRAFFIC_PC5S_SESSION_INIT = 10
|
||||
TRAFFIC_PC5S_SESSION_INIT = 10,
|
||||
TRAFFIC_NONIP_TYPE_UNKOWN = 11,
|
||||
TRAFFIC_NONIP_TYPE_UNICAST = 12,
|
||||
TRAFFIC_NONIP_TYPE_MULTICAST = 13,
|
||||
TRAFFIC_NONIP_TYPE_BROADCAST = 14
|
||||
} ip_traffic_type_t;
|
||||
|
||||
typedef struct net_ip_address_s {
|
||||
|
||||
@@ -57,9 +57,6 @@
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include <assert.h>
|
||||
#ifdef NDEBUG
|
||||
#warning assert is disabled
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
8
common/utils/colors.h
Normal file
8
common/utils/colors.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
@@ -1138,10 +1138,10 @@ void *UE_thread(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file)
|
||||
void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file, ueinfo_t *ueinfo)
|
||||
{
|
||||
NR_UE_RRC_INST_t *rrc_inst = nr_rrc_init_ue(uecap_file, nb_inst, get_nrUE_params()->nb_antennas_tx);
|
||||
NR_UE_MAC_INST_t *mac_inst = nr_l2_init_ue(nb_inst);
|
||||
NR_UE_MAC_INST_t *mac_inst = nr_l2_init_ue(nb_inst, ueinfo);
|
||||
AssertFatal(mac_inst, "Couldn't allocate MAC module\n");
|
||||
|
||||
for (int i = 0; i < nb_inst; i++) {
|
||||
@@ -1153,7 +1153,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
|
||||
nr_rlc_activate_srb0(mac_inst[i].crnti, NULL, send_srb0_rrc);
|
||||
}
|
||||
//TODO: Move this call to RRC
|
||||
start_sidelink((&rrc_inst[i])->ue_id);
|
||||
start_sidelink((&rrc_inst[i])->ue_id, ueinfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "nr_nas_msg.h"
|
||||
#include <openair1/PHY/MODULATION/nr_modulation.h>
|
||||
#include "openair2/GNB_APP/gnb_paramdef.h"
|
||||
#include "openair2/RRC/NR_UE/sl_preconfig_paramvalues.h"
|
||||
#include "pdcp.h"
|
||||
#include "actor.h"
|
||||
|
||||
@@ -129,6 +130,8 @@ int otg_enabled;
|
||||
double cpuf;
|
||||
uint32_t N_RB_DL = 106;
|
||||
|
||||
nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
|
||||
int create_tasks_nrue(uint32_t ue_nb) {
|
||||
LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb);
|
||||
itti_wait_ready(1);
|
||||
@@ -253,7 +256,7 @@ void init_openair0()
|
||||
uint64_t dl_carrier, ul_carrier;
|
||||
openair0_cfg[card].configFilename = NULL;
|
||||
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
|
||||
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
|
||||
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; // IS_SOFTMODEM_RFSIM ? frame_parms->samples_per_subframe * 1e3 : 46080000;
|
||||
openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame;
|
||||
|
||||
if (frame_parms->frame_type==TDD)
|
||||
@@ -446,18 +449,30 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
ueinfo_t ueinfo;
|
||||
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
||||
paramdef_t SL_UEINFO[] = SL_UEINFO_DESC(ueinfo);
|
||||
paramlist_def_t SL_UEINFOList = {SL_CONFIG_STRING_UEINFO, NULL, 0};
|
||||
sprintf(aprefix, "%s.[%d]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0);
|
||||
config_getlist(config_get_if(), &SL_UEINFOList, NULL, 0, aprefix);
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0, SL_CONFIG_STRING_UEINFO, 0);
|
||||
config_get(config_get_if(), SL_UEINFO, sizeof(SL_UEINFO)/sizeof(paramdef_t), aprefix);
|
||||
|
||||
int mode_offset = get_softmodem_params()->nsa ? NUMBER_OF_UE_MAX : 1;
|
||||
uint16_t node_number = get_softmodem_params()->node_number;
|
||||
ue_id_g = (node_number == 0) ? 0 : node_number - 2;
|
||||
AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n");
|
||||
|
||||
if (node_number == 0)
|
||||
if(node_number == 0 && get_softmodem_params()->sl_mode == 0) {
|
||||
init_pdcp(0);
|
||||
else
|
||||
} else if (get_softmodem_params()->sl_mode == 2) {
|
||||
init_pdcp(1+ueinfo.srcid);
|
||||
} else {
|
||||
init_pdcp(mode_offset + ue_id_g);
|
||||
}
|
||||
nas_init_nrue(NB_UE_INST);
|
||||
|
||||
init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file);
|
||||
init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file, &ueinfo);
|
||||
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
RCconfig_nr_ue_macrlc();
|
||||
@@ -581,4 +596,3 @@ int main(int argc, char **argv)
|
||||
free(pckg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,20 @@
|
||||
#include <executables/softmodem-common.h>
|
||||
#include "common/utils/threadPool/thread-pool.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
typedef struct ueinfo {
|
||||
int srcid;
|
||||
int thirdOctet;
|
||||
int fourthOctet;
|
||||
} ueinfo_t;
|
||||
|
||||
#define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed\n"
|
||||
#define CONFIG_HLP_IF_FREQ_OFF "UL IF frequency offset for RF, if needed\n"
|
||||
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n"
|
||||
#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n"
|
||||
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
|
||||
#define CONFIG_HLP_SL_SYNCSOURCEUE "Sidelink UE acts as SYNC REF UE"
|
||||
#define CONFIG_HLP_SL_MAX_MCS "Sidelink initial max mcs value"
|
||||
#define CONFIG_HLP_SL_SNR "Sets sidelink SNR value"
|
||||
#define CONFIG_HLP_TIME_SYNC_P "coefficient for Proportional part of time sync PI controller\n"
|
||||
#define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n"
|
||||
#define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n"
|
||||
@@ -27,6 +35,7 @@
|
||||
#define CALIBPRACH_OPT "calib-prach-tx"
|
||||
#define DUMPFRAME_OPT "ue-dump-frame"
|
||||
|
||||
#define SL_UE_iterator(BaSe, VaR) NR_SL_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters defining UE running mode */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -64,6 +73,9 @@
|
||||
{"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
{"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \
|
||||
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
|
||||
{"sync-ref", CONFIG_HLP_SL_SYNCSOURCEUE, PARAMFLAG_BOOL, .uptr=&(nrUE_params.sync_ref), .defuintval=0, TYPE_UINT32, 0}, \
|
||||
{"mcs", CONFIG_HLP_SL_MAX_MCS, 0, .u8ptr=&(nrUE_params.mcs), .defintval=9, TYPE_UINT8, 0}, \
|
||||
{"snr", CONFIG_HLP_SL_SNR, 0, .dblptr=&(nrUE_params.snr), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -83,6 +95,9 @@ typedef struct {
|
||||
int nb_antennas_tx;
|
||||
int N_RB_DL;
|
||||
int ssb_start_subcarrier;
|
||||
uint32_t sync_ref;
|
||||
uint8_t mcs;
|
||||
double snr;
|
||||
double time_sync_P;
|
||||
double time_sync_I;
|
||||
int autonomous_ta;
|
||||
@@ -107,7 +122,7 @@ extern nrUE_params_t *get_nrUE_params(void);
|
||||
// In nr-ue.c
|
||||
extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
extern void fill_ue_band_info(void);
|
||||
extern void init_NR_UE(int, char *, char *, char *);
|
||||
extern void init_NR_UE(int, char *, char *, char *, ueinfo_t*);
|
||||
extern void init_NR_UE_threads(PHY_VARS_NR_UE *ue);
|
||||
void start_oai_nrue_threads(void);
|
||||
void *UE_thread(void *arg);
|
||||
|
||||
@@ -114,6 +114,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint8_t harq_pid;
|
||||
uint8_t ack_nack;
|
||||
uint8_t *ack_nack_rcvd;
|
||||
uint8_t num_acks_rcvd;
|
||||
uint32_t pdu_length;
|
||||
uint8_t* pdu;
|
||||
} fapi_nr_pdsch_pdu_t;
|
||||
|
||||
@@ -5,11 +5,30 @@
|
||||
|
||||
#define SL_NR_RX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_TX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_RX_IND_MAX_PDU 1
|
||||
#define SL_NR_RX_IND_MAX_PDU 2
|
||||
#define SL_NR_SCI_IND_MAX_PDU 2
|
||||
#define SL_NR_MAX_PSCCH_SCI_LENGTH_IN_BYTES 8
|
||||
#define SL_NR_MAX_PSSCH_SCI_LENGTH_IN_BYTES 8
|
||||
#define SL_NR_MAX_SCI_LENGTH_IN_BYTES 8
|
||||
|
||||
typedef struct sl_nr_tti_csi_rs_pdu {
|
||||
uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4
|
||||
uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended
|
||||
uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274
|
||||
uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276
|
||||
uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP
|
||||
uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18
|
||||
uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter
|
||||
uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13
|
||||
uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12
|
||||
uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4
|
||||
uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three
|
||||
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
|
||||
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
|
||||
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
|
||||
uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1
|
||||
} sl_nr_tti_csi_rs_pdu_t;
|
||||
|
||||
typedef enum sl_sci_format_type_enum {
|
||||
SL_SCI_INVALID_FORMAT,
|
||||
SL_SCI_FORMAT_1A_ON_PSCCH,
|
||||
@@ -20,7 +39,8 @@ typedef enum sl_sci_format_type_enum {
|
||||
typedef enum sl_rx_pdu_type_enum {
|
||||
SL_NR_RX_PDU_TYPE_NONE,
|
||||
SL_NR_RX_PDU_TYPE_SSB,
|
||||
SL_NR_RX_PDU_TYPE_SLSCH
|
||||
SL_NR_RX_PDU_TYPE_SLSCH,
|
||||
SL_NR_RX_PDU_TYPE_SLSCH_PSFCH,
|
||||
} sl_rx_pdu_type_enum_t;
|
||||
|
||||
//Type of SL-RX CONFIG requests from MAC to PHY
|
||||
@@ -30,6 +50,7 @@ typedef enum sl_nr_rx_config_type_enum {
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SCI,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS,
|
||||
SL_NR_CONFIG_TYPE_RX_MAXIMUM
|
||||
} sl_nr_rx_config_type_enum_t;
|
||||
|
||||
@@ -37,7 +58,8 @@ typedef enum sl_nr_rx_config_type_enum {
|
||||
typedef enum sl_nr_tx_config_type_enum {
|
||||
SL_NR_CONFIG_TYPE_TX_PSBCH = SL_NR_CONFIG_TYPE_RX_MAXIMUM + 1,
|
||||
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH,
|
||||
SL_NR_CONFIG_TYPE_TX_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS,
|
||||
SL_NR_CONFIG_TYPE_TX_MAXIMUM
|
||||
} sl_nr_tx_config_type_enum_t;
|
||||
|
||||
@@ -69,7 +91,7 @@ typedef struct {
|
||||
uint8_t sensing_result;
|
||||
//in case pssch sensing is requested.
|
||||
int16_t pssch_rsrp;
|
||||
sl_nr_sci_indication_pdu_t sci_pdu;
|
||||
sl_nr_sci_indication_pdu_t sci_pdu[SL_NR_SCI_IND_MAX_PDU];
|
||||
} sl_nr_sci_indication_t;
|
||||
|
||||
// IF UE Rx PSBCH, PHY indicates MAC with received MIB and PSBCH RSRP
|
||||
@@ -191,6 +213,22 @@ typedef struct sl_nr_rx_config_pssch_pdu {
|
||||
uint8_t ndi;
|
||||
} sl_nr_rx_config_pssch_pdu_t;
|
||||
|
||||
typedef struct sl_nr_tx_rx_config_psfch_pdu {
|
||||
// These fields can be mapped directly to the same fields in nfapi_nr_ul_config_pucch_pdu
|
||||
uint8_t freq_hop_flag;
|
||||
uint8_t group_hop_flag;
|
||||
uint8_t sequence_hop_flag;
|
||||
uint16_t second_hop_prb;
|
||||
uint8_t nr_of_symbols;
|
||||
uint8_t start_symbol_index;
|
||||
uint8_t hopping_id;
|
||||
uint16_t prb;
|
||||
uint16_t sl_bwp_start;
|
||||
uint16_t initial_cyclic_shift;
|
||||
uint8_t mcs;
|
||||
uint8_t bit_len_harq;
|
||||
} sl_nr_tx_rx_config_psfch_pdu_t;
|
||||
|
||||
typedef struct {
|
||||
sl_nr_rx_config_type_enum_t pdu_type; // indicates the type of RX config request
|
||||
union {
|
||||
@@ -198,6 +236,9 @@ typedef struct {
|
||||
sl_nr_rx_config_pssch_sci_pdu_t rx_sci2_config_pdu;
|
||||
sl_nr_rx_config_pssch_pdu_t rx_pssch_config_pdu;
|
||||
};
|
||||
sl_nr_tti_csi_rs_pdu_t rx_csi_rs_config_pdu;
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *rx_psfch_pdu_list;
|
||||
uint16_t num_psfch_pdus;
|
||||
} sl_nr_rx_config_request_pdu_t;
|
||||
|
||||
// MAC commands PHY to perform an action on RX RESOURCE POOL or RX PSBCH using this RX CONFIG
|
||||
@@ -244,6 +285,9 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
|
||||
//Indicates the number of symbols for PSCCH+PSSCH txn
|
||||
uint8_t pssch_numsym;
|
||||
|
||||
// start symbol of PSCCH/PSSCH (excluding AGC)
|
||||
uint8_t pssch_startsym;
|
||||
|
||||
//.... Other Parameters for SCI-2 and PSSCH
|
||||
|
||||
// Used to determine number of SCI2 modulated symbols
|
||||
@@ -267,13 +311,21 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
|
||||
uint16_t dmrs_symbol_position;
|
||||
|
||||
|
||||
// PSFCH related parameters
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
|
||||
uint16_t num_psfch_pdus;
|
||||
//....TBD.. any additional parameters
|
||||
|
||||
// CSI-RS related parameters
|
||||
sl_nr_tti_csi_rs_pdu_t nr_sl_csi_rs_pdu;
|
||||
|
||||
//TX Power for PSSCH in symbol without PSCCH.
|
||||
// Power for PSCCH and power for PSSCH in symbol with PSCCH is calculated
|
||||
// from this value according to 38.213 section 16
|
||||
int16_t pssch_tx_power;
|
||||
|
||||
uint16_t slsch_payload_length;
|
||||
uint8_t *slsch_payload;
|
||||
} sl_nr_tx_config_pscch_pssch_pdu_t;
|
||||
|
||||
// MAC indicates PHY to send PSBCH.
|
||||
@@ -383,7 +435,26 @@ typedef struct {
|
||||
//only 1 SL-BWP can be configured in REL16, REL17
|
||||
sl_nr_bwp_config_t sl_bwp_config;
|
||||
|
||||
uint32_t sl_DMRS_ScrambleId;
|
||||
|
||||
} sl_nr_phy_config_request_t;
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR {
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_NOTHING, /* No components present */
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots4,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots5,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots8,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots10,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots16,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots20,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots32,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots40,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots64,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots80,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots160,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots320,
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots640
|
||||
} NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -341,7 +341,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
int32_t sync_pos = -1; // sync_pos_frame = -1;
|
||||
int32_t metric_tdd_ncp = 0;
|
||||
uint8_t phase_tdd_ncp;
|
||||
uint8_t phase_tdd_ncp = 0;
|
||||
double im, re;
|
||||
int ret = -1;
|
||||
uint16_t rx_slss_id = 65535;
|
||||
|
||||
@@ -275,6 +275,12 @@
|
||||
/* - between reception of un uplink grant and its related transmission (k2) */
|
||||
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3)
|
||||
|
||||
#ifndef NO_RAT_NR
|
||||
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */
|
||||
#else
|
||||
#define DURATION_RX_TO_TX (6) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */
|
||||
#endif
|
||||
|
||||
#define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */
|
||||
#define NR_MAX_DLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 5.1 UE procedure for receiving the physical downlink shared channel */
|
||||
#endif
|
||||
|
||||
@@ -857,7 +857,7 @@ int main(int argc, char **argv)
|
||||
|
||||
init_nr_ue_transport(UE);
|
||||
|
||||
nr_l2_init_ue(1);
|
||||
nr_l2_init_ue(1, NULL);
|
||||
UE_mac = get_mac_inst(0);
|
||||
ue_init_config_request(UE_mac, mu);
|
||||
|
||||
|
||||
@@ -729,7 +729,7 @@ int main(int argc, char *argv[])
|
||||
init_nr_ue_transport(UE);
|
||||
|
||||
//Configure UE
|
||||
nr_l2_init_ue(1);
|
||||
nr_l2_init_ue(1, NULL);
|
||||
NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);
|
||||
|
||||
ue_init_config_request(UE_mac, mu);
|
||||
|
||||
@@ -137,6 +137,8 @@ typedef struct NRRrcMacSBcchDataInd_s {
|
||||
uint16_t rx_slss_id;
|
||||
uint8_t rsrq;
|
||||
uint8_t rsrp;
|
||||
uint32_t phycellid;
|
||||
long ssb_arfcn;
|
||||
} NRRrcMacSBcchDataInd;
|
||||
|
||||
typedef struct RrcMacBcchMbmsDataReq_s {
|
||||
|
||||
@@ -101,6 +101,54 @@ uint32_t nr_compute_tbs(uint16_t Qm,
|
||||
return nr_tbs;
|
||||
}
|
||||
|
||||
uint32_t nr_compute_tbs_sl(uint16_t Qm,
|
||||
uint16_t R,
|
||||
uint16_t nb_re,
|
||||
uint8_t Nl)
|
||||
{
|
||||
|
||||
LOG_D(NR_MAC, "In %s: nb_re %d, Nl %d\n", __FUNCTION__, nb_re,Nl);
|
||||
|
||||
// Intermediate number of information bits
|
||||
// Rx1024 is tabulated as 10 times the actual code rate
|
||||
const uint32_t R_5 = R/5; // R can be fractional so we can't divide by 10
|
||||
// So we ned to right shift by 11 (10 for x1024 and 1 additional as above)
|
||||
const uint32_t Ninfo = ((nb_re * R_5 * Qm * Nl)>>11);
|
||||
|
||||
uint32_t nr_tbs=0;
|
||||
uint32_t Np_info, C, n;
|
||||
|
||||
if (Ninfo <=3824) {
|
||||
n = max(3, floor(log2(Ninfo)) - 6);
|
||||
Np_info = max(24, (Ninfo>>n)<<n);
|
||||
for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
|
||||
if (Tbstable_nr[i] >= Np_info){
|
||||
nr_tbs = Tbstable_nr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n = log2(Ninfo-24)-5;
|
||||
Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
|
||||
|
||||
if (R <= 2560) {
|
||||
C = CEILIDIV((Np_info+24),3816);
|
||||
nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
|
||||
} else {
|
||||
if (Np_info > 8424){
|
||||
C = CEILIDIV((Np_info+24),8424);
|
||||
nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
|
||||
} else {
|
||||
nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "Ninfo %u nb_re %d Qm %d, R %d, tbs %d bits\n", Ninfo, nb_re, Qm, R, nr_tbs);
|
||||
|
||||
return nr_tbs;
|
||||
}
|
||||
|
||||
//tbslbrm calculation according to 5.4.2.1 of 38.212
|
||||
uint32_t nr_compute_tbslbrm(uint16_t table,
|
||||
uint16_t nb_rb,
|
||||
|
||||
@@ -107,6 +107,14 @@ typedef struct {
|
||||
uint8_t R: 2; // octet 1 [7:6]
|
||||
} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_FIXED;
|
||||
|
||||
// 38321 section 6.1.6 Figure 6.1.6-1
|
||||
typedef struct {
|
||||
uint8_t V: 4; // octet 1 [7:4]
|
||||
uint8_t R: 4; // octet 1 [3:0]
|
||||
uint16_t SRC: 16; // octet 2, octet 3
|
||||
uint8_t DST: 8; // octet 4
|
||||
}__attribute__ ((__packed__)) NR_SLSCH_MAC_SUBHEADER_FIXED;
|
||||
|
||||
static inline int get_mac_len(uint8_t *pdu, uint32_t pdu_len, uint16_t *mac_ce_len, uint16_t *mac_subheader_len)
|
||||
{
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
@@ -130,6 +138,17 @@ static inline int get_mac_len(uint8_t *pdu, uint32_t pdu_len, uint16_t *mac_ce_l
|
||||
return true;
|
||||
}
|
||||
|
||||
// SL BSR MAC CEs
|
||||
// TS 38.321 ch. 6.1.3.33
|
||||
// Short BSR for a specific logical channel group ID
|
||||
typedef struct {
|
||||
uint8_t destination_index: 5; // octet 1 MSB
|
||||
uint8_t LcgID: 3; // octet 1 LSB
|
||||
uint8_t Buffer_size: 8;
|
||||
} __attribute__ ((__packed__)) NR_SL_BSR_SHORT;
|
||||
|
||||
typedef NR_SL_BSR_SHORT NR_SL_BSR_SHORT_TRUNCATED;
|
||||
|
||||
// BSR MAC CEs
|
||||
// TS 38.321 ch. 6.1.3.1
|
||||
// Short BSR for a specific logical channel group ID
|
||||
@@ -458,7 +477,24 @@ typedef struct {
|
||||
#define UL_SCH_LCID_L_BSR 0x3E
|
||||
#define UL_SCH_LCID_PADDING 0x3F
|
||||
|
||||
#define NR_MAX_NUM_LCID 32
|
||||
#define NR_MAX_NUM_LCGID 8
|
||||
|
||||
#define SL_SCH_LCID_SCCH_PC5_NOT_PROT 0 // SCCH carrying PC5-S messages that are not protected
|
||||
#define SL_SCH_LCID_SCCH_PC5_DSMC 1 // SCCH carrying PC5-S messages "Direct Security Mode Command" and "Direct Security Mode Complete"
|
||||
#define SL_SCH_LCID_SCCH_PC5_PROT 2 // SCCH carrying other PC5-S messages that are protected
|
||||
#define SL_SCH_LCID_SCCH_PC5_RRC 3 // SCCH carrying PC5-RRC messages
|
||||
#define SL_SCH_LCID_4_19 4 // 4–19 Identity of the logical channel
|
||||
#define SL_SCH_LCID_20_55 20 // 20–55 Reserved
|
||||
#define SL_SCH_LCID_SCCH_RRC_SL_RLC0 56 // SCCH carrying RRC messages delivered via SL-RLC0 as specified in TS 38.331 [5]
|
||||
#define SL_SCH_LCID_SCCH_RRC_SL_RLC1 57 // SCCH carrying RRC message delivered via SL-RLC1 as specified in TS 38.331 [5]
|
||||
#define SL_SCH_LCID_SCCH_SL_DISCOVERY 58 // SCCH for Sidelink Discovery Messages
|
||||
#define SL_SCH_LCID_SL_INTER_UE_COORD_REQ 59 // Sidelink Inter-UE Coordination Request
|
||||
#define SL_SCH_LCID_SL_INTER_UE_COORD_INFO 60 // Sidelink Inter-UE Coordination Information
|
||||
#define SL_SCH_LCID_SL_DRX_CMD 61 // Sidelink DRX Command
|
||||
#define SL_SCH_LCID_SL_CSI_REPORT 62 // Sidelink CSI Reporting
|
||||
#define SL_SCH_LCID_SL_PADDING 63 // Padding
|
||||
|
||||
#define MAX_RLC_SDU_SUBHEADER_SIZE 3
|
||||
|
||||
//===========
|
||||
@@ -576,6 +612,25 @@ typedef struct nr_csi_report {
|
||||
int N2;
|
||||
} nr_csi_report_t;
|
||||
|
||||
// 38321 sec. 6.1.3.35
|
||||
typedef struct {
|
||||
uint8_t RI: 1; // 7th bit
|
||||
uint8_t CQI: 4; // 3-6 bits
|
||||
uint8_t R: 3; // 0-2 bits
|
||||
} __attribute__ ((__packed__)) nr_sl_csi_report_t;
|
||||
|
||||
// 38321 sec. 6.1.3.34
|
||||
typedef struct {
|
||||
uint8_t C1: 1; // 1st bit
|
||||
uint8_t C2: 1; // 2nd bit
|
||||
uint8_t C3: 1; // 3rd bit
|
||||
uint8_t C4: 1; // 4th bit
|
||||
uint8_t C5: 1; // 5th bit
|
||||
uint8_t C6: 1; // 6th bit
|
||||
uint8_t C7: 1; // 7th bit
|
||||
uint8_t C8: 1; // 8th bit
|
||||
} __attribute__ ((__packed__)) nr_sl_config_grant_t;
|
||||
|
||||
typedef enum {
|
||||
NR_SRS_SRI_0 = 0,
|
||||
NR_SRS_SRI_1,
|
||||
@@ -695,5 +750,14 @@ typedef enum {
|
||||
RA_2_STEP = 1,
|
||||
} nr_ra_type_t;
|
||||
|
||||
/*! \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;
|
||||
|
||||
#endif /*__LAYER2_MAC_H__ */
|
||||
|
||||
|
||||
@@ -37,6 +37,61 @@
|
||||
|
||||
#define reserved 0xffff
|
||||
|
||||
// CQI TABLES (10 times the value in 214 to adequately compare with R)
|
||||
// Table 1 (38.214 5.2.2.1-2)
|
||||
static const uint16_t cqi_table1[16][2] = {{0, 0},
|
||||
{2, 780},
|
||||
{2, 1200},
|
||||
{2, 1930},
|
||||
{2, 3080},
|
||||
{2, 4490},
|
||||
{2, 6020},
|
||||
{4, 3780},
|
||||
{4, 4900},
|
||||
{4, 6160},
|
||||
{6, 4660},
|
||||
{6, 5670},
|
||||
{6, 6660},
|
||||
{6, 7720},
|
||||
{6, 8730},
|
||||
{6, 9480}};
|
||||
|
||||
// Table 2 (38.214 5.2.2.1-3)
|
||||
static const uint16_t cqi_table2[16][2] = {{0, 0},
|
||||
{2, 780},
|
||||
{2, 1930},
|
||||
{2, 4490},
|
||||
{4, 3780},
|
||||
{4, 4900},
|
||||
{4, 6160},
|
||||
{6, 4660},
|
||||
{6, 5670},
|
||||
{6, 6660},
|
||||
{6, 7720},
|
||||
{6, 8730},
|
||||
{8, 7110},
|
||||
{8, 7970},
|
||||
{8, 8850},
|
||||
{8, 9480}};
|
||||
|
||||
// Table 2 (38.214 5.2.2.1-4)
|
||||
static const uint16_t cqi_table3[16][2] = {{0, 0},
|
||||
{2, 300},
|
||||
{2, 500},
|
||||
{2, 780},
|
||||
{2, 1200},
|
||||
{2, 1930},
|
||||
{2, 3080},
|
||||
{2, 4490},
|
||||
{2, 6020},
|
||||
{4, 3780},
|
||||
{4, 4900},
|
||||
{4, 6160},
|
||||
{6, 4660},
|
||||
{6, 5670},
|
||||
{6, 6660},
|
||||
{6, 7720}};
|
||||
|
||||
//38.321 Table 6.1.3.1-1
|
||||
const uint32_t NR_SHORT_BSR_TABLE[NR_SHORT_BSR_TABLE_SIZE] = {
|
||||
0, 10, 14, 20, 28, 38, 53, 74,
|
||||
@@ -3709,6 +3764,93 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
|
||||
return l_prime;
|
||||
}
|
||||
|
||||
#define BLER_UPDATE_FRAME 10
|
||||
#define BLER_FILTER 0.9f
|
||||
int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
const NR_mac_dir_stats_t *stats,
|
||||
NR_bler_stats_t *bler_stats,
|
||||
int max_mcs,
|
||||
frame_t frame)
|
||||
{
|
||||
/* first call: everything is zero. Initialize to sensible default */
|
||||
if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) {
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = 9;
|
||||
bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f;
|
||||
}
|
||||
int diff = frame - bler_stats->last_frame;
|
||||
if (diff < 0) // wrap around
|
||||
diff += 1024;
|
||||
|
||||
max_mcs = min(max_mcs, bler_options->max_mcs);
|
||||
const uint8_t old_mcs = min(bler_stats->mcs, max_mcs);
|
||||
if (diff < BLER_UPDATE_FRAME)
|
||||
return old_mcs; // no update
|
||||
|
||||
// last update is longer than x frames ago
|
||||
const int dtx = (int)(stats->rounds[0] - bler_stats->rounds[0]);
|
||||
const int dretx = (int)(stats->rounds[1] - bler_stats->rounds[1]);
|
||||
const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler;
|
||||
bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window;
|
||||
|
||||
int new_mcs = old_mcs;
|
||||
// EpiSci TODO: In following statement, dtx > 9 in function on sl-eurecom2 branch
|
||||
if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && dtx > 3)
|
||||
new_mcs += 1;
|
||||
else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold
|
||||
|| (dtx <= 3 && old_mcs > 9)) // no activity
|
||||
new_mcs -= 1;
|
||||
// else we are within threshold boundaries
|
||||
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = new_mcs;
|
||||
memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds));
|
||||
LOG_D(MAC, "frame %4d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f)\n",
|
||||
frame, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler);
|
||||
return new_mcs;
|
||||
}
|
||||
|
||||
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx, int default_mcs)
|
||||
{
|
||||
if (cqi_idx <= 0) {
|
||||
LOG_E(NR_MAC, "invalid cqi_idx %d, default to MCS 9\n", cqi_idx);
|
||||
return default_mcs;
|
||||
}
|
||||
|
||||
if (mcs_table != cqi_table) {
|
||||
LOG_E(NR_MAC, "indices of CQI (%d) and MCS (%d) tables don't correspond yet\n", cqi_table, mcs_table);
|
||||
return default_mcs;
|
||||
}
|
||||
|
||||
uint16_t target_coderate, target_qm;
|
||||
switch (cqi_table) {
|
||||
case 0:
|
||||
target_qm = cqi_table1[cqi_idx][0];
|
||||
target_coderate = cqi_table1[cqi_idx][1];
|
||||
break;
|
||||
case 1:
|
||||
target_qm = cqi_table2[cqi_idx][0];
|
||||
target_coderate = cqi_table2[cqi_idx][1];
|
||||
break;
|
||||
case 2:
|
||||
target_qm = cqi_table3[cqi_idx][0];
|
||||
target_coderate = cqi_table3[cqi_idx][1];
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0, "Invalid cqi table index %d\n", cqi_table);
|
||||
}
|
||||
const int max_mcs = mcs_table == 1 ? 27 : 28;
|
||||
for (int i = 0; i <= max_mcs; i++) {
|
||||
const int R = nr_get_code_rate_dl(i, mcs_table);
|
||||
const int Qm = nr_get_Qm_dl(i, mcs_table);
|
||||
if (Qm == target_qm && target_coderate <= R)
|
||||
return i;
|
||||
}
|
||||
|
||||
LOG_E(NR_MAC, "could not find maximum MCS from cqi_idx %d, default to 9\n", cqi_idx);
|
||||
return default_mcs;
|
||||
}
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type)
|
||||
{
|
||||
|
||||
@@ -5352,3 +5494,129 @@ int nr_get_prach_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_Conf
|
||||
|
||||
return mu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new NR_list
|
||||
*/
|
||||
void create_nr_list(NR_list_t *list, int len)
|
||||
{
|
||||
list->head = -1;
|
||||
list->next = malloc(len * sizeof(*list->next));
|
||||
AssertFatal(list->next, "cannot malloc() memory for NR_list_t->next\n");
|
||||
for (int i = 0; i < len; ++i)
|
||||
list->next[i] = -1;
|
||||
list->tail = -1;
|
||||
list->len = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize an NR_list
|
||||
*/
|
||||
void resize_nr_list(NR_list_t *list, int new_len)
|
||||
{
|
||||
if (new_len == list->len)
|
||||
return;
|
||||
if (new_len > list->len) {
|
||||
/* list->head remains */
|
||||
const int old_len = list->len;
|
||||
int* n = realloc(list->next, new_len * sizeof(*list->next));
|
||||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||||
list->next = n;
|
||||
for (int i = old_len; i < new_len; ++i)
|
||||
list->next[i] = -1;
|
||||
/* list->tail remains */
|
||||
list->len = new_len;
|
||||
} else { /* new_len < len */
|
||||
AssertFatal(list->head < new_len, "shortened list head out of index %d (new len %d)\n", list->head, new_len);
|
||||
AssertFatal(list->tail < new_len, "shortened list tail out of index %d (new len %d)\n", list->head, new_len);
|
||||
for (int i = 0; i < list->len; ++i)
|
||||
AssertFatal(list->next[i] < new_len, "shortened list entry out of index %d (new len %d)\n", list->next[i], new_len);
|
||||
/* list->head remains */
|
||||
int *n = realloc(list->next, new_len * sizeof(*list->next));
|
||||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||||
list->next = n;
|
||||
/* list->tail remains */
|
||||
list->len = new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an NR_list
|
||||
*/
|
||||
void destroy_nr_list(NR_list_t *list)
|
||||
{
|
||||
free(list->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ID to an NR_list at the end, traversing the whole list. Note:
|
||||
* add_tail_nr_list() is a faster alternative, but this implementation ensures
|
||||
* we do not add an existing ID.
|
||||
*/
|
||||
void add_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
int *cur = &listP->head;
|
||||
while (*cur >= 0) {
|
||||
AssertFatal(*cur != id, "id %d already in NR_UE_list!\n", id);
|
||||
cur = &listP->next[*cur];
|
||||
}
|
||||
*cur = id;
|
||||
if (listP->next[id] < 0)
|
||||
listP->tail = id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an ID from an NR_list
|
||||
*/
|
||||
void remove_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
int *cur = &listP->head;
|
||||
int *prev = &listP->head;
|
||||
while (*cur != -1 && *cur != id) {
|
||||
prev = cur;
|
||||
cur = &listP->next[*cur];
|
||||
}
|
||||
AssertFatal(*cur != -1, "ID %d not found in UE_list\n", id);
|
||||
int *next = &listP->next[*cur];
|
||||
*cur = listP->next[*cur];
|
||||
*next = -1;
|
||||
listP->tail = *prev >= 0 && listP->next[*prev] >= 0 ? listP->tail : *prev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ID to the tail of the NR_list in O(1). Note that there is
|
||||
* corresponding remove_tail_nr_list(), as we cannot set the tail backwards and
|
||||
* therefore need to go through the whole list (use remove_nr_list())
|
||||
*/
|
||||
void add_tail_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
int *last = listP->tail < 0 ? &listP->head : &listP->next[listP->tail];
|
||||
*last = id;
|
||||
listP->next[id] = -1;
|
||||
listP->tail = id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ID to the front of the NR_list in O(1)
|
||||
*/
|
||||
void add_front_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
const int ohead = listP->head;
|
||||
listP->head = id;
|
||||
listP->next[id] = ohead;
|
||||
if (listP->tail < 0)
|
||||
listP->tail = id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an ID from the front of the NR_list in O(1)
|
||||
*/
|
||||
void remove_front_nr_list(NR_list_t *listP)
|
||||
{
|
||||
AssertFatal(listP->head >= 0, "Nothing to remove\n");
|
||||
const int ohead = listP->head;
|
||||
listP->head = listP->next[ohead];
|
||||
listP->next[ohead] = -1;
|
||||
if (listP->head < 0)
|
||||
listP->tail = -1;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#define NB_SRS_PERIOD (18)
|
||||
static const uint16_t srs_period[NB_SRS_PERIOD] = { 0, 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560};
|
||||
static const uint8_t nr_rv_round_map[4] = {0, 2, 3, 1};
|
||||
|
||||
typedef enum {
|
||||
pusch_dmrs_pos0 = 0,
|
||||
@@ -47,6 +48,42 @@ typedef enum {
|
||||
pusch_dmrs_pos3 = 3,
|
||||
} pusch_dmrs_AdditionalPosition_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;
|
||||
} NR_mac_dir_stats_t;
|
||||
|
||||
typedef struct NR_UE_sl_mac_stats {
|
||||
NR_mac_dir_stats_t sl;
|
||||
uint32_t slsch_DTX;
|
||||
uint64_t slsch_total_bytes_scheduled;
|
||||
int cumul_rsrp;
|
||||
uint8_t num_rsrp_meas;
|
||||
uint32_t cumul_round[5];
|
||||
} NR_UE_sl_mac_stats_t;
|
||||
|
||||
typedef struct NR_bler_options {
|
||||
double upper;
|
||||
double lower;
|
||||
uint8_t max_mcs;
|
||||
uint8_t harq_round_max;
|
||||
} NR_bler_options_t;
|
||||
|
||||
typedef struct NR_bler_stats {
|
||||
frame_t last_frame;
|
||||
float bler;
|
||||
uint8_t mcs;
|
||||
uint64_t rounds[8];
|
||||
} NR_bler_stats_t;
|
||||
|
||||
typedef enum {
|
||||
pusch_len1 = 1,
|
||||
pusch_len2 = 2
|
||||
@@ -175,6 +212,14 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
|
||||
|
||||
int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrecoder);
|
||||
|
||||
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx, int default_mcs);
|
||||
|
||||
int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
const NR_mac_dir_stats_t *stats,
|
||||
NR_bler_stats_t *bler_stats,
|
||||
int max_mcs,
|
||||
frame_t frame);
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type);
|
||||
|
||||
int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t);
|
||||
@@ -198,6 +243,11 @@ uint32_t nr_compute_tbs(uint16_t Qm,
|
||||
uint8_t tb_scaling,
|
||||
uint8_t Nl);
|
||||
|
||||
uint32_t nr_compute_tbs_sl(uint16_t Qm,
|
||||
uint16_t R,
|
||||
uint16_t nb_re,
|
||||
uint8_t Nl);
|
||||
|
||||
/** \brief Computes Q based on I_MCS PDSCH and table_idx for downlink. Implements MCS Tables from 38.214. */
|
||||
uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx);
|
||||
uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx);
|
||||
@@ -330,4 +380,13 @@ int get_nrofHARQ_ProcessesForPUSCH(const NR_UE_ServingCell_Info_t *sc_info);
|
||||
|
||||
int nr_get_prach_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_ConfigCommon_t *rach_ConfigCommon);
|
||||
|
||||
/* Functions to manage an NR_list_t */
|
||||
void create_nr_list(NR_list_t *listP, int len);
|
||||
void resize_nr_list(NR_list_t *list, int new_len);
|
||||
void destroy_nr_list(NR_list_t *list);
|
||||
void add_nr_list(NR_list_t *listP, int id);
|
||||
void remove_nr_list(NR_list_t *listP, int id);
|
||||
void add_tail_nr_list(NR_list_t *listP, int id);
|
||||
void add_front_nr_list(NR_list_t *listP, int id);
|
||||
void remove_front_nr_list(NR_list_t *listP);
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@ void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
|
||||
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, nrofUplinkSlots %d, nrofMixed slots 1, nb_slots_per_period %d \n",
|
||||
nrofDownlinkSlots,nrofUplinkSlots,nb_slots_per_period);
|
||||
}
|
||||
|
||||
// EpiSci TODO: computing method is different max_tdd_periodicity_list
|
||||
tdd_table->max_tdd_periodicity_list = (fapi_nr_max_tdd_periodicity_t *) malloc(nb_slots_per_period * sizeof(fapi_nr_max_tdd_periodicity_t));
|
||||
|
||||
for(int memory_alloc = 0 ; memory_alloc < nb_slots_per_period; memory_alloc++)
|
||||
@@ -1673,7 +1673,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t
|
||||
switch (cause) {
|
||||
case GO_TO_IDLE:
|
||||
reset_ra(mac, true);
|
||||
nr_ue_init_mac(mac);
|
||||
nr_ue_init_mac(mac, NULL);
|
||||
release_mac_configuration(mac, cause);
|
||||
nr_ue_mac_default_configs(mac);
|
||||
// new sync but no target cell id -> -1
|
||||
|
||||
@@ -20,8 +20,50 @@
|
||||
*/
|
||||
|
||||
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
|
||||
#include "openair2/LAYER2/NR_MAC_UE/nr_ue_sci.h"
|
||||
#include "NR_SidelinkPreconfigNR-r16.h"
|
||||
#include "mac_proto.h"
|
||||
#include "common/config/config_paramdesc.h"
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
|
||||
#define SL_CONFIG_STRING_SL_PRECONFIGURATION "SIDELINK_PRECONFIGURATION"
|
||||
|
||||
/* Sidelink CSI-RS configuration parameters for MAC*/
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_LIST "sl_csi_rs"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_SYMB_L0 "symb_l0"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_CSI_TYPE "csi_Type"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_SLOT_OFFSET "slot_Offset"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_SLOT_PERIODICITY "slot_Periodicity"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET "sl_powerControlOffset"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET_SS "sl_powerControlOffsetSS"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_SL_CSI_ACQUISITION "sl_CSI_Acquisition"
|
||||
#define SL_CONFIG_STRING_SL_CSI_RS_SL_LATENCYBOUNDCSI_REPORT "sl_LatencyBoundCSI_Report"
|
||||
|
||||
#define SL_CONFIG_STRING_SL_ALLOWED_RESOURCE_SELECTION_CONFIG "sl_AllowedResourceSelectionConfig"
|
||||
|
||||
#define SL_CSI_RS_DESC(sl_csi_info) { \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_SYMB_L0,NULL,0,.u8ptr=&sl_csi_info->symb_l0,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_CSI_TYPE,NULL,0,.u8ptr=&sl_csi_info->csi_type,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET,NULL,0,.u8ptr=&sl_csi_info->power_control_offset,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_POWER_CONTROL_OFFSET_SS,NULL,0,.u8ptr=&sl_csi_info->power_control_offset_ss,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_SLOT_OFFSET,NULL,0,.u8ptr=&sl_csi_info->slot_offset,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_SLOT_PERIODICITY,NULL,0,.u8ptr=&sl_csi_info->slot_periodicity,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_SL_CSI_ACQUISITION,NULL,0,.u8ptr=&sl_csi_info->sl_csi_acquisition,.defuintval=1,TYPE_UINT8,0}, \
|
||||
{SL_CONFIG_STRING_SL_CSI_RS_SL_LATENCYBOUNDCSI_REPORT,NULL,0,.u8ptr=&sl_csi_info->sl_latencyboundcsi_report,.defuintval=8,TYPE_UINT8,0}}
|
||||
|
||||
#define SL_CONFIG_RESOURCE_SELECTION(resource_selection_cfg) { \
|
||||
{SL_CONFIG_STRING_SL_ALLOWED_RESOURCE_SELECTION_CONFIG, NULL, 0, .u16ptr=resource_selection_cfg, .defuintval=3, TYPE_UINT16, 0}}
|
||||
|
||||
typedef struct sl_csi_info {
|
||||
uint8_t symb_l0;
|
||||
uint8_t csi_type;
|
||||
uint8_t slot_offset;
|
||||
uint8_t slot_periodicity;
|
||||
uint8_t power_control_offset;
|
||||
uint8_t power_control_offset_ss;
|
||||
uint8_t sl_csi_acquisition;
|
||||
uint8_t sl_latencyboundcsi_report;
|
||||
} sl_csi_info_t;
|
||||
|
||||
void sl_ue_mac_free(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
@@ -60,37 +102,79 @@ void sl_ue_mac_free(NR_UE_MAC_INST_t *mac)
|
||||
free_and_zero(mac->SL_MAC_PARAMS);
|
||||
}
|
||||
|
||||
//Prepares the TDD config to be passed to PHY
|
||||
void sl_set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
|
||||
int mu,
|
||||
NR_TDD_UL_DL_Pattern_t *pattern)
|
||||
{
|
||||
const int nrofUplinkSlots = pattern->nrofUplinkSlots;
|
||||
const int nrofUplinkSymbols = pattern->nrofUplinkSymbols;
|
||||
const int nb_periods_per_frame = get_nb_periods_per_frame(pattern->dl_UL_TransmissionPeriodicity);
|
||||
const int nb_slots_per_period = ((1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) / nb_periods_per_frame;
|
||||
int slot_number = 0;
|
||||
int nb_periods_per_frame = get_nb_periods_per_frame(tdd_table->tdd_period_in_slots);
|
||||
int nb_slots_to_set = 2*(1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
|
||||
int nb_slots_per_period = ((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME)/nb_periods_per_frame;
|
||||
tdd_table->tdd_period_in_slots = nb_slots_per_period;
|
||||
|
||||
LOG_I(PHY,"UL slots:%d, symbols:%d, slots_per_period:%d\n",
|
||||
nrofUplinkSlots, nrofUplinkSymbols, nb_slots_per_period);
|
||||
|
||||
tdd_table->max_tdd_periodicity_list = (fapi_nr_max_tdd_periodicity_t *) malloc(nb_slots_per_period * sizeof(fapi_nr_max_tdd_periodicity_t));
|
||||
|
||||
for(int memory_alloc = 0 ; memory_alloc < nb_slots_per_period; memory_alloc++)
|
||||
tdd_table->max_tdd_periodicity_list[memory_alloc].max_num_of_symbol_per_slot_list =
|
||||
(fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT*sizeof(fapi_nr_max_num_of_symbol_per_slot_t));
|
||||
|
||||
int slot_number = (nb_slots_per_period - nrofUplinkSlots) - (nrofUplinkSymbols ? 1 : 0);
|
||||
if (nrofUplinkSymbols != 0) {
|
||||
for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 1;
|
||||
}
|
||||
slot_number++;
|
||||
if ((pattern->nrofDownlinkSlots == 0) && (pattern->nrofDownlinkSymbols == 0)) {
|
||||
pattern->nrofDownlinkSymbols = (nrofUplinkSymbols) ? 14 - nrofUplinkSymbols : 0;
|
||||
pattern->nrofDownlinkSlots = nb_slots_per_period - nrofUplinkSlots;
|
||||
if (pattern->nrofDownlinkSymbols) pattern->nrofDownlinkSlots -= 1;
|
||||
}
|
||||
while(slot_number < nb_slots_per_period) {
|
||||
for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config = 1;
|
||||
if((number_of_symbol + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
|
||||
slot_number++;
|
||||
int nrofDownlinkSlots = pattern->nrofDownlinkSlots, nrofDownlinkSymbols = pattern->nrofDownlinkSymbols;
|
||||
|
||||
LOG_D(NR_MAC,"Set Phy Sidelink TDD Config: scs:%d,dl:%d-%d, ul:%d-%d, nb_periods_per_frame:%d, nb_slots_per_period:%d\n", mu, nrofDownlinkSlots, nrofDownlinkSymbols, nrofUplinkSlots, nrofUplinkSymbols, nb_periods_per_frame, nb_slots_per_period);
|
||||
|
||||
if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 )
|
||||
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots),
|
||||
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, nrofUplinkSlots %d, nb_slots_per_period %d \n",
|
||||
nrofDownlinkSlots, nrofUplinkSlots, nb_slots_per_period);
|
||||
else {
|
||||
AssertFatal(nrofDownlinkSymbols + nrofUplinkSymbols <= 14, "illegal symbol configuration DL %d, UL %d\n", nrofDownlinkSymbols, nrofUplinkSymbols);
|
||||
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots + 1),
|
||||
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, nrofUplinkSlots %d, nrofMixed slots 1, nb_slots_per_period %d \n",
|
||||
nrofDownlinkSlots, nrofUplinkSlots, nb_slots_per_period);
|
||||
}
|
||||
|
||||
tdd_table->max_tdd_periodicity_list = (fapi_nr_max_tdd_periodicity_t *) malloc(nb_slots_to_set * sizeof(fapi_nr_max_tdd_periodicity_t));
|
||||
|
||||
for(int memory_alloc =0 ; memory_alloc < nb_slots_to_set; memory_alloc++)
|
||||
tdd_table->max_tdd_periodicity_list[memory_alloc].max_num_of_symbol_per_slot_list = (fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT*sizeof(
|
||||
fapi_nr_max_num_of_symbol_per_slot_t));
|
||||
|
||||
while(slot_number != nb_slots_to_set) {
|
||||
if(nrofDownlinkSlots != 0) {
|
||||
for (int number_of_symbol = 0; number_of_symbol < nrofDownlinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config= 0;
|
||||
|
||||
if((number_of_symbol+1)%NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
|
||||
slot_number++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nrofDownlinkSymbols != 0 || nrofUplinkSymbols != 0) {
|
||||
for(int number_of_symbol =0; number_of_symbol < nrofDownlinkSymbols; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 0;
|
||||
}
|
||||
|
||||
for(int number_of_symbol = nrofDownlinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT-nrofUplinkSymbols; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 2;
|
||||
}
|
||||
|
||||
for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT-nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 1;
|
||||
}
|
||||
|
||||
slot_number++;
|
||||
}
|
||||
|
||||
if(nrofUplinkSlots != 0) {
|
||||
for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config = 1;
|
||||
|
||||
if((number_of_symbol+1)%NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
|
||||
slot_number++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,18 +213,23 @@ static void sl_prepare_phy_config(int module_id,
|
||||
LOG_I(NR_MAC, "SIDELINK CONFIGs: AbsFreqSSB:%d, AbsFreqPointA:%d, SL band:%d\n",
|
||||
SSB_ARFCN,pointA_ARFCN, sl_band);
|
||||
|
||||
//FREQSHIFT_7P5KHZ is DISABLED
|
||||
phycfg->sl_carrier_config.sl_frequency_shift_7p5khz = 0;
|
||||
#define SL_VALUE_FREQSHIFT_7P5KHZ_DISABLED 0
|
||||
phycfg->sl_carrier_config.sl_frequency_shift_7p5khz = SL_VALUE_FREQSHIFT_7P5KHZ_DISABLED;
|
||||
phycfg->sl_carrier_config.sl_value_N = freqcfg->valueN_r16;
|
||||
phycfg->sl_carrier_config.sl_num_tx_ant = 1;
|
||||
phycfg->sl_carrier_config.sl_num_rx_ant = 1;
|
||||
|
||||
NR_SCS_SpecificCarrier_t *carriercfg =
|
||||
freqcfg->sl_SCS_SpecificCarrierList_r16.list.array[0];
|
||||
|
||||
AssertFatal(carriercfg, "SCS_SpecificCarrier cannot be NULL");
|
||||
|
||||
int bw_index = get_supported_band_index(carriercfg->subcarrierSpacing, FR1, carriercfg->carrierBandwidth);
|
||||
int bw_index = get_supported_band_index(carriercfg->subcarrierSpacing,
|
||||
FR1,
|
||||
carriercfg->carrierBandwidth);
|
||||
phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, bw_index);
|
||||
|
||||
// EpiSci TODO: from_nrarfcn(band, scs, etc) / 1000;
|
||||
phycfg->sl_carrier_config.sl_frequency =
|
||||
from_nrarfcn(sl_band,carriercfg->subcarrierSpacing,pointA_ARFCN); // freq in kHz
|
||||
|
||||
@@ -213,6 +302,12 @@ static void sl_prepare_phy_config(int module_id,
|
||||
phycfg->sl_sync_source.gnss_dfn_offset = sl_OffsetDFN;
|
||||
|
||||
// TDD Table Configuration
|
||||
if (sl_TDD_config->pattern1.ext1 == NULL)
|
||||
phycfg->tdd_table.tdd_period_in_slots = sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity;
|
||||
else {
|
||||
if (sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL)
|
||||
phycfg->tdd_table.tdd_period_in_slots += (1 + *sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530);
|
||||
}
|
||||
sl_set_tdd_config_nr_ue(&phycfg->tdd_table,
|
||||
phycfg->sl_bwp_config.sl_scs,
|
||||
&sl_TDD_config->pattern1);
|
||||
@@ -235,10 +330,12 @@ static void sl_prepare_phy_config(int module_id,
|
||||
str[phycfg->sl_sync_source.sync_source],
|
||||
phycfg->sl_sync_source.gnss_dfn_offset,
|
||||
phycfg->sl_sync_source.rx_slss_id);
|
||||
LOG_I(NR_MAC, "UE[%d] Carrier CFG Params: freq:%ld, bw:%d, gridsize:%d, valueN:%d\n",
|
||||
LOG_I(NR_MAC, "UE[%d] Carrier CFG Params: freq:%ld, bw:%d, gridsize:%d, rxant:%d, txant:%d, valueN:%d\n",
|
||||
module_id,phycfg->sl_carrier_config.sl_frequency,
|
||||
phycfg->sl_carrier_config.sl_bandwidth,
|
||||
phycfg->sl_carrier_config.sl_grid_size,
|
||||
phycfg->sl_carrier_config.sl_num_rx_ant,
|
||||
phycfg->sl_carrier_config.sl_num_tx_ant,
|
||||
phycfg->sl_carrier_config.sl_value_N);
|
||||
LOG_I(NR_MAC, "UE[%d] SL-BWP Params: start:%d, size:%d, scs:%d, Ncp:%d, startsym:%d, numsym:%d,ssb_offset:%d,dcloc:%d\n",
|
||||
module_id,phycfg->sl_bwp_config.sl_bwp_start,
|
||||
@@ -268,9 +365,6 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
AssertFatal(sl_preconfiguration !=NULL,"SL-Preconfig Cannot be NULL");
|
||||
AssertFatal(mac, "mac should have an instance");
|
||||
|
||||
if (!mac->SL_MAC_PARAMS)
|
||||
mac->SL_MAC_PARAMS = CALLOC(1, sizeof(sl_nr_ue_mac_params_t));
|
||||
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
|
||||
NR_SidelinkPreconfigNR_r16_t *sl_preconfig = &sl_preconfiguration->sidelinkPreconfigNR_r16;
|
||||
@@ -294,9 +388,6 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
sl_mac->sl_SSB_PriorityNR = (sl_preconfig->sl_SSB_PriorityNR_r16)
|
||||
? *sl_preconfig->sl_SSB_PriorityNR_r16 : 0;
|
||||
|
||||
//Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_mac->sl_CSI_Acquisition = (sl_preconfig->sl_CSI_Acquisition_r16) ? 0 : 1;
|
||||
|
||||
//Used for DFN calculation in case Sync source = GNSS.
|
||||
uint32_t sl_OffsetDFN = (sl_preconfig->sl_OffsetDFN_r16)
|
||||
? *sl_preconfig->sl_OffsetDFN_r16 : 0;
|
||||
@@ -305,6 +396,7 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
if (freqcfg->sl_BWP_List_r16 &&
|
||||
freqcfg->sl_BWP_List_r16->list.array[0])
|
||||
bwp = freqcfg->sl_BWP_List_r16->list.array[0];
|
||||
mac->sl_bwp = bwp;
|
||||
|
||||
AssertFatal(bwp!=NULL, "BWP config common cannot be NULL\n");
|
||||
if (bwp->sl_BWP_PoolConfigCommon_r16) {
|
||||
@@ -315,6 +407,7 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
if (rxpool) {
|
||||
if (sl_mac->sl_RxPool[i] == NULL)
|
||||
sl_mac->sl_RxPool[i] = malloc16_clear(sizeof(SL_ResourcePool_params_t));
|
||||
mac->sl_rx_res_pool = rxpool;
|
||||
sl_mac->sl_RxPool[i]->respool = rxpool;
|
||||
uint16_t sci_1a_len = 0, num_subch = 0;
|
||||
sci_1a_len = sl_determine_sci_1a_len(&num_subch,
|
||||
@@ -339,10 +432,28 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.array[0]->sl_ResourcePool_r16;
|
||||
|
||||
if (txpool) {
|
||||
mac->sl_tx_res_pool = txpool;
|
||||
if (sl_mac->sl_TxPool[i] == NULL)
|
||||
sl_mac->sl_TxPool[i] = malloc16_clear(sizeof(SL_ResourcePool_params_t));
|
||||
sl_mac->sl_TxPool[i]->respool = txpool;
|
||||
|
||||
uint8_t tproc1_valaues[] = {3, 5, 9, 17};
|
||||
uint8_t mu = get_softmodem_params()->numerology;
|
||||
struct NR_SL_UE_SelectedConfigRP_r16 *sl_ue_selected_config = sl_mac->sl_TxPool[i]->respool->sl_UE_SelectedConfigRP_r16;
|
||||
uint16_t sensing_window_ms = (uint16_t)*sl_ue_selected_config->sl_SensingWindow_r16;
|
||||
uint16_t selection_window = (uint16_t)sl_ue_selected_config->sl_SelectionWindowList_r16->list.array[0]->sl_SelectionWindow_r16;
|
||||
sl_mac->sl_TxPool[i]->t2min = selection_window;
|
||||
sl_mac->sl_TxPool[i]->t0 = time_to_slots(mu, sensing_window_ms);
|
||||
sl_mac->sl_TxPool[i]->tproc0 = 1;
|
||||
sl_mac->sl_TxPool[i]->tproc1 = tproc1_valaues[mu];
|
||||
sl_mac->sl_TxPool[i]->t1 = 1;
|
||||
sl_mac->sl_TxPool[i]->t2 = 60; // According to 38214 sec. 8.1.4: T2min <= t2 <= PDB, where T2min = {1,5,10,20}*2^μ, u = 1, PDB = 20ms = 40 slots
|
||||
sl_mac->mac_tx_params.rri = sl_ue_selected_config->sl_ResourceReservePeriodList_r16->list.array[0]->choice.sl_ResourceReservePeriod1_r16;
|
||||
sl_mac->mac_tx_params.resel_counter = get_random_reselection_counter(sl_mac->mac_tx_params.rri);
|
||||
mac->sl_thresh_rsrp = (-128 + (*sl_ue_selected_config->sl_Thres_RSRP_List_r16->list.array[0] - 1) * 2);
|
||||
LOG_D(NR_MAC, "sl_thresh_rsrp %d rri %i sl_ResourceReservePeriod1 %ld, i %d, sensing_window_ms %d, selection_window %d\n",
|
||||
mac->sl_thresh_rsrp, sl_mac->mac_tx_params.rri,
|
||||
sl_ue_selected_config->sl_ResourceReservePeriodList_r16->list.array[0]->choice.sl_ResourceReservePeriod1_r16,
|
||||
i, sensing_window_ms, selection_window);
|
||||
uint16_t sci_1a_len = 0, num_subch = 0;
|
||||
sci_1a_len = sl_determine_sci_1a_len(&num_subch,
|
||||
sl_mac->sl_TxPool[i]->respool,
|
||||
@@ -382,6 +493,66 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, sl_mac->sl_TDD_config);
|
||||
sl_mac->sl_TDD_config = NULL;
|
||||
}
|
||||
if (get_nrUE_params()->sync_ref) {
|
||||
int scs = get_softmodem_params()->numerology;
|
||||
const int nr_slots_frame = nr_slots_per_frame[scs];
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : nr_slots_frame;
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_tx_res_pool);
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
|
||||
int nr_slots_period = nr_slots_frame;
|
||||
int nr_ulstart_slot = 0;
|
||||
if (tdd) {
|
||||
nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0 && tdd->nrofUplinkSymbols == 0);
|
||||
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
}
|
||||
|
||||
for (int slot = 0; slot < nr_slots_frame; ++slot) {
|
||||
mac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
|
||||
LOG_D(NR_MAC,
|
||||
"slot %d UL %d\n",
|
||||
slot,
|
||||
(mac->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0);
|
||||
}
|
||||
|
||||
BIT_STRING_t *sl_tx_time_rsrc = mac->sl_tx_res_pool->ext1->sl_TimeResource_r16;
|
||||
int total_downlink_slots_in_bitmap = (((sl_tx_time_rsrc->size << 3) - sl_tx_time_rsrc->bits_unused) / n_ul_slots_period) * (nr_slots_period - n_ul_slots_period);
|
||||
int total_uplink_slots_in_bitmap = (((sl_tx_time_rsrc->size << 3) - sl_tx_time_rsrc->bits_unused) / n_ul_slots_period) * (n_ul_slots_period);
|
||||
AssertFatal(((sl_tx_time_rsrc->size << 3) - sl_tx_time_rsrc->bits_unused) == total_uplink_slots_in_bitmap, "The computation for total uplink slots is invalid. %ld != %d\n",
|
||||
((sl_tx_time_rsrc->size << 3) - sl_tx_time_rsrc->bits_unused), total_uplink_slots_in_bitmap);
|
||||
int phy_sl_size = ((sl_tx_time_rsrc->size << 3) - sl_tx_time_rsrc->bits_unused) + total_downlink_slots_in_bitmap;
|
||||
AssertFatal(total_downlink_slots_in_bitmap + total_uplink_slots_in_bitmap == phy_sl_size, "The total number of uplink and downlink slots must equal the total bitmap size!");
|
||||
LOG_D(NR_MAC, "size of phy_sl_map %d total_downlink_slots %d, sl_tx_time_rsrc.size %ld, n_ul_slots_period %d, (nr_slots_period - n_ul_slots_period) %d\n",
|
||||
phy_sl_size, total_downlink_slots_in_bitmap, ((sl_tx_time_rsrc->size << 3) - sl_tx_time_rsrc->bits_unused), n_ul_slots_period, (nr_slots_period - n_ul_slots_period));
|
||||
|
||||
uint8_t pool_id = 0;
|
||||
size_t byte_capacity = (phy_sl_size + 7) / 8;
|
||||
|
||||
SL_ResourcePool_params_t *sl_tx_rsrc_pool = sl_mac->sl_TxPool[pool_id];
|
||||
BIT_STRING_t *phy_sl_tx_bitmap = &sl_tx_rsrc_pool->phy_sl_bitmap;
|
||||
phy_sl_tx_bitmap->buf = (uint8_t*)malloc16_clear(byte_capacity);
|
||||
phy_sl_tx_bitmap->size = byte_capacity;
|
||||
phy_sl_tx_bitmap->bits_unused = ((phy_sl_tx_bitmap->size << 3) - phy_sl_size) % 8;
|
||||
uint16_t tx_phy_map_sz = get_physical_sl_pool(mac, sl_tx_time_rsrc, phy_sl_tx_bitmap);
|
||||
|
||||
|
||||
SL_ResourcePool_params_t *sl_rx_rsrc_pool = sl_mac->sl_RxPool[pool_id];
|
||||
BIT_STRING_t *phy_sl_rx_bitmap = &sl_rx_rsrc_pool->phy_sl_bitmap;
|
||||
phy_sl_rx_bitmap->buf = (uint8_t*)malloc16_clear(byte_capacity);
|
||||
phy_sl_rx_bitmap->size = byte_capacity;
|
||||
phy_sl_rx_bitmap->bits_unused = ((phy_sl_rx_bitmap->size << 3) - phy_sl_size) % 8;
|
||||
BIT_STRING_t *sl_rx_time_rsrc = mac->sl_rx_res_pool->ext1->sl_TimeResource_r16;
|
||||
uint16_t rx_phy_map_sz = get_physical_sl_pool(mac, sl_rx_time_rsrc, phy_sl_rx_bitmap);
|
||||
|
||||
AssertFatal(tx_phy_map_sz == rx_phy_map_sz, "Transmit %d and receive %d phy_map_sz is different.\n",
|
||||
tx_phy_map_sz, rx_phy_map_sz);
|
||||
mac->sl_res_percentage = 0.5;
|
||||
}
|
||||
// Configuring CSI-RS parameters locally at MAC.
|
||||
nr_sl_params_read_conf(module_id);
|
||||
|
||||
nr_sl_phy_config_t *sl_phy_cfg = &sl_mac->sl_phy_config;
|
||||
sl_phy_cfg->Mod_id = module_id;
|
||||
@@ -390,6 +561,7 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
sl_prepare_phy_config(module_id, &sl_phy_cfg->sl_config_req,
|
||||
freqcfg, sync_source, sl_OffsetDFN, sl_mac->sl_TDD_config);
|
||||
|
||||
sl_mac->mac_tx_params.packet_delay_budget_ms = 30;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -515,20 +687,148 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
if (ret == 0) {
|
||||
//sl_tdd_config bytes are all 1's - no TDD config present use all slots for sidelink.
|
||||
//Spec not clear -- TBD...
|
||||
sl_config->tdd_table.tdd_period_in_slots = 7;// set it to frame period
|
||||
sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots =
|
||||
NR_NUMBER_OF_SUBFRAMES_PER_FRAME*(1<<cfg->sl_bwp_config.sl_scs);
|
||||
} else {
|
||||
if (sl_mac->sl_TDD_config->pattern1.ext1 == NULL) {
|
||||
sl_config->tdd_table.tdd_period_in_slots = sl_mac->sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity;
|
||||
} else {
|
||||
if (sl_mac->sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL)
|
||||
sl_config->tdd_table.tdd_period_in_slots += (1 + *sl_mac->sl_TDD_config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530);
|
||||
}
|
||||
}
|
||||
|
||||
sl_set_tdd_config_nr_ue(&cfg->tdd_table,
|
||||
cfg->sl_bwp_config.sl_scs,
|
||||
&sl_mac->sl_TDD_config->pattern1);
|
||||
|
||||
AssertFatal(get_nrUE_params()->sync_ref == 0, "Expecting Nearby UE\n");
|
||||
int scs = get_softmodem_params()->numerology;
|
||||
const int nr_slots_frame = nr_slots_per_frame[scs];
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : nr_slots_frame;
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_tx_res_pool);
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
|
||||
LOG_I(MAC, "SIDELINK CONFIGs: tdd config period:%ld, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
|
||||
sl_mac->sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity,sl_mac->sl_TDD_config->referenceSubcarrierSpacing,
|
||||
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSlots, sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots,
|
||||
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSymbols,sl_mac->sl_TDD_config->pattern1.nrofUplinkSymbols);
|
||||
|
||||
int nr_slots_period = nr_slots_frame;
|
||||
int nr_ulstart_slot = 0;
|
||||
if (tdd) {
|
||||
nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0 && tdd->nrofUplinkSymbols == 0);
|
||||
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
}
|
||||
|
||||
for (int slot = 0; slot < nr_slots_frame; ++slot) {
|
||||
mac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
|
||||
LOG_D(NR_MAC,
|
||||
"slot %d UL %d\n",
|
||||
slot,
|
||||
(mac->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0);
|
||||
}
|
||||
|
||||
BIT_STRING_t *sl_time_rsrc = mac->sl_tx_res_pool->ext1->sl_TimeResource_r16;
|
||||
int total_downlink_slots = ((sl_time_rsrc->size << 3) - sl_time_rsrc->bits_unused) / n_ul_slots_period * (nr_slots_period - n_ul_slots_period);
|
||||
int phy_sl_size = ((sl_time_rsrc->size << 3) - sl_time_rsrc->bits_unused) + total_downlink_slots;
|
||||
LOG_D(NR_MAC, "size of phy_sl_map %d total_downlink_slots %d, sl_time_rsrc->size %ld, n_ul_slots_period %d, (nr_slots_period - n_ul_slots_period) %d\n", phy_sl_size, total_downlink_slots, ((sl_time_rsrc->size << 3) - sl_time_rsrc->bits_unused), n_ul_slots_period, (nr_slots_period - n_ul_slots_period));
|
||||
|
||||
size_t byte_capacity = (phy_sl_size + 7) / 8;
|
||||
uint8_t pool_id = 0;
|
||||
SL_ResourcePool_params_t *sl_tx_rsrc_pool = sl_mac->sl_TxPool[pool_id];
|
||||
SL_ResourcePool_params_t *sl_rx_rsrc_pool = sl_mac->sl_RxPool[pool_id];
|
||||
|
||||
sl_tx_rsrc_pool->phy_sl_bitmap.buf = (uint8_t*)malloc16_clear(byte_capacity);
|
||||
sl_rx_rsrc_pool->phy_sl_bitmap.buf = (uint8_t*)malloc16_clear(byte_capacity);
|
||||
sl_tx_rsrc_pool->phy_sl_bitmap.size = (phy_sl_size + 7) >> 3;
|
||||
sl_tx_rsrc_pool->phy_sl_bitmap.bits_unused = ((sl_tx_rsrc_pool->phy_sl_bitmap.size << 3) - phy_sl_size) % 8;
|
||||
|
||||
BIT_STRING_t *phy_sl_bitmap = &sl_tx_rsrc_pool->phy_sl_bitmap;
|
||||
uint16_t tx_phy_map_sz = get_physical_sl_pool(mac, sl_time_rsrc, phy_sl_bitmap);
|
||||
|
||||
sl_time_rsrc = mac->sl_rx_res_pool->ext1->sl_TimeResource_r16;
|
||||
phy_sl_bitmap = &sl_rx_rsrc_pool->phy_sl_bitmap;
|
||||
sl_rx_rsrc_pool->phy_sl_bitmap.size = (phy_sl_size + 7) >> 3;
|
||||
sl_rx_rsrc_pool->phy_sl_bitmap.bits_unused = ((sl_rx_rsrc_pool->phy_sl_bitmap.size << 3) - phy_sl_size) % 8;
|
||||
|
||||
uint16_t rx_phy_map_sz = get_physical_sl_pool(mac, sl_time_rsrc, phy_sl_bitmap);
|
||||
|
||||
AssertFatal(tx_phy_map_sz == rx_phy_map_sz, "Transmit and Receive physical sidelink bitmap does not have same length!!!");
|
||||
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
||||
mac->if_module->sl_phy_config_request(&sl_mac->sl_phy_config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nr_sl_params_read_conf(module_id_t module_id) {
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
|
||||
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
||||
sl_csi_info_t *sl_csi_rs_info = (sl_csi_info_t *)malloc16_clear(sizeof(sl_csi_info_t));
|
||||
paramdef_t SL_CRI_RS_INFO[] = SL_CSI_RS_DESC(sl_csi_rs_info);
|
||||
paramlist_def_t SL_CRI_RS_List = {SL_CONFIG_STRING_SL_CSI_RS_LIST, NULL, 0};
|
||||
sprintf(aprefix, "%s.[%d]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0);
|
||||
config_getlist(config_get_if(), &SL_CRI_RS_List, NULL, 0, aprefix);
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0, SL_CONFIG_STRING_SL_CSI_RS_LIST, 0);
|
||||
config_get(config_get_if(), SL_CRI_RS_INFO, sizeofArray(SL_CRI_RS_INFO), aprefix);
|
||||
|
||||
sl_mac->csi_type = sl_csi_rs_info->csi_type;
|
||||
sl_mac->symb_l0 = sl_csi_rs_info->symb_l0;
|
||||
sl_mac->power_control_offset = sl_csi_rs_info->power_control_offset;
|
||||
sl_mac->power_control_offset_ss = sl_csi_rs_info->power_control_offset_ss;
|
||||
sl_mac->measurement_bitmap = 0b00011011;
|
||||
sl_mac->sl_CSI_Acquisition = sl_csi_rs_info->sl_csi_acquisition;
|
||||
sl_mac->sl_LatencyBoundCSI_Report = sl_csi_rs_info->sl_latencyboundcsi_report;
|
||||
// Based on 38211 Table 7.4.1.5.3-1, for density of 1 and ports 1 & 2 ENUMERATED {noCDM, fd-CDM2}
|
||||
sl_mac->cdm_type = get_nrUE_params()->nb_antennas_tx == 1 ? 0 : 1;
|
||||
sl_mac->row = get_nrUE_params()->nb_antennas_tx == 1 ? 2 : 3;
|
||||
// Only 1 is supported (38211, 8.4.1.5.3) - means CSI-RS transmission in every resource block
|
||||
sl_mac->freq_density = 1;
|
||||
sl_mac->freq_domain = 0b000000000001; //bitmap size is dependent upon row size; for row 2 length is 12 bits else 6 bits;
|
||||
int loc_bw = mac->sl_bwp->sl_BWP_Generic_r16->sl_BWP_r16->locationAndBandwidth;
|
||||
uint16_t bwp_start = NRRIV2PRBOFFSET(loc_bw, MAX_BWP_SIZE);
|
||||
// PRB where this CSI resource starts in relation to common resource block #0 (CRB#0) on the common resource block grid.
|
||||
// Only multiples of 4 are allowed (0, 4, ...)
|
||||
// INTEGER (0..maxNrofPhysicalResourceBlocks-1)
|
||||
sl_mac->start_rb = (bwp_start % 4 == 0) ? bwp_start : ((bwp_start >> 2) << 2) + 4;
|
||||
// Number of PRBs across which this CSI resource spans. The smallest configurable number is the minimum of 24 and the width of the associated BWP
|
||||
// Only multiples of 4 are allowed.
|
||||
// INTEGER (24..maxNrofPhysicalResourceBlocksPlus1)
|
||||
uint16_t max_allowable_num_rbs = (NRRIV2BW(loc_bw, MAX_BWP_SIZE) >> 2) << 2;
|
||||
sl_mac->nr_of_rbs = min(24, max_allowable_num_rbs);
|
||||
|
||||
LOG_D(NR_MAC, "loc_bw %i, start_rb %i, nr_of_rbs %i, max_allowable_num_rbs %i\n", loc_bw, sl_mac->start_rb, sl_mac->nr_of_rbs, max_allowable_num_rbs);
|
||||
|
||||
char aprefix_rsc[MAX_OPTNAME_SIZE*2 + 8];
|
||||
sprintf(aprefix_rsc, "%s.[%d]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0);
|
||||
|
||||
uint16_t* resource_selection_cfg = (uint16_t *)malloc16_clear(sizeof(*resource_selection_cfg));
|
||||
paramdef_t SL_CONFIG_RSR_INFO[] = SL_CONFIG_RESOURCE_SELECTION(resource_selection_cfg);
|
||||
config_get(config_get_if(), SL_CONFIG_RSR_INFO, sizeofArray(SL_CONFIG_RSR_INFO), aprefix_rsc);
|
||||
|
||||
switch(*resource_selection_cfg) {
|
||||
case 0:
|
||||
mac->rsc_selection_method = c1;
|
||||
break;
|
||||
case 3:
|
||||
mac->rsc_selection_method = c4;
|
||||
break;
|
||||
case 4:
|
||||
mac->rsc_selection_method = c5;
|
||||
break;
|
||||
case 6:
|
||||
mac->rsc_selection_method = c7;
|
||||
break;
|
||||
default:
|
||||
LOG_D(NR_MAC, "Provided resource selection mechanism is not supported!!!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common/platform_types.h"
|
||||
#include "platform_types.h"
|
||||
|
||||
/* IF */
|
||||
#include "NR_IF_Module.h"
|
||||
@@ -62,7 +62,9 @@
|
||||
#include "NR_ServingCellConfig.h"
|
||||
#include "NR_MeasConfig.h"
|
||||
#include "NR_ServingCellConfigCommonSIB.h"
|
||||
|
||||
#include "NR_SL-BWP-ConfigCommon-r16.h"
|
||||
#include "linear_alloc.h"
|
||||
#include "nr_ue_sci.h"
|
||||
|
||||
// ==========
|
||||
// NR UE defs
|
||||
@@ -566,6 +568,225 @@ typedef struct ntn_timing_advance_components {
|
||||
bool ntn_params_changed;
|
||||
} ntn_timing_advance_componets_t;
|
||||
|
||||
typedef struct NR_sched_pssch {
|
||||
int frame;
|
||||
int slot;
|
||||
int mu;
|
||||
|
||||
/// 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 sl_harq_pid;
|
||||
|
||||
uint8_t nrOfLayers;
|
||||
//NR_pusch_dmrs_t dmrs_info;
|
||||
} NR_sched_pssch_t;
|
||||
|
||||
typedef struct {
|
||||
bool is_waiting;
|
||||
bool is_active;
|
||||
uint8_t ndi;
|
||||
uint8_t round;
|
||||
uint16_t feedback_slot;
|
||||
uint16_t feedback_frame;
|
||||
int8_t sl_harq_pid;
|
||||
|
||||
// Transport block to be sent using this HARQ process, its size is in sched_pssch
|
||||
uint32_t transportBlock[38016]; // valid up to 4 layers
|
||||
uint32_t tb_size;
|
||||
|
||||
/// sched_pusch keeps information on MCS etc used for the initial transmission
|
||||
NR_sched_pssch_t sched_pssch;
|
||||
} NR_UE_sl_harq_t;
|
||||
|
||||
typedef struct SL_CSI_Report {
|
||||
uint8_t ri;
|
||||
int8_t cqi;
|
||||
uint8_t cqi_table;
|
||||
uint32_t frame;
|
||||
uint32_t slot;
|
||||
bool active;
|
||||
uint8_t slot_offset;
|
||||
uint8_t slot_periodicity;
|
||||
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR slot_periodicity_offset;
|
||||
} SL_CSI_Report_t;
|
||||
//
|
||||
|
||||
typedef struct SL_sched_feedback {
|
||||
int16_t feedback_slot;
|
||||
int16_t feedback_frame;
|
||||
int16_t harq_feedback;
|
||||
uint8_t dai_c;
|
||||
bool active;
|
||||
uint8_t freq_hop_flag;
|
||||
uint8_t group_hop_flag;
|
||||
uint8_t sequence_hop_flag;
|
||||
uint16_t second_hop_prb;
|
||||
uint8_t nr_of_symbols;
|
||||
uint8_t start_symbol_index;
|
||||
uint8_t hopping_id;
|
||||
uint16_t prb;
|
||||
uint16_t sl_bwp_start;
|
||||
uint16_t initial_cyclic_shift;
|
||||
uint8_t mcs;
|
||||
uint8_t bit_len_harq;
|
||||
} SL_sched_feedback_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
// sidelink bytes that are currently scheduled
|
||||
int sched_sl_bytes;
|
||||
/// Sched PSSCH: scheduling decisions, copied into HARQ and cleared every TTI
|
||||
NR_sched_pssch_t sched_pssch;
|
||||
|
||||
// Used on PSFCH transmitter
|
||||
SL_sched_feedback_t *sched_psfch;
|
||||
|
||||
/// total amount of data awaiting for this UE
|
||||
uint32_t num_total_bytes;
|
||||
uint16_t sl_pdus_total;
|
||||
/// per-LC status data
|
||||
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID];
|
||||
//
|
||||
NR_bler_stats_t sl_bler_stats;
|
||||
|
||||
/// information about every UL HARQ process
|
||||
NR_UE_sl_harq_t sl_harq_processes[NR_MAX_HARQ_PROCESSES];
|
||||
/// UL HARQ processes that are free
|
||||
NR_list_t available_sl_harq;
|
||||
/// UL HARQ processes that await feedback
|
||||
NR_list_t feedback_sl_harq;
|
||||
/// UL HARQ processes that await retransmission
|
||||
NR_list_t retrans_sl_harq;
|
||||
// NR_SLSCH
|
||||
// Used on CSI report transmitter
|
||||
SL_CSI_Report_t sched_csi_report;
|
||||
// To hold the CSI report values received from different users
|
||||
nr_sl_csi_report_t rx_csi_report;
|
||||
bool print_csi_report;
|
||||
/// UE-estimated maximum MCS (from CSI-RS)
|
||||
uint8_t sl_max_mcs;
|
||||
|
||||
} NR_SL_UE_sched_ctrl_t;
|
||||
|
||||
#define MAX_SL_UE_CONNECTIONS 8
|
||||
#define CUR_SL_UE_CONNECTIONS 1
|
||||
|
||||
#define MAX_SL_CSI_REPORTCONFIG MAX_SL_UE_CONNECTIONS
|
||||
|
||||
typedef struct {
|
||||
uid_t uid; // unique ID of this UE
|
||||
/// scheduling control info
|
||||
nr_sl_csi_report_t csi_report_template[MAX_SL_CSI_REPORTCONFIG];
|
||||
NR_SL_UE_sched_ctrl_t UE_sched_ctrl;
|
||||
NR_UE_sl_mac_stats_t mac_sl_stats;
|
||||
} NR_SL_UE_info_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
NR_SL_UE_info_t *list[MAX_SL_UE_CONNECTIONS+1];
|
||||
uid_allocator_t ue_allocator;
|
||||
pthread_mutex_t mutex;
|
||||
} NR_SL_UEs_t;
|
||||
|
||||
typedef struct {
|
||||
int16_t frame;
|
||||
int16_t slot;
|
||||
} frameslot_t;
|
||||
|
||||
typedef struct {
|
||||
frameslot_t frame_slot;
|
||||
uint16_t rsvp; // The resource reservation period in ms
|
||||
uint8_t subch_len; // The total number of the sub-channel allocated
|
||||
uint8_t subch_start; // The index of the starting sub-channel allocated
|
||||
uint8_t prio; // The priority
|
||||
int16_t sl_rsrp; // The measured RSRP value over the used resource blocks
|
||||
uint8_t gap_re_tx1; // Gap for a first retransmission in absolute slots
|
||||
uint8_t subch_startre_tx1; // The index of the starting sub-channel allocated
|
||||
// to first retransmission
|
||||
uint8_t gap_re_tx2; // Gap for a second retransmission in absolute slots
|
||||
uint8_t subch_startre_tx2; // The index of the starting sub-channel allocated
|
||||
// to second retransmission
|
||||
} sensing_data_t;
|
||||
|
||||
typedef struct {
|
||||
void* data;
|
||||
size_t element_size;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} List_t;
|
||||
|
||||
typedef struct {
|
||||
List_t* lists;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} vec_of_list_t;
|
||||
|
||||
typedef enum {
|
||||
c1, c2, c3, c4, c5, c6, c7
|
||||
} allowed_rsc_selection_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t num_sl_pscch_rbs;
|
||||
uint16_t sl_pscch_sym_start;
|
||||
uint16_t sl_pscch_sym_len;
|
||||
uint16_t sl_pssch_sym_start;
|
||||
uint16_t sl_pssch_sym_len;
|
||||
uint16_t sl_subchan_size;
|
||||
uint16_t sl_max_num_per_reserve;
|
||||
uint8_t sl_psfch_period;
|
||||
uint8_t sl_min_time_gap_psfch;
|
||||
uint8_t sl_min_time_gap_processing;
|
||||
frameslot_t sfn;
|
||||
uint8_t sl_subchan_start;
|
||||
uint8_t sl_subchan_len;
|
||||
bool slot_busy;
|
||||
} sl_resource_info_t;
|
||||
|
||||
/**
|
||||
* \brief Structure to denote a future resource reserved by another UE
|
||||
*
|
||||
* This data structure represents resources excluded by step 6c) of the
|
||||
* TS 38.214 Sec. 8.1.4 sensing algorithm.
|
||||
*/
|
||||
typedef struct {
|
||||
frameslot_t sfn; // The SfnSf
|
||||
uint16_t rsvp; // The resource reservation period in ms
|
||||
uint8_t sb_ch_length; // The total number of the sub-channel allocated
|
||||
uint8_t sb_ch_start; // The index of the starting sub-channel allocated
|
||||
uint8_t prio; // The priority
|
||||
double sl_rsrp; // The measured RSRP value over the used resource blocks
|
||||
} reserved_resource_t;
|
||||
|
||||
typedef struct {
|
||||
// PSCCH
|
||||
uint16_t num_sl_pscch_rbs; // Indicates the number of PRBs for PSCCH in a resource pool where it is not
|
||||
// greater than the number PRBs of the subchannel.
|
||||
uint16_t sl_pscch_sym_start; // Indicates the starting symbol used for sidelink PSCCH in a slot
|
||||
uint16_t sl_pscch_sym_len; // Indicates the total number of symbols available for sidelink PSCCH
|
||||
// PSSCH
|
||||
uint16_t sl_pssch_sym_start; // Indicates the starting symbol used for sidelink PSSCH in a slot
|
||||
uint16_t sl_pssch_sym_len; // Indicates the total number of symbols available for sidelink PSSCH
|
||||
bool sl_has_psfch; // Indicates whether PSFCH is present in the slot
|
||||
// subchannel size in RBs
|
||||
uint16_t sl_sub_chan_size; // Indicates the subchannel size in number of RBs
|
||||
uint16_t sl_max_num_per_reserve; // The maximum number of reserved PSCCH/PSSCH resources
|
||||
// that can be indicated by an SCI.
|
||||
uint64_t abs_slot_index; // Indicates the the absolute slot index
|
||||
uint32_t slot_offset; // Indicates the positive offset between two slots
|
||||
} slot_info_t;
|
||||
|
||||
/*!\brief Top level UE MAC structure */
|
||||
typedef struct NR_UE_MAC_INST_s {
|
||||
module_id_t ue_id;
|
||||
@@ -599,8 +820,22 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
|
||||
NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
|
||||
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon;
|
||||
// sidelink
|
||||
NR_SL_BWP_ConfigCommon_r16_t *sl_bwp;
|
||||
int max_fb_time;
|
||||
NR_SL_ResourcePool_r16_t *sl_rx_res_pool;
|
||||
NR_SL_ResourcePool_r16_t *sl_tx_res_pool;
|
||||
|
||||
bool phy_config_request_sent;
|
||||
frame_type_t frame_type;
|
||||
|
||||
/// Type0-PDCCH seach space
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t type0_pdcch_dci_config;
|
||||
uint32_t type0_pdcch_ss_mux_pattern;
|
||||
int type0_pdcch_ss_sfn_c;
|
||||
uint32_t type0_pdcch_ss_n_c;
|
||||
uint32_t type0_pdcch_consecutive_slots;
|
||||
|
||||
/* Random Access */
|
||||
/// CRNTI
|
||||
uint16_t crnti;
|
||||
@@ -667,6 +902,38 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
sl_nr_ue_mac_params_t *SL_MAC_PARAMS;
|
||||
// PUCCH closed loop power control state
|
||||
int G_b_f_c;
|
||||
|
||||
// SIDELINK Scheduling fields
|
||||
NR_SL_UEs_t sl_info;
|
||||
|
||||
// current SCI pdu build from SCI1 and SCI2
|
||||
nr_sci_pdu_t sci_pdu_rx;
|
||||
nr_sci_pdu_t sci1_pdu;
|
||||
nr_sci_pdu_t sci2_pdu;
|
||||
uint8_t slsch_payload[16384];
|
||||
time_stats_t rlc_data_req;
|
||||
int src_id;
|
||||
pthread_mutex_t sl_sched_lock;
|
||||
|
||||
allowed_rsc_selection_t rsc_selection_method; // Flag to enable NR Sidelink resource selection based on
|
||||
// sensing; otherwise, use random selection
|
||||
double m_slProbResourceKeep; // Sidelink probability of keeping a resource after resource
|
||||
// re-selection counter reaches zero
|
||||
List_t sl_sensing_data; // List to store sensing data
|
||||
int sl_thresh_rsrp; // A threshold in dBm used for sensing based UE autonomous resource selection
|
||||
float sl_res_percentage; /* The percentage threshold to indicate the
|
||||
minimum number of candidate single-slot
|
||||
resources to be selected using sensing procedure.
|
||||
*/
|
||||
uint8_t sl_resel_counter; // The resource selection counter
|
||||
uint16_t sl_c_resel; // The C_resel counter
|
||||
List_t sl_transmit_history; // History of slots used for transmission
|
||||
|
||||
/// bitmap of ULSCH slots, can hold up to 160 slots
|
||||
uint64_t ulsch_slot_bitmap[3];
|
||||
List_t *sl_candidate_resources;
|
||||
uint16_t reselection_timer;
|
||||
|
||||
bool pucch_power_control_initialized;
|
||||
int f_b_f_c;
|
||||
bool pusch_power_control_initialized;
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
#include "NR_TDD-UL-DL-ConfigCommon.h"
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_common.h"
|
||||
|
||||
#define HARQ_ROUND_MAX 4
|
||||
#define SL_NR_MAC_NUM_RX_RESOURCE_POOLS 1
|
||||
#define SL_NR_MAC_NUM_TX_RESOURCE_POOLS 1
|
||||
#define SL_NUM_BYTES_TIMERESOURCEBITMAP 20
|
||||
@@ -44,6 +46,24 @@
|
||||
|
||||
#define sci_field_t dci_field_t
|
||||
|
||||
#define NR_UE_SL_SCHED_LOCK(lock) \
|
||||
do { \
|
||||
int rc = pthread_mutex_lock(lock); \
|
||||
AssertFatal(rc == 0, "error while locking scheduler mutex\n"); \
|
||||
} while (0)
|
||||
|
||||
#define NR_UE_SL_SCHED_UNLOCK(lock) \
|
||||
do { \
|
||||
int rc = pthread_mutex_unlock(lock); \
|
||||
AssertFatal(rc == 0, "error while locking scheduler mutex\n"); \
|
||||
} while (0)
|
||||
|
||||
#define NR_UE_SL_SCHED_ENSURE_LOCKED(lock)\
|
||||
do {\
|
||||
int rc = pthread_mutex_trylock(lock); \
|
||||
AssertFatal(rc == EBUSY, "this function should be called with the scheduler mutex locked\n");\
|
||||
} while (0)
|
||||
|
||||
typedef struct sidelink_sci_format_1a_fields {
|
||||
|
||||
// Priority of this transmission
|
||||
@@ -105,6 +125,14 @@ typedef struct SL_ResourcePool_params {
|
||||
//SCI-1A configuration according to RESPOOL configured.
|
||||
sidelink_sci_format_1a_fields_t sci_1a;
|
||||
|
||||
BIT_STRING_t phy_sl_bitmap;
|
||||
uint8_t tproc0; // T_proc0 in slots
|
||||
uint8_t tproc1; // T_proc1 in slots
|
||||
uint16_t t0; // T0 - Sensing window
|
||||
uint8_t t1; // T1 - The offset in number of slots between the slot in which the resource
|
||||
// selection is triggered and the start of the selection window
|
||||
uint16_t t2; // T2 - The configured value of T2 (end of selection window)
|
||||
uint8_t t2min; // t2min
|
||||
} SL_ResourcePool_params_t;
|
||||
|
||||
typedef struct sl_ssb_timealloc {
|
||||
@@ -131,6 +159,18 @@ typedef struct sl_bch_params {
|
||||
|
||||
} sl_bch_params_t;
|
||||
|
||||
/**
|
||||
* \brief Structure to pass parameters to trigger the selection of candidate
|
||||
* resources as per TR 38.214 Section 8.1.4
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t priority; // L1 priority prio_TX
|
||||
uint16_t packet_delay_budget_ms; // remaining packet delay budget
|
||||
uint16_t l_subch; // L_subCH; number of subchannels to be used
|
||||
uint16_t rri; // resource reservation interval
|
||||
uint16_t resel_counter; // C_resel counter
|
||||
} nr_sl_transmission_params_t;
|
||||
|
||||
typedef struct sl_stored_tti_req {
|
||||
uint32_t sl_action;
|
||||
int frame;
|
||||
@@ -148,6 +188,24 @@ typedef struct sl_nr_ue_mac_params {
|
||||
//Holds either the TDD config from RRC
|
||||
//or TDD config decoded from SL-MIB
|
||||
NR_TDD_UL_DL_ConfigCommon_t *sl_TDD_config;
|
||||
nr_sl_transmission_params_t mac_tx_params;
|
||||
|
||||
// CSI params configured locally
|
||||
uint8_t symb_l0;
|
||||
uint8_t csi_type;
|
||||
uint8_t power_control_offset;
|
||||
uint8_t power_control_offset_ss;
|
||||
uint8_t freq_density;
|
||||
uint8_t subcarrier_spacing;
|
||||
uint8_t cyclic_prefix;
|
||||
uint16_t start_rb;
|
||||
uint16_t nr_of_rbs;
|
||||
uint8_t row;
|
||||
uint16_t freq_domain;
|
||||
uint8_t cdm_type;
|
||||
uint16_t scramb_id;
|
||||
uint8_t measurement_bitmap;
|
||||
uint8_t sl_LatencyBoundCSI_Report;
|
||||
|
||||
//Configured from RRC
|
||||
uint32_t sl_MaxNumConsecutiveDTX;
|
||||
@@ -182,6 +240,8 @@ typedef struct sl_nr_ue_mac_params {
|
||||
uint16_t N_SSB_16frames;
|
||||
|
||||
sl_stored_tti_req_t *future_ttis;
|
||||
NR_bler_options_t sl_bler;
|
||||
bool is_synced;
|
||||
|
||||
} sl_nr_ue_mac_params_t;
|
||||
|
||||
|
||||
@@ -36,14 +36,85 @@
|
||||
#include "mac_defs.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "RRC/NR_UE/rrc_defs.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */
|
||||
#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */
|
||||
static const int pscch_rb_table[5] = {10,12,15,20,25};
|
||||
static const int pscch_tda[2] = {2,3};
|
||||
|
||||
// 38.213 Table 16.3-1 set of cyclic shift pairs
|
||||
static const int16_t table_16_3_1[4][6] = {
|
||||
{0},
|
||||
{0, 3},
|
||||
{0, 2, 4},
|
||||
{0, 1, 2, 3, 4, 5}
|
||||
};
|
||||
|
||||
typedef struct prbs_set {
|
||||
uint16_t **start_prb;
|
||||
uint16_t **end_prb;
|
||||
} prbs_set_t;
|
||||
|
||||
typedef struct psfch_params {
|
||||
uint16_t m0;
|
||||
prbs_set_t *prbs_sets;
|
||||
} psfch_params_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
NR_BSR_SHORT s;
|
||||
NR_BSR_LONG l;
|
||||
uint8_t lcg_bsr[8];
|
||||
} bsr;
|
||||
enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr;
|
||||
} type_bsr_t;
|
||||
|
||||
#define MAX_LCID 8 // NR_MAX_NUM_LCID shall be used but the mac_rlc_data_req function can fetch data for max 8 LCID
|
||||
typedef struct {
|
||||
uint8_t phr_len;
|
||||
uint sdu_length_total;
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE phr;
|
||||
|
||||
uint8_t bsr_len;
|
||||
uint8_t bsr_ce_len;
|
||||
uint8_t bsr_header_len;
|
||||
uint8_t phr_ce_len;
|
||||
uint8_t phr_header_len;
|
||||
//TODO: Add following inside type_bsr_t
|
||||
NR_SL_BSR_SHORT *sl_bsr_s;
|
||||
type_bsr_t bsr;
|
||||
// int tot_mac_ce_len;
|
||||
// uint8_t total_mac_pdu_header_len;
|
||||
uint8_t *pdu_end;
|
||||
uint8_t *end_for_tailer;
|
||||
uint8_t *cur_ptr;
|
||||
uint num_sdus;
|
||||
// variable used to store the lcid data status during lcp
|
||||
bool lcids_data_status[NR_MAX_NUM_LCID];
|
||||
uint32_t lcp_allocation_counter;
|
||||
} NR_UE_MAC_CE_INFO;
|
||||
|
||||
void nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes);
|
||||
|
||||
void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid, bool sr_DelayTimerApplied);
|
||||
|
||||
void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
uint8_t gNB_index,
|
||||
uint8_t *ulsch_buffer,
|
||||
uint32_t buflen,
|
||||
uint32_t *LCG_bytes,
|
||||
NR_UE_MAC_CE_INFO *mac_ce_p,
|
||||
int tx_power,
|
||||
int P_CMAX);
|
||||
|
||||
/**\brief initialize the field in nr_mac instance
|
||||
\param mac MAC pointer */
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac);
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac, ueinfo_t *ueinfo);
|
||||
|
||||
void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
|
||||
void update_mac_timers(NR_UE_MAC_INST_t *mac);
|
||||
@@ -93,16 +164,17 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r1
|
||||
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause);
|
||||
|
||||
/**\brief initialization NR UE MAC instance(s)*/
|
||||
NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst);
|
||||
NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst, ueinfo_t *ueinfo);
|
||||
|
||||
/**\brief fetch MAC instance by module_id
|
||||
\param module_id index of MAC instance(s)*/
|
||||
/**\brief fetch MAC instance by module_id, within 0 - (NB_NR_UE_MAC_INST-1)
|
||||
\param module_id index of MAC instance\(s)*/
|
||||
NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id);
|
||||
|
||||
void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac);
|
||||
void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach);
|
||||
void release_mac_configuration(NR_UE_MAC_INST_t *mac,
|
||||
NR_UE_MAC_reset_cause_t cause);
|
||||
size_t dump_mac_stats_sl(NR_UE_MAC_INST_t *mac, char *output, size_t strlen, bool reset_rsrp);
|
||||
|
||||
/**\brief called at each slot, slot length based on numerology. now use u=0, scs=15kHz, slot=1ms
|
||||
performs BSR/SR/PHR procedures, random access procedure handler and DLSCH/ULSCH procedures.
|
||||
@@ -125,6 +197,32 @@ int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_csirs_measurements_t *csirs_measurements);
|
||||
// EpiSci TODO: Following function is not available in Develop branch but we are using it for Sidelinkl
|
||||
// needs to find the alternative implementation
|
||||
/**\brief fill nr_scheduled_response struct instance
|
||||
@param nr_scheduled_response_t * pointer to scheduled_response instance to fill
|
||||
@param fapi_nr_dl_config_request_t* pointer to dl_config,
|
||||
@param fapi_nr_ul_config_request_t* pointer to ul_config,
|
||||
@param fapi_nr_tx_request_t* pointer to tx_request;
|
||||
@param sl_nr_rx_config_request_t* pointer to sl_rx_config,
|
||||
@param sl_nr_tx_config_request_t* pointer to sl_tx_config,
|
||||
@param module_id_t mod_id module ID
|
||||
@param int cc_id CC ID
|
||||
@param frame_t frame frame number
|
||||
@param int slot reference number
|
||||
@param void *phy_pata pointer to a PHY specific structure to be filled in the scheduler response (can be null) */
|
||||
void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
|
||||
fapi_nr_dl_config_request_t *dl_config,
|
||||
fapi_nr_ul_config_request_t *ul_config,
|
||||
fapi_nr_tx_request_t *tx_request,
|
||||
sl_nr_rx_config_request_t *sl_rx_config,
|
||||
sl_nr_tx_config_request_t *sl_tx_config,
|
||||
module_id_t mod_id,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
void *phy_data);
|
||||
|
||||
void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot);
|
||||
|
||||
bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac,
|
||||
@@ -168,15 +266,6 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in
|
||||
|
||||
void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac,nr_downlink_indication_t *dl_info, int pdu_id);
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
NR_BSR_SHORT s;
|
||||
NR_BSR_LONG l;
|
||||
uint8_t lcg_bsr[8];
|
||||
} bsr;
|
||||
enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr;
|
||||
} type_bsr_t;
|
||||
|
||||
int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end);
|
||||
|
||||
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
@@ -457,4 +546,299 @@ void nr_mac_rrc_sl_mib_ind(const module_id_t module_id,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id);
|
||||
|
||||
#endif
|
||||
uint8_t count_on_bits(uint8_t* buf, size_t size);
|
||||
|
||||
void nr_sl_params_read_conf(module_id_t module_id);
|
||||
|
||||
void nr_ue_process_mac_sl_pdu(int module_idP,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
int pdu_id);
|
||||
|
||||
NR_SL_UE_info_t* find_UE(NR_UE_MAC_INST_t *mac,
|
||||
uint16_t ue_id);
|
||||
|
||||
int get_csi_reporting_frame_slot(NR_UE_MAC_INST_t *mac,
|
||||
NR_TDD_UL_DL_Pattern_t *tdd,
|
||||
uint8_t csi_offset,
|
||||
const int nr_slots_frame,
|
||||
uint32_t frame,
|
||||
uint32_t slot,
|
||||
uint32_t *csi_report_frame,
|
||||
uint32_t *csi_report_slot);
|
||||
|
||||
uint16_t sl_get_subchannel_size(NR_SL_ResourcePool_r16_t *rpool);
|
||||
|
||||
int nr_ue_process_sci1_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,frame_t frame, int slot, sl_nr_sci_indication_pdu_t *sci,void *phy_data);
|
||||
|
||||
void nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_t *sci_pdu,
|
||||
nr_sci_pdu_t *sci2_pdu,
|
||||
nr_sci_format_t format2,
|
||||
NR_SL_UE_info_t *UE,
|
||||
uint16_t *slsch_pdu_length,
|
||||
NR_UE_sl_harq_t *cur_harq,
|
||||
mac_rlc_status_resp_t *rlc_status,
|
||||
sl_resource_info_t *resource);
|
||||
|
||||
SL_CSI_Report_t* set_nr_ue_sl_csi_meas_periodicity(const NR_TDD_UL_DL_Pattern_t *tdd,
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
int uid,
|
||||
bool is_rsrp);
|
||||
|
||||
void nr_ue_sl_csi_period_offset(SL_CSI_Report_t *sl_csi_report,
|
||||
int *period,
|
||||
int *offset);
|
||||
|
||||
uint8_t nr_ue_sl_psbch_scheduler(nr_sidelink_indication_t *sl_ind,
|
||||
sl_nr_ue_mac_params_t *sl_mac_params,
|
||||
sl_nr_rx_config_request_t *rx_config,
|
||||
sl_nr_tx_config_request_t *tx_config,
|
||||
uint8_t *config_type);
|
||||
|
||||
bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
nr_sidelink_indication_t *sl_ind,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_nr_tx_config_request_t *tx_config,
|
||||
sl_resource_info_t *resource,
|
||||
uint8_t *config_type);
|
||||
|
||||
void nr_ue_sl_pscch_rx_scheduler(nr_sidelink_indication_t *sl_ind,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_nr_rx_config_request_t *rx_config,
|
||||
uint8_t *config_type,
|
||||
bool sl_has_psfch);
|
||||
|
||||
void nr_ue_sl_csi_rs_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
uint8_t scs,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
sl_nr_tx_config_request_t *tx_config,
|
||||
sl_nr_rx_config_request_t *rx_config,
|
||||
uint8_t *config_type);
|
||||
|
||||
void nr_ue_sl_csi_report_scheduling(int Mod_idP,
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl,
|
||||
frame_t frame,
|
||||
sub_frame_t slot);
|
||||
|
||||
void fill_csi_rs_pdu(sl_nr_ue_mac_params_t *sl_mac,
|
||||
sl_nr_tti_csi_rs_pdu_t *csi_rs_pdu,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
uint8_t scs);
|
||||
|
||||
void nr_ue_sl_psfch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
uint16_t slot,
|
||||
long psfch_period,
|
||||
nr_sidelink_indication_t *sl_ind,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
sl_nr_tx_config_request_t *tx_config,
|
||||
uint8_t *config_type);
|
||||
|
||||
void config_pscch_pdu_rx(sl_nr_rx_config_pscch_pdu_t *nr_sl_pscch_pdu,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
bool sl_has_psfch);
|
||||
|
||||
int config_pssch_sci_pdu_rx(sl_nr_rx_config_pssch_sci_pdu_t *nr_sl_pssch_sci_pdu,
|
||||
nr_sci_format_t sci2_format,
|
||||
nr_sci_pdu_t *sci_pdu,
|
||||
uint32_t pscch_Nid,
|
||||
int pscch_subchannel_index,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
bool sl_has_psfch);
|
||||
|
||||
sl_resource_info_t* get_resource_element(List_t* resource_list, frameslot_t sfn);
|
||||
|
||||
int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac,
|
||||
module_id_t mod_id,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
sl_nr_sci_indication_pdu_t *sci,
|
||||
void *phy_data);
|
||||
|
||||
void extract_pssch_sci_pdu(uint64_t *sci2_payload,
|
||||
int len,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
nr_sci_pdu_t *sci_pdu);
|
||||
|
||||
void fill_pssch_pscch_pdu(sl_nr_ue_mac_params_t *sl_mac_params,
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *nr_sl_pssch_pscch_pdu,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
nr_sci_pdu_t *sci_pdu,
|
||||
nr_sci_pdu_t *sci2_pdu,
|
||||
uint16_t slsch_pdu_length,
|
||||
const nr_sci_format_t format1,
|
||||
const nr_sci_format_t format2,
|
||||
uint16_t slot,
|
||||
sl_resource_info_t *selected_resource);
|
||||
|
||||
void fill_psfch_pdu(SL_sched_feedback_t *mac_psfch_pdu,
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *tx_psfch_pdu,
|
||||
int num_psfch_symbols);
|
||||
|
||||
void update_harq_lists(NR_UE_MAC_INST_t *mac, frame_t frame, sub_frame_t slot, NR_SL_UE_info_t* UE);
|
||||
|
||||
int find_current_slot_harqs(frame_t frame, sub_frame_t slot, NR_SL_UE_sched_ctrl_t * sched_ctrl, NR_UE_sl_harq_t **matched_harqs);
|
||||
|
||||
uint8_t sl_num_slsch_feedbacks(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
bool is_feedback_scheduled(NR_UE_MAC_INST_t *mac, int frameP,int slotP);
|
||||
|
||||
uint16_t sl_get_num_subch(NR_SL_ResourcePool_r16_t *rpool);
|
||||
|
||||
void fill_psfch_params_tx(NR_UE_MAC_INST_t *mac, sl_nr_rx_indication_t *rx_ind, long psfch_period, uint16_t sched_frame, uint16_t sched_slot, uint8_t ack_nack, psfch_params_t *psfch_params, const int nr_slots_frame, int psfch_index);
|
||||
|
||||
void fill_psfch_params_rx(sl_nr_rx_config_request_t *rx_config, sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu, psfch_params_t *psfch_params, NR_UE_sl_harq_t *cur_harq, NR_UE_MAC_INST_t *mac, long psfch_period, const uint16_t slot);
|
||||
|
||||
void configure_psfch_params_rx(int module_idP, NR_UE_MAC_INST_t *mac, sl_nr_rx_config_request_t *rx_config);
|
||||
|
||||
void reset_sched_psfch(NR_UE_MAC_INST_t *mac, int frameP,int slotP);
|
||||
|
||||
int nr_ue_sl_acknack_scheduling(NR_UE_MAC_INST_t *mac, sl_nr_rx_indication_t *rx_ind,
|
||||
long psfch_period, uint16_t frame, uint16_t slot, const int nr_slots_frame);
|
||||
|
||||
int get_feedback_frame_slot(NR_UE_MAC_INST_t *mac, NR_TDD_UL_DL_Pattern_t *tdd,
|
||||
uint8_t feedback_offset, uint8_t psfch_min_time_gap,
|
||||
const int nr_slots_frame, uint16_t frame, uint16_t slot,
|
||||
long psfch_period, int *psfch_frame, int *psfch_slot);
|
||||
|
||||
int16_t get_feedback_slot(long psfch_period, uint16_t slot);
|
||||
|
||||
int get_pssch_to_harq_feedback(uint8_t *pssch_to_harq_feedback,
|
||||
uint8_t psfch_min_time_gap,
|
||||
NR_TDD_UL_DL_Pattern_t *tdd,
|
||||
const int nr_slots_frame);
|
||||
|
||||
int get_psfch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_psfch_max_size);
|
||||
|
||||
void init_list(List_t* list, size_t element_size, size_t initial_capacity);
|
||||
|
||||
void push_back(List_t* list, void* element);
|
||||
|
||||
void update_sensing_data(List_t* sensing_data, frameslot_t *frame_slot, sl_nr_ue_mac_params_t *sl_mac, uint16_t pool_id);
|
||||
|
||||
void update_transmit_history(List_t* transmit_history, frameslot_t *frame_slot, sl_nr_ue_mac_params_t *sl_mac, uint16_t pool_id);
|
||||
|
||||
void pop_back(List_t* sensing_data);
|
||||
|
||||
void free_list_mem(List_t* list);
|
||||
|
||||
int64_t normalize(frameslot_t *frame_slot, uint8_t mu);
|
||||
|
||||
void de_normalize(int64_t abs_slot_idx, uint8_t mu, frameslot_t *frame_slot);
|
||||
|
||||
frameslot_t add_to_sfn(frameslot_t* sfn, uint16_t slot_n, uint8_t mu);
|
||||
|
||||
uint16_t get_T2_min(uint16_t pool_id, sl_nr_ue_mac_params_t *sl_mac, uint8_t mu);
|
||||
|
||||
uint16_t get_t2(uint16_t pool_id,
|
||||
uint8_t mu,
|
||||
nr_sl_transmission_params_t* sl_tx_params,
|
||||
sl_nr_ue_mac_params_t *sl_mac);
|
||||
|
||||
uint16_t time_to_slots(uint8_t mu, uint16_t time);
|
||||
|
||||
uint8_t get_tproc0(sl_nr_ue_mac_params_t *sl_mac, uint16_t pool_id);
|
||||
|
||||
void remove_old_sensing_data(frameslot_t *frame_slot,
|
||||
uint16_t sensing_window,
|
||||
List_t* sensing_data,
|
||||
sl_nr_ue_mac_params_t *sl_mac);
|
||||
|
||||
void remove_old_transmit_history(frameslot_t *frame_slot,
|
||||
uint16_t sensing_window,
|
||||
List_t* transmit_history,
|
||||
sl_nr_ue_mac_params_t *sl_mac);
|
||||
|
||||
List_t* get_candidate_resources(frameslot_t *frame_slot,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
List_t *sensing_data,
|
||||
List_t *transmission_history);
|
||||
|
||||
List_t get_nr_sl_comm_opportunities(NR_UE_MAC_INST_t *mac,
|
||||
uint64_t abs_idx_cur_slot,
|
||||
uint8_t bwp_id,
|
||||
uint16_t mu,
|
||||
uint16_t pool_id,
|
||||
uint8_t t1,
|
||||
uint16_t t2,
|
||||
uint8_t psfch_period);
|
||||
|
||||
void validate_selected_sl_slot(bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *conf, frameslot_t frame_slot);
|
||||
|
||||
bool check_t1_within_tproc1(uint8_t mu, uint16_t t1_slots);
|
||||
|
||||
NR_SL_ResourcePool_r16_t* get_resource_pool(NR_UE_MAC_INST_t *mac, uint16_t pool_id);
|
||||
|
||||
bool slot_has_psfch(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint64_t abs_index_cur_slot, uint8_t psfch_period, size_t phy_sl_map_size, NR_TDD_UL_DL_ConfigCommon_t *conf);
|
||||
|
||||
void append_bit(uint8_t *buf, size_t bit_pos, int bit_value);
|
||||
|
||||
int get_bit_from_map(const uint8_t *buf, size_t bit_pos);
|
||||
|
||||
void init_vector(vec_of_list_t* vec, size_t initial_capacity);
|
||||
|
||||
void add_list(vec_of_list_t* vec, size_t element_size, size_t initial_list_capacity);
|
||||
|
||||
List_t* get_list(vec_of_list_t *vec, size_t index);
|
||||
|
||||
void* get_front(const List_t* list);
|
||||
|
||||
void* get_back(const List_t* list);
|
||||
|
||||
void delete_at(List_t* list, size_t index);
|
||||
|
||||
void free_vector(vec_of_list_t* vec);
|
||||
|
||||
int get_physical_sl_pool(NR_UE_MAC_INST_t *mac, BIT_STRING_t *sl_time_rsrc, BIT_STRING_t *phy_sl_bitmap);
|
||||
|
||||
void push_back_list(vec_of_list_t* vec, List_t* new_list);
|
||||
|
||||
List_t* get_candidate_resources_from_slots(frameslot_t *sfn,
|
||||
uint8_t psfch_period,
|
||||
uint8_t min_time_gap_psfch,
|
||||
uint16_t l_subch,
|
||||
uint16_t total_subch,
|
||||
List_t* slot_info,
|
||||
uint8_t mu);
|
||||
|
||||
List_t exclude_reserved_resources(sensing_data_t *sensed_data,
|
||||
float slot_period_ms,
|
||||
uint16_t resv_period_slots,
|
||||
uint16_t t1,
|
||||
uint16_t t2,
|
||||
uint8_t mu);
|
||||
|
||||
void exclude_resources_based_on_history(frameslot_t frame_slot,
|
||||
List_t* transmit_history,
|
||||
List_t* candidate_resources,
|
||||
List_t* sl_rsrc_rsrv_period_list,
|
||||
uint8_t mu);
|
||||
|
||||
bool overlapped_resource(uint8_t first_start,
|
||||
uint8_t first_length,
|
||||
uint8_t second_start,
|
||||
uint8_t second_length);
|
||||
|
||||
uint8_t get_random_reselection_counter(uint16_t rri);
|
||||
|
||||
uint32_t compute_TRIV(uint8_t N, uint8_t t1, uint8_t t2);
|
||||
|
||||
uint32_t compute_FRIV(uint8_t sl_max_num_per_reserve,
|
||||
uint8_t L_sub_chan,
|
||||
uint8_t n_start_subch1,
|
||||
uint8_t n_start_subch2,
|
||||
uint8_t N_sl_subch);
|
||||
|
||||
void print_candidate_list(List_t *candidate_resources, int line);
|
||||
|
||||
void print_reserved_list(List_t *candidate_resources, int line);
|
||||
|
||||
void print_sensing_data_list(List_t *sensing_data, int line);
|
||||
#endif
|
||||
@@ -52,7 +52,7 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p);
|
||||
}
|
||||
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac, ueinfo_t *ueinfo)
|
||||
{
|
||||
LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id);
|
||||
nr_ue_reset_sync_state(mac);
|
||||
@@ -86,6 +86,38 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
|
||||
mac->pucch_power_control_initialized = false;
|
||||
mac->pusch_power_control_initialized = false;
|
||||
|
||||
mac->SL_MAC_PARAMS = calloc(1, sizeof(sl_nr_ue_mac_params_t));
|
||||
mac->SL_MAC_PARAMS->sl_bler.harq_round_max = HARQ_ROUND_MAX;
|
||||
init_list(&mac->sl_sensing_data, sizeof(sensing_data_t), 1);
|
||||
init_list(&mac->sl_transmit_history, sizeof(frameslot_t), 1);
|
||||
mac->sl_candidate_resources = (List_t*)malloc16_clear(sizeof(List_t*));
|
||||
init_list(mac->sl_candidate_resources, sizeof(sl_resource_info_t), 1);
|
||||
mac->reselection_timer = 0;
|
||||
|
||||
if (ueinfo != NULL) {
|
||||
mac->src_id = ueinfo->srcid;
|
||||
LOG_D(NR_MAC, "srcid %d\n", ueinfo->srcid);
|
||||
}
|
||||
|
||||
AssertFatal((get_nrUE_params()->mcs >= 0 && get_nrUE_params()->mcs <= 28), "MCS must be 1 to 28!!!");
|
||||
int k = 0;
|
||||
for (int i = 0; i < CUR_SL_UE_CONNECTIONS + 1; i++) {
|
||||
if (mac->src_id == i)
|
||||
continue;
|
||||
mac->sl_info.list[k] = calloc(1, sizeof(NR_SL_UE_info_t));
|
||||
mac->sl_info.list[k]->uid = i;
|
||||
NR_SL_UE_sched_ctrl_t *UE_sched_ctrl = &mac->sl_info.list[k]->UE_sched_ctrl;
|
||||
UE_sched_ctrl->rx_csi_report.RI = 0;
|
||||
UE_sched_ctrl->rx_csi_report.CQI = 0;
|
||||
UE_sched_ctrl->sl_max_mcs = get_nrUE_params()->mcs;
|
||||
create_nr_list(&UE_sched_ctrl->available_sl_harq, 16);
|
||||
for (int harq = 0; harq < 16; harq++)
|
||||
add_tail_nr_list(&UE_sched_ctrl->available_sl_harq, harq);
|
||||
create_nr_list(&UE_sched_ctrl->feedback_sl_harq, 16);
|
||||
create_nr_list(&UE_sched_ctrl->retrans_sl_harq, 16);
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
|
||||
@@ -127,8 +159,7 @@ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id)
|
||||
return mac->state;
|
||||
}
|
||||
|
||||
NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst)
|
||||
{
|
||||
NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst, ueinfo_t *ueinfo) {
|
||||
//init mac here
|
||||
nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(nb_inst, sizeof(NR_UE_MAC_INST_t));
|
||||
AssertFatal(nr_ue_mac_inst, "Couldn't allocate %d instances of MAC module\n", nb_inst);
|
||||
@@ -136,7 +167,7 @@ NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst)
|
||||
for (int j = 0; j < nb_inst; j++) {
|
||||
NR_UE_MAC_INST_t *mac = &nr_ue_mac_inst[j];
|
||||
mac->ue_id = j;
|
||||
nr_ue_init_mac(mac);
|
||||
nr_ue_init_mac(mac, ueinfo);
|
||||
nr_ue_mac_default_configs(mac);
|
||||
if (IS_SA_MODE(get_softmodem_params()))
|
||||
ue_init_config_request(mac, get_softmodem_params()->numerology);
|
||||
@@ -160,6 +191,87 @@ NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id)
|
||||
return mac;
|
||||
}
|
||||
|
||||
size_t dump_mac_stats_sl(NR_UE_MAC_INST_t *mac, char *output, size_t strlen, bool reset_rsrp)
|
||||
{
|
||||
const char *begin = output;
|
||||
const char *end = output + strlen;
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
|
||||
/* this function is called from gNB_dlsch_ulsch_scheduler(), so assumes the
|
||||
* scheduler to be locked*/
|
||||
// NR_UE_SL_SCHED_ENSURE_LOCKED(&mac->sl_sched_lock);
|
||||
|
||||
NR_UE_SL_SCHED_LOCK(&mac->sl_info.mutex);
|
||||
SL_UE_iterator(mac->sl_info.list, UE) {
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_sl_mac_stats_t *stats = &UE->mac_sl_stats;
|
||||
|
||||
if(sched_ctrl->print_csi_report) {
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: CQI %d, RI %d\n",
|
||||
UE->uid,
|
||||
sched_ctrl->rx_csi_report.CQI,
|
||||
sched_ctrl->rx_csi_report.RI + 1);
|
||||
sched_ctrl->print_csi_report = false;
|
||||
}
|
||||
|
||||
output += snprintf(output, end - output, "%"PRIu64, stats->sl.rounds[0]);
|
||||
for (int i = 1; i < sl_mac->sl_bler.harq_round_max; i++)
|
||||
output += snprintf(output, end - output, "/%"PRIu64, stats->sl.rounds[i]);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
", slsch_errors %"PRIu64", BLER %.5f MCS %d\n",
|
||||
stats->sl.errors,
|
||||
sched_ctrl->sl_bler_stats.bler,
|
||||
sched_ctrl->sl_bler_stats.mcs);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: slsch_total_bytes %"PRIu64"\n",
|
||||
UE->uid, stats->sl.total_bytes);
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: slsch_rounds ", UE->uid);
|
||||
output += snprintf(output, end - output, "%"PRIu64, stats->sl.rounds[0]);
|
||||
for (int i = 1; i < sl_mac->sl_bler.harq_round_max; i++)
|
||||
output += snprintf(output, end - output, "/%"PRIu64, stats->sl.rounds[i]);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
", slsch_DTX %d, slsch_errors %"PRIu64", BLER %.5f MCS %d\n",
|
||||
stats->slsch_DTX,
|
||||
stats->sl.errors,
|
||||
sched_ctrl->sl_bler_stats.bler,
|
||||
sched_ctrl->sl_bler_stats.mcs);
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: slsch_total_bytes_scheduled %"PRIu64", slsch_total_bytes_received %"PRIu64"\n",
|
||||
UE->uid,
|
||||
stats->slsch_total_bytes_scheduled, stats->sl.total_bytes);
|
||||
|
||||
for (int lc_id = 0; lc_id < 63; lc_id++) {
|
||||
if (stats->sl.lc_bytes[lc_id] > 0)
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: LCID %d: %"PRIu64" bytes TX\n",
|
||||
UE->uid,
|
||||
lc_id,
|
||||
stats->sl.lc_bytes[lc_id]);
|
||||
if (stats->sl.lc_bytes[lc_id] > 0)
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: LCID %d: %"PRIu64" bytes RX\n",
|
||||
UE->uid,
|
||||
lc_id,
|
||||
stats->sl.lc_bytes[lc_id]);
|
||||
}
|
||||
}
|
||||
NR_UE_SL_SCHED_UNLOCK(&mac->sl_info.mutex);
|
||||
return output - begin;
|
||||
}
|
||||
|
||||
void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
{
|
||||
// MAC reset according to 38.321 Section 5.12
|
||||
|
||||
369
openair2/LAYER2/NR_MAC_UE/nr_slsch_scheduler.c
Normal file
369
openair2/LAYER2/NR_MAC_UE/nr_slsch_scheduler.c
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* \file nr_slsch_scheduler.c
|
||||
* \brief Routines for UE SLSCH scheduling
|
||||
* \author R. Knopp
|
||||
* \date Aug. 2023
|
||||
* \version 0.1
|
||||
* \company EURECOM
|
||||
* \email raymond.knopp@eurecom.fr
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/utils/nr/nr_common.h>
|
||||
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "mac_proto.h"
|
||||
#include "mac_extern.h"
|
||||
#include "nr_ue_sci.h"
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
#include "mac_defs_sl.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
|
||||
#define LOWER_BLER 0.2344
|
||||
#define UPPER_BLER 5.547
|
||||
#define MAX_MCS 28
|
||||
|
||||
void reset_sl_harq_list(NR_SL_UE_sched_ctrl_t *sched_ctrl) {
|
||||
int harq;
|
||||
while ((harq = sched_ctrl->feedback_sl_harq.head) >= 0) {
|
||||
remove_front_nr_list(&sched_ctrl->feedback_sl_harq);
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq);
|
||||
}
|
||||
|
||||
while ((harq = sched_ctrl->retrans_sl_harq.head) >= 0) {
|
||||
remove_front_nr_list(&sched_ctrl->retrans_sl_harq);
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NR_MAX_HARQ_PROCESSES; i++) {
|
||||
sched_ctrl->sl_harq_processes[i].feedback_slot = -1;
|
||||
sched_ctrl->sl_harq_processes[i].round = 0;
|
||||
sched_ctrl->sl_harq_processes[i].is_waiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t compute_TRIV(uint8_t N, uint8_t t1, uint8_t t2) {
|
||||
int32_t triv = 0;
|
||||
if (N == 1) {
|
||||
triv = 0;
|
||||
} else if (N == 2) {
|
||||
triv = t1;
|
||||
} else {
|
||||
if ((t2 - t1 - 1) <= 15) {
|
||||
triv = 30 * (t2 - t1 - 1) + t1 + 31;
|
||||
} else {
|
||||
triv = 30 * (31 - t2 + t1) + 62 - t1;
|
||||
}
|
||||
}
|
||||
return triv;
|
||||
}
|
||||
|
||||
uint32_t compute_FRIV(uint8_t sl_max_num_per_reserve,
|
||||
uint8_t L_sub_chan,
|
||||
uint8_t n_start_subch1,
|
||||
uint8_t n_start_subch2,
|
||||
uint8_t N_sl_subch) {
|
||||
uint32_t friv = 0;
|
||||
int sum = 0;
|
||||
if (sl_max_num_per_reserve == NR_SL_UE_SelectedConfigRP_r16__sl_MaxNumPerReserve_r16_n2) {
|
||||
for (int i = 1; i < L_sub_chan; i++) {
|
||||
sum += N_sl_subch + 1 - i;
|
||||
}
|
||||
friv = n_start_subch1 + sum;
|
||||
} else if (sl_max_num_per_reserve == NR_SL_UE_SelectedConfigRP_r16__sl_MaxNumPerReserve_r16_n3) {
|
||||
for (int i = 1; i < L_sub_chan; i++) {
|
||||
sum += (N_sl_subch + 1 - i) * (N_sl_subch + 1 - i);
|
||||
}
|
||||
friv = n_start_subch1 + n_start_subch2 * (N_sl_subch + 1 - L_sub_chan) + sum;
|
||||
} else {
|
||||
AssertFatal(1 == 0, "sl_MaxNumPerReserve is configured with incorrect value");
|
||||
}
|
||||
|
||||
return friv;
|
||||
}
|
||||
|
||||
void nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_t *sci_pdu,
|
||||
nr_sci_pdu_t *sci2_pdu, nr_sci_format_t format2,
|
||||
NR_SL_UE_info_t *UE,
|
||||
uint16_t *slsch_pdu_length_max, NR_UE_sl_harq_t *cur_harq,
|
||||
mac_rlc_status_resp_t *rlc_status,
|
||||
sl_resource_info_t *resource) {
|
||||
uid_t dest_id = UE->uid;
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
const NR_mac_dir_stats_t *stats = &UE->mac_sl_stats.sl;
|
||||
NR_sched_pssch_t *sched_pssch = &sched_ctrl->sched_pssch;
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
uint8_t mu = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
uint8_t slots_per_frame = nr_slots_per_frame[mu];
|
||||
|
||||
uint8_t psfch_period = 0;
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
psfch_period = (mac->sl_tx_res_pool->sl_PSFCH_Config_r16 &&
|
||||
mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16)
|
||||
? psfch_periods[*mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16] : 0;
|
||||
*slsch_pdu_length_max = 0;
|
||||
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
int period = 0, offset = 0;
|
||||
bool csi_acq = !mac->SL_MAC_PARAMS->sl_CSI_Acquisition;
|
||||
SL_CSI_Report_t *sl_csi_report = set_nr_ue_sl_csi_meas_periodicity(tdd, sched_ctrl, mac, dest_id, false);
|
||||
nr_ue_sl_csi_period_offset(sl_csi_report,
|
||||
&period,
|
||||
&offset);
|
||||
// Determine current slot is csi-rs schedule slot
|
||||
bool csi_req_slot = !((slots_per_frame * frameP + slotP - offset) % period);
|
||||
|
||||
uint8_t ri = 0;
|
||||
uint8_t cqi_Table = 0;
|
||||
uint8_t cqi = sched_ctrl->rx_csi_report.CQI;
|
||||
sched_pssch->mcs = sched_ctrl->sl_max_mcs;
|
||||
|
||||
int mcs_tb_ind = 0;
|
||||
// we are using as a flag to indicate if csi report was received
|
||||
if (cqi) {
|
||||
if (sci_pdu->additional_mcs.nbits > 0)
|
||||
mcs_tb_ind = sci_pdu->additional_mcs.val;
|
||||
if (mcs_tb_ind == 0)
|
||||
cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1;
|
||||
else if (mcs_tb_ind == 1)
|
||||
cqi_Table = NR_CSI_ReportConfig__cqi_Table_table2;
|
||||
else if (mcs_tb_ind == 2)
|
||||
cqi_Table = NR_CSI_ReportConfig__cqi_Table_table3;
|
||||
|
||||
sched_pssch->mcs = get_mcs_from_cqi(mcs_tb_ind, cqi_Table, cqi, get_nrUE_params()->mcs);
|
||||
sched_ctrl->sl_max_mcs = sched_pssch->mcs;
|
||||
ri = sched_ctrl->rx_csi_report.RI;
|
||||
}
|
||||
|
||||
/* Calculate coeff */
|
||||
NR_bler_options_t *sl_bo = &sl_mac->sl_bler;
|
||||
sl_bo->lower = LOWER_BLER;
|
||||
sl_bo->upper = UPPER_BLER;
|
||||
sl_bo->max_mcs = MAX_MCS;
|
||||
|
||||
const int max_mcs_table = mcs_tb_ind == 1 ? 27 : 28;
|
||||
int max_mcs = min(sched_ctrl->sl_max_mcs, max_mcs_table);
|
||||
if (sl_bo->harq_round_max == 1)
|
||||
sched_pssch->mcs = max_mcs;
|
||||
else {
|
||||
sched_pssch->mcs = get_mcs_from_bler(sl_bo, stats, &sched_ctrl->sl_bler_stats, max_mcs, frameP);
|
||||
}
|
||||
|
||||
uint16_t sl_max_num_reserve = *mac->sl_tx_res_pool->sl_UE_SelectedConfigRP_r16->sl_MaxNumPerReserve_r16;
|
||||
/*
|
||||
Following values are based on spec. 38214 section 8.1.5, N = 1 or 2 actual resources when sl-
|
||||
MaxNumPerReserve is 2, and N = 1 or 2 or 3 actual resources when sl-MaxNumPerReserve is 3.
|
||||
For N = 2, 1 <= t1 <= 31; and for N = 3, 1 <= t1 <= 30, t1 < t2 <= 31, We are taking N = 1; it represents only 1 reserved resource.
|
||||
*/
|
||||
int N = 1;
|
||||
uint8_t t1 = 0, t2 = 0;
|
||||
|
||||
long sl_num_subch = *mac->sl_tx_res_pool->sl_NumSubchannel_r16;
|
||||
uint8_t l_subch = resource->sl_subchan_len; // number of used sub channels; as in current setting, we have only 1 subchannel so l_subch is set to 1
|
||||
uint8_t n_start_subch1 = 0, n_start_subch2 = 0; // represent starting sub-channel index for the second resource and third resource;
|
||||
// as we are considering only 1 subchannel, so we have initialized these variables with zeros.
|
||||
// Fill SCI1A
|
||||
sci_pdu->priority = 0;
|
||||
sci_pdu->frequency_resource_assignment.val = compute_FRIV(sl_max_num_reserve, l_subch, n_start_subch1, n_start_subch2, sl_num_subch);
|
||||
sci_pdu->time_resource_assignment.val = compute_TRIV(N, t1, t2);
|
||||
sci_pdu->resource_reservation_period.val = mac->SL_MAC_PARAMS->mac_tx_params.rri;
|
||||
sci_pdu->dmrs_pattern.val = 0;
|
||||
sci_pdu->second_stage_sci_format = 0;
|
||||
sci_pdu->number_of_dmrs_port = ri;
|
||||
// we are using as a flag to indicate if csi report was received
|
||||
sci_pdu->mcs = sched_pssch->mcs;
|
||||
sci_pdu->additional_mcs.val = 0;
|
||||
if (frameP % 5 == 0)
|
||||
LOG_D(NR_MAC, "cqi ---> %d Tx %4d.%2d dest: %d mcs %i\n",
|
||||
cqi, frameP, slotP, dest_id, sci_pdu->mcs);
|
||||
/*Following code will check whether SLSCH was received before and
|
||||
its feedback has scheduled for current slot
|
||||
*/
|
||||
int scs = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
const int nr_slots_frame = nr_slots_per_frame[scs];
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : nr_slots_frame;
|
||||
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_tx_res_pool);
|
||||
bool is_feedback_slot = false;
|
||||
for (int i = 0; i < (n_ul_slots_period * num_subch); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
if (slotP == sched_psfch->feedback_slot) {
|
||||
LOG_D(NR_MAC, "%4d.%2d i = %d sched_psfch %p feedback slot %d\n", frameP, slotP, i, sched_psfch, sched_psfch->feedback_slot);
|
||||
is_feedback_slot = true;
|
||||
frameslot_t frame_slot;
|
||||
frame_slot.frame = frameP;
|
||||
frame_slot.slot = slotP;
|
||||
validate_selected_sl_slot(true, false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frameslot_t fs;
|
||||
fs.frame = frameP;
|
||||
fs.slot = slotP;
|
||||
uint8_t pool_id = 0;
|
||||
uint64_t tx_abs_slot = normalize(&fs, mu);
|
||||
SL_ResourcePool_params_t *sl_tx_rsrc_pool = sl_mac->sl_TxPool[pool_id];
|
||||
size_t phy_map_sz = ((sl_tx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_tx_rsrc_pool->phy_sl_bitmap.bits_unused);
|
||||
bool sl_has_psfch = slot_has_psfch(mac, &sl_tx_rsrc_pool->phy_sl_bitmap, tx_abs_slot, psfch_period, phy_map_sz, mac->SL_MAC_PARAMS->sl_TDD_config);
|
||||
if ((psfch_period == 2 || psfch_period == 4) && (sl_has_psfch)) {
|
||||
if (is_feedback_slot) {
|
||||
sci_pdu->psfch_overhead.val = 1;
|
||||
LOG_D(NR_MAC, "%4d.%2d Setting psfch_overhead 1\n", frameP, slotP);
|
||||
} else {
|
||||
sci_pdu->psfch_overhead.val = 0;
|
||||
LOG_D(NR_MAC, "%4d.%2d Setting psfch_overhead 0\n", frameP, slotP);
|
||||
}
|
||||
} else if ((psfch_period == 2 || psfch_period == 4) && (!sl_has_psfch)) {
|
||||
sci_pdu->psfch_overhead.val = 0;
|
||||
}
|
||||
|
||||
sci_pdu->reserved.val = sl_mac->is_synced ? 1 : 0;
|
||||
sci_pdu->conflict_information_receiver.val = 0;
|
||||
sci_pdu->beta_offset_indicator = 0;
|
||||
sci2_pdu->harq_pid = cur_harq->sl_harq_pid;
|
||||
sci2_pdu->ndi = cur_harq->ndi;
|
||||
sci2_pdu->rv_index = nr_rv_round_map[cur_harq->round % 4];
|
||||
sci2_pdu->source_id = mac->src_id;
|
||||
sci2_pdu->dest_id = dest_id;
|
||||
sci2_pdu->harq_feedback = cur_harq->is_waiting;
|
||||
LOG_D(NR_MAC, "%4d.%2d Comparing Setting harq_feedback %d bytes_in_buffer %d sl_harq_pid %d\n", frameP, slotP, sci2_pdu->harq_feedback, rlc_status->bytes_in_buffer, cur_harq ? cur_harq->sl_harq_pid : 0);
|
||||
sci2_pdu->cast_type = 1;
|
||||
if (format2 == NR_SL_SCI_FORMAT_2C || format2 == NR_SL_SCI_FORMAT_2A) {
|
||||
sci2_pdu->csi_req = (csi_acq && csi_req_slot) ? 1 : 0;
|
||||
sci2_pdu->csi_req = (cur_harq->round > 0 || is_feedback_slot) ? 0 : sci2_pdu->csi_req;
|
||||
LOG_D(NR_MAC, "%4d.%2d Setting sci2_pdu->csi_req %d\n", frameP, slotP, sci2_pdu->csi_req);
|
||||
}
|
||||
if (format2 == NR_SL_SCI_FORMAT_2B)
|
||||
sci2_pdu->zone_id = 0;
|
||||
// Fill in for R17: communication_range
|
||||
sci2_pdu->communication_range.val = 0;
|
||||
if (format2 == NR_SL_SCI_FORMAT_2C) {
|
||||
sci2_pdu->providing_req_ind = 0;
|
||||
// Fill in for R17 : resource combinations
|
||||
sci2_pdu->resource_combinations.val = 0;
|
||||
sci2_pdu->first_resource_location = 0;
|
||||
// Fill in for R17 : reference_slot_location
|
||||
sci2_pdu->reference_slot_location.val = 0;
|
||||
sci2_pdu->resource_set_type = 0;
|
||||
// Fill in for R17 : lowest_subchannel_indices
|
||||
sci2_pdu->lowest_subchannel_indices.val = 0;
|
||||
}
|
||||
// Set SLSCH
|
||||
*slsch_pdu_length_max = rlc_status->bytes_in_buffer;
|
||||
}
|
||||
|
||||
SL_CSI_Report_t* set_nr_ue_sl_csi_meas_periodicity(const NR_TDD_UL_DL_Pattern_t *tdd,
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
int uid,
|
||||
bool is_rsrp) {
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
sl_nr_phy_config_request_t *sl_cfg = &sl_mac->sl_phy_config.sl_config_req;
|
||||
uint8_t mu = sl_cfg->sl_bwp_config.sl_scs;
|
||||
uint8_t n_slots_frame = nr_slots_per_frame[mu];
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame;
|
||||
const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int ideal_period = (CUR_SL_UE_CONNECTIONS * nr_slots_period) / n_ul_slots_period;
|
||||
const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0 && tdd->nrofUplinkSymbols == 0) : 0;
|
||||
const int idx = (uid << 1) + is_rsrp;
|
||||
SL_CSI_Report_t *csi_report = &sched_ctrl->sched_csi_report;
|
||||
const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * nr_slots_period;
|
||||
AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n");
|
||||
csi_report->slot_offset = offset;
|
||||
if (ideal_period < 5) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots4;
|
||||
} else if (ideal_period < 6) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots5;
|
||||
} else if (ideal_period < 9) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots8;
|
||||
} else if (ideal_period < 11) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots10;
|
||||
} else if (ideal_period < 17) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots16;
|
||||
} else if (ideal_period < 21) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots20;
|
||||
} else if (ideal_period < 41) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots40;
|
||||
} else if (ideal_period < 81) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots80;
|
||||
} else if (ideal_period < 161) {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots160;
|
||||
} else {
|
||||
csi_report->slot_periodicity_offset = NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots320;
|
||||
}
|
||||
return csi_report;
|
||||
}
|
||||
|
||||
void nr_ue_sl_csi_period_offset(SL_CSI_Report_t *sl_csi_report,
|
||||
int *period,
|
||||
int *offset) {
|
||||
*offset = sl_csi_report->slot_offset;
|
||||
switch(sl_csi_report->slot_periodicity_offset) {
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots4:
|
||||
*period = 4;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots5:
|
||||
*period = 5;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots8:
|
||||
*period = 8;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots10:
|
||||
*period = 10;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots16:
|
||||
*period = 16;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots20:
|
||||
*period = 20;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots32:
|
||||
*period = 32;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots40:
|
||||
*period = 40;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots64:
|
||||
*period = 64;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots80:
|
||||
*period = 80;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots160:
|
||||
*period = 160;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots320:
|
||||
*period = 320;
|
||||
break;
|
||||
case NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots640:
|
||||
*period = 640;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "No periodicity and offset found in CSI resource");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "mac_defs.h"
|
||||
#include "mac_proto.h"
|
||||
#include "LAYER2/RLC/rlc.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
|
||||
sl_resource_info_t* get_resource_element(List_t* resource_list, frameslot_t sfn);
|
||||
|
||||
static uint16_t sl_adjust_ssb_indices(sl_ssb_timealloc_t *ssb_timealloc, uint32_t slot_in_16frames, uint16_t *ssb_slot_ptr)
|
||||
{
|
||||
@@ -161,7 +165,7 @@ uint8_t sl_determine_if_SSB_slot(uint16_t frame, uint16_t slot, uint16_t slots_p
|
||||
if (num_ssb < sl_NumSSB_WithinPeriod && slot_in_16frames == ssb_slot) {
|
||||
num_ssb += 1;
|
||||
ssb_slot = (num_ssb < sl_NumSSB_WithinPeriod) ? (ssb_slot + sl_TimeInterval) : sl_TimeOffsetSSB;
|
||||
|
||||
// EpiSci TODO: Check slot_type == SIDELINK_SLOT_TYPE_RX is needed or not
|
||||
sl_bch->ssb_slot = ssb_slot;
|
||||
sl_bch->num_ssb = num_ssb;
|
||||
|
||||
@@ -273,17 +277,614 @@ static void sl_actions_after_new_timing(sl_nr_ue_mac_params_t *sl_mac,
|
||||
sl_adjust_indices_based_on_timing(sl_mac, ue_id, frame, slot, slots_per_frame);
|
||||
}
|
||||
|
||||
static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac)
|
||||
static void nr_store_slsch_buffer(NR_UE_MAC_INST_t *mac, frame_t frame, sub_frame_t slot) {
|
||||
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
sched_ctrl->sl_pdus_total = 0;
|
||||
|
||||
const int lcid = 4;
|
||||
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(0, mac->src_id, 0, frame, slot, ENB_FLAG_NO, MBMS_FLAG_NO, 4, 0, 0);
|
||||
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
continue;
|
||||
|
||||
sched_ctrl->sl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
|
||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||
LOG_D(MAC,
|
||||
"[%4d.%2d] SLSCH, RLC status for UE: %d bytes in buffer, total DL buffer size = %d bytes, %d total PDU bytes\n",
|
||||
frame,
|
||||
slot,
|
||||
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
|
||||
sched_ctrl->num_total_bytes,
|
||||
sched_ctrl->sl_pdus_total);
|
||||
}
|
||||
}
|
||||
|
||||
/*TS 38.321
|
||||
A BSR shall be triggered if any of the following events occur:
|
||||
- UL data, for a logical channel which belongs to an LCG, becomes available to the MAC entity; and either
|
||||
=> here we don't implement exactly the same, there is no direct relation with new data came in the UE since last BSR
|
||||
|
||||
- this UL data belongs to a logical channel with higher priority than the priority of any logical channel
|
||||
containing available UL data which belong to any LCG; or
|
||||
=> same, we don't know the last BSR content
|
||||
|
||||
- none of the logical channels which belong to an LCG contains any available UL data.
|
||||
in which case the BSR is referred below to as 'Regular BSR';
|
||||
|
||||
- UL resources are allocated and number of padding bits is equal to or larger than the size of the Buffer Status
|
||||
Report MAC CE plus its subheader, in which case the BSR is referred below to as 'Padding BSR';
|
||||
|
||||
- retxBSR-Timer expires, and at least one of the logical channels which belong to an LCG contains UL data, in
|
||||
which case the BSR is referred below to as 'Regular BSR';
|
||||
|
||||
- periodicBSR-Timer expires, in which case the BSR is referred below to as 'Periodic BSR'.
|
||||
|
||||
*/
|
||||
|
||||
void nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes)
|
||||
{
|
||||
bool bsr_regular_triggered = mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_REGULAR;
|
||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
||||
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
|
||||
int lcid = lc_info->lcid;
|
||||
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
|
||||
int lcgid = lc_sched_info->LCGID;
|
||||
// check if UL data for a logical channel which belongs to a LCG becomes available for transmission
|
||||
if (lcgid != NR_INVALID_LCGID) {
|
||||
// Update waiting bytes for this LCG
|
||||
LCG_bytes[lcgid] += lc_sched_info->LCID_buffer_remain;
|
||||
if (!bsr_regular_triggered) {
|
||||
bsr_regular_triggered = true;
|
||||
trigger_regular_bsr(mac, lcid, lc_info->sr_DelayTimerApplied);
|
||||
LOG_D(NR_MAC, "[UE %d] MAC BSR Triggered\n", mac->ue_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_control_info(NR_UE_MAC_INST_t *mac,
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl,
|
||||
const int nr_slots_per_frame,
|
||||
uint16_t frame,
|
||||
uint16_t slot,
|
||||
int16_t dest_id,
|
||||
NR_SetupRelease_SL_PSFCH_Config_r16_t *configured_PSFCH) {
|
||||
int period = 0, offset = 0;
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
// Determine current slot is csi-rs schedule slot
|
||||
bool csi_acq = !mac->SL_MAC_PARAMS->sl_CSI_Acquisition;
|
||||
bool is_harq_feedback = configured_PSFCH ? is_feedback_scheduled(mac, frame, slot) : false;
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
// Determine current slot is csi report schedule slot
|
||||
SL_CSI_Report_t *sl_csi_report = set_nr_ue_sl_csi_meas_periodicity(tdd, sched_ctrl, mac, dest_id, false);
|
||||
nr_ue_sl_csi_period_offset(sl_csi_report,
|
||||
&period,
|
||||
&offset);
|
||||
LOG_D(NR_MAC, "frame.slot %4d.%2d period %d offset %d\n", frame, slot, period, offset);
|
||||
bool csi_req_slot = !((nr_slots_per_frame * frame + slot - offset) % period);
|
||||
bool is_csi_report_sched_slot = ((sched_ctrl->sched_csi_report.frame == frame) &&
|
||||
(sched_ctrl->sched_csi_report.slot == slot));
|
||||
bool control_info = (is_harq_feedback || (csi_acq && csi_req_slot) || is_csi_report_sched_slot);
|
||||
|
||||
LOG_D(NR_MAC, "frame.slot %4d.%2d harq_feedback %d, (csi_acq && csi_req_slot) %d, is_csi_report_sched_slot %d\n",
|
||||
frame, slot, is_harq_feedback, (csi_acq && csi_req_slot), is_csi_report_sched_slot);
|
||||
|
||||
return control_info;
|
||||
}
|
||||
|
||||
void preprocess(NR_UE_MAC_INST_t *mac,
|
||||
uint16_t frame,
|
||||
uint16_t slot,
|
||||
int *fb_frame,
|
||||
int *fb_slot,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
NR_SetupRelease_SL_PSFCH_Config_r16_t *configured_PSFCH) {
|
||||
|
||||
nr_store_slsch_buffer(mac, frame, slot);
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
int scs = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
const int nr_slots_frame = nr_slots_per_frame[scs];
|
||||
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
UE->mac_sl_stats.sl.current_bytes = 0;
|
||||
UE->mac_sl_stats.sl.current_rbs = 0;
|
||||
NR_sched_pssch_t *sched_pssch = &sched_ctrl->sched_pssch;
|
||||
sched_pssch->sl_harq_pid = configured_PSFCH ? sched_ctrl->retrans_sl_harq.head : -1;
|
||||
|
||||
/* retransmission */
|
||||
if (sched_pssch->sl_harq_pid >= 0) {
|
||||
if (sched_ctrl->available_sl_harq.head < 0) {
|
||||
LOG_W(NR_MAC, "[UE][%4d.%2d] UE has no free SL HARQ process, skipping\n",
|
||||
frame,
|
||||
slot);
|
||||
continue;
|
||||
} else {
|
||||
sched_ctrl->sched_csi_report.active = false;
|
||||
}
|
||||
} else {
|
||||
if (sched_ctrl->available_sl_harq.head < 0) {
|
||||
LOG_W(NR_MAC, "[UE][%4d.%2d] UE has no free SL HARQ process, skipping\n",
|
||||
frame,
|
||||
slot);
|
||||
continue;
|
||||
}
|
||||
bool control_info = get_control_info(mac, sched_ctrl, nr_slots_frame, frame, slot, UE->uid, configured_PSFCH);
|
||||
LOG_D(NR_MAC, "sched_ctrl->num_total_bytes %d, control_info %d\n", sched_ctrl->num_total_bytes, control_info);
|
||||
/* Check SL buffer and control info, skip this UE if no bytes and no control info */
|
||||
if (sched_ctrl->num_total_bytes == 0) {
|
||||
if (!control_info)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SLSCH tx computes feedback frame and slot, which will be used by transmitter of PSFCH after receiving SLSCH.
|
||||
* Transmitter of SLSCH stores the feedback frame and slot in harq process to use those in retreiving the feedback.
|
||||
*/
|
||||
if (configured_PSFCH) {
|
||||
const uint8_t psfch_periods[] = {0, 1, 2, 4};
|
||||
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup;
|
||||
long psfch_period = (sl_psfch_config->sl_PSFCH_Period_r16)
|
||||
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
|
||||
|
||||
int rcv_tx_frame = (frame + ((slot + DURATION_RX_TO_TX) / nr_slots_frame)) % 1024;
|
||||
int rcv_tx_slot = (slot + DURATION_RX_TO_TX) % nr_slots_frame;
|
||||
int psfch_slot = get_feedback_slot(psfch_period, rcv_tx_slot);
|
||||
update_harq_lists(mac, frame, slot, UE);
|
||||
*fb_frame = rcv_tx_frame;
|
||||
*fb_slot = psfch_slot;
|
||||
LOG_D(NR_MAC, "Tx SLSCH %4d.%2d, Expected Feedback: %4d.%2d in current PSFCH: psfch_period %ld\n",
|
||||
frame,
|
||||
slot,
|
||||
*fb_frame,
|
||||
*fb_slot,
|
||||
psfch_period);
|
||||
}
|
||||
int locbw = sl_bwp->sl_BWP_Generic_r16->sl_BWP_r16->locationAndBandwidth;
|
||||
sched_pssch->mu = scs;
|
||||
sched_pssch->frame = frame;
|
||||
sched_pssch->slot = slot;
|
||||
sched_pssch->rbSize = NRRIV2BW(locbw, MAX_BWP_SIZE);
|
||||
sched_pssch->rbStart = NRRIV2PRBOFFSET(locbw, MAX_BWP_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
nr_sidelink_indication_t *sl_ind,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_nr_tx_config_request_t *tx_config,
|
||||
sl_resource_info_t *resource,
|
||||
uint8_t *config_type) {
|
||||
|
||||
uint16_t slot = sl_ind->slot_tx;
|
||||
uint16_t frame = sl_ind->frame_tx;
|
||||
int feedback_frame, feedback_slot;
|
||||
int lcid = 4;
|
||||
int sdu_length = 0;
|
||||
uint16_t sdu_length_total = 0;
|
||||
uint8_t total_mac_pdu_header_len = 0;
|
||||
bool is_resource_allocated = false;
|
||||
*config_type = 0;
|
||||
|
||||
sl_nr_ue_mac_params_t* sl_mac_params = mac->SL_MAC_PARAMS;
|
||||
NR_SetupRelease_SL_PSFCH_Config_r16_t *configured_PSFCH = mac->sl_tx_res_pool->sl_PSFCH_Config_r16;
|
||||
if ((frame & 127) == 0 && slot == 0) {
|
||||
print_meas(&mac->rlc_data_req,"rlc_data_req",NULL,NULL);
|
||||
}
|
||||
if (sl_ind->slot_type != SIDELINK_SLOT_TYPE_TX) return is_resource_allocated;
|
||||
|
||||
if (slot > 9 && get_nrUE_params()->sync_ref) return is_resource_allocated;
|
||||
|
||||
if (slot < 10 && !get_nrUE_params()->sync_ref) return is_resource_allocated;
|
||||
|
||||
LOG_D(NR_MAC,"[UE%d] SL-PSSCH SCHEDULER: Frame:SLOT %d:%d, slot_type:%d\n",
|
||||
sl_ind->module_id, frame, slot,sl_ind->slot_type);
|
||||
|
||||
uint16_t slsch_pdu_length_max;
|
||||
tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.slsch_payload = mac->slsch_payload;
|
||||
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
|
||||
if (*(UE_info->list) == NULL) {
|
||||
LOG_D(NR_MAC, "UE list is empty\n");
|
||||
return is_resource_allocated;
|
||||
}
|
||||
|
||||
preprocess(mac, frame, slot, &feedback_frame, &feedback_slot, sl_bwp, configured_PSFCH);
|
||||
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
NR_mac_dir_stats_t *sl_mac_stats = &UE->mac_sl_stats.sl;
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
sl_mac_stats->current_bytes = 0;
|
||||
sl_mac_stats->current_rbs = 0;
|
||||
NR_sched_pssch_t *sched_pssch = &sched_ctrl->sched_pssch;
|
||||
int8_t harq_id = sched_pssch->sl_harq_pid;
|
||||
|
||||
if (sched_pssch->rbSize <= 0)
|
||||
continue;
|
||||
|
||||
NR_UE_sl_harq_t *cur_harq = NULL;
|
||||
|
||||
if (harq_id < 0) {
|
||||
/* PP has not selected a specific HARQ Process, get a new one */
|
||||
harq_id = sched_ctrl->available_sl_harq.head;
|
||||
AssertFatal(harq_id >= 0,
|
||||
"no free HARQ process available\n");
|
||||
remove_front_nr_list(&sched_ctrl->available_sl_harq);
|
||||
sched_pssch->sl_harq_pid = harq_id;
|
||||
} else {
|
||||
/* PP selected a specific HARQ process. Check whether it will be a new
|
||||
* transmission or a retransmission, and remove from the corresponding
|
||||
* list */
|
||||
if (sched_ctrl->sl_harq_processes[harq_id].round == 0)
|
||||
remove_nr_list(&sched_ctrl->available_sl_harq, harq_id);
|
||||
else
|
||||
remove_nr_list(&sched_ctrl->retrans_sl_harq, harq_id);
|
||||
}
|
||||
cur_harq = &sched_ctrl->sl_harq_processes[harq_id];
|
||||
DevAssert(!cur_harq->is_waiting);
|
||||
/* retransmission or bytes to send */
|
||||
if (configured_PSFCH && ((cur_harq->round != 0) || (sched_ctrl->num_total_bytes > 0))) {
|
||||
cur_harq->feedback_slot = feedback_slot;
|
||||
cur_harq->feedback_frame = feedback_frame;
|
||||
add_tail_nr_list(&sched_ctrl->feedback_sl_harq, harq_id);
|
||||
cur_harq->is_waiting = true;
|
||||
LOG_D(NR_MAC, "%4d.%2d Sending Data; Expecting feedback at %4d.%2d\n", frame, slot, feedback_frame, feedback_slot);
|
||||
}
|
||||
else
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq_id);
|
||||
cur_harq->sl_harq_pid = harq_id;
|
||||
/*
|
||||
The encoder checks for a change in ndi value everytime, since sci2 changes with every transmission,
|
||||
we oscillate the ndi value so the encoder treats the data as new data everytime.
|
||||
*/
|
||||
cur_harq->ndi ^= 1;
|
||||
|
||||
nr_schedule_slsch(mac, frame, slot, &mac->sci1_pdu, &mac->sci2_pdu, NR_SL_SCI_FORMAT_2A,
|
||||
UE, &slsch_pdu_length_max, cur_harq, &sched_ctrl->rlc_status[lcid], resource);
|
||||
|
||||
*config_type = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH;
|
||||
tx_config->number_pdus = 1;
|
||||
tx_config->sfn = frame;
|
||||
tx_config->slot = slot;
|
||||
tx_config->tx_config_list[0].pdu_type = *config_type;
|
||||
fill_pssch_pscch_pdu(sl_mac_params,
|
||||
&tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu,
|
||||
sl_bwp,
|
||||
sl_res_pool,
|
||||
&mac->sci1_pdu,
|
||||
&mac->sci2_pdu,
|
||||
slsch_pdu_length_max,
|
||||
NR_SL_SCI_FORMAT_1A,
|
||||
NR_SL_SCI_FORMAT_2A,
|
||||
slot,
|
||||
resource);
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu = &tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu;
|
||||
sched_pssch->R = pscch_pssch_pdu->target_coderate;
|
||||
sched_pssch->tb_size = pscch_pssch_pdu->tb_size;
|
||||
sched_pssch->sl_harq_pid = mac->sci2_pdu.harq_pid;
|
||||
sched_pssch->nrOfLayers = pscch_pssch_pdu->num_layers;
|
||||
sched_pssch->mcs = pscch_pssch_pdu->mcs;
|
||||
sched_pssch->Qm = pscch_pssch_pdu->mod_order;
|
||||
|
||||
LOG_D(NR_MAC, "PSSCH: %4d.%2d SL sched %4d.%2d start %2d RBS %3d MCS %2d nrOfLayers %2d TBS %4d HARQ PID %2d round %d NDI %d sched %6d\n",
|
||||
frame,
|
||||
slot,
|
||||
sched_pssch->frame,
|
||||
sched_pssch->slot,
|
||||
sched_pssch->rbStart,
|
||||
sched_pssch->rbSize,
|
||||
sched_pssch->mcs,
|
||||
sched_pssch->nrOfLayers,
|
||||
sched_pssch->tb_size,
|
||||
sched_pssch->sl_harq_pid,
|
||||
cur_harq->round,
|
||||
cur_harq->ndi,
|
||||
sched_ctrl->sched_sl_bytes);
|
||||
|
||||
/* Statistics */
|
||||
AssertFatal(cur_harq->round < sl_mac_params->sl_bler.harq_round_max, "Indexing ulsch_rounds[%d] is out of bounds for max harq round %d\n", cur_harq->round, sl_mac_params->sl_bler.harq_round_max);
|
||||
|
||||
sl_mac_stats->rounds[cur_harq->round]++;
|
||||
if (cur_harq->round != 0) { // retransmission
|
||||
LOG_D(NR_MAC,
|
||||
"PSSCH: %d.%2d SL retransmission sched %d.%2d HARQ PID %d round %d NDI %d\n",
|
||||
frame,
|
||||
slot,
|
||||
sched_pssch->frame,
|
||||
sched_pssch->slot,
|
||||
sched_pssch->sl_harq_pid,
|
||||
cur_harq->round,
|
||||
cur_harq->ndi);
|
||||
sl_mac_stats->total_rbs_retx += sched_pssch->rbSize;
|
||||
} else { // initial transmission
|
||||
|
||||
UE->mac_sl_stats.slsch_total_bytes_scheduled += sched_pssch->tb_size;
|
||||
/* save which time allocation and nrOfLayers have been used, to be used on
|
||||
* retransmissions */
|
||||
cur_harq->sched_pssch.nrOfLayers = sched_pssch->nrOfLayers;
|
||||
sched_ctrl->sched_sl_bytes += sched_pssch->tb_size;
|
||||
sl_mac_stats->total_rbs += sched_pssch->rbSize;
|
||||
|
||||
|
||||
int buflen = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.tb_size;
|
||||
|
||||
LOG_D(NR_MAC, "[UE%d] Initial TTI-%d:%d TX PSCCH_PSSCH REQ TBS %d\n", sl_ind->module_id, frame, slot, buflen);
|
||||
|
||||
uint8_t *pdu = (uint8_t *) cur_harq->transportBlock;
|
||||
int buflen_remain = buflen;
|
||||
|
||||
NR_SLSCH_MAC_SUBHEADER_FIXED *sl_sch_subheader = (NR_SLSCH_MAC_SUBHEADER_FIXED *) pdu;
|
||||
sl_sch_subheader->V = 0;
|
||||
sl_sch_subheader->R = 0;
|
||||
sl_sch_subheader->SRC = mac->sci2_pdu.source_id;
|
||||
sl_sch_subheader->DST = mac->sci2_pdu.dest_id;
|
||||
pdu += sizeof(NR_SLSCH_MAC_SUBHEADER_FIXED);
|
||||
LOG_D(NR_MAC, "%4d.%2d Tx V %d, R %d, SRC %d, DST %d\n", frame, slot, sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
|
||||
buflen_remain -= sizeof(NR_SLSCH_MAC_SUBHEADER_FIXED);
|
||||
LOG_D(NR_MAC, "buflen_remain after adding SL_SCH_MAC_SUBHEADER_FIXED %d\n", buflen_remain);
|
||||
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
|
||||
|
||||
int num_sdus=0;
|
||||
if (sched_ctrl->num_total_bytes > 0) {
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer > 0) {
|
||||
while (buflen_remain > sh_size + 1) {
|
||||
|
||||
// Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu;
|
||||
pdu += sh_size;
|
||||
buflen_remain -= sh_size;
|
||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, buflen_remain);
|
||||
|
||||
start_meas(&mac->rlc_data_req);
|
||||
|
||||
sdu_length = mac_rlc_data_req(0,
|
||||
mac->src_id,
|
||||
0,
|
||||
frame,
|
||||
ENB_FLAG_NO,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
ndata,
|
||||
(char *)pdu,
|
||||
0,
|
||||
0);
|
||||
stop_meas(&mac->rlc_data_req);
|
||||
AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n",
|
||||
__FUNCTION__,
|
||||
lcid,
|
||||
sdu_length,
|
||||
buflen_remain);
|
||||
if (sdu_length > 0) {
|
||||
|
||||
LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] SL-DXCH -> SLSCH, Generating SL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID 0x%02x (buflen (TBS) %d bytes)\n",
|
||||
__FUNCTION__,
|
||||
0,
|
||||
frame,
|
||||
slot,
|
||||
num_sdus + 1,
|
||||
sdu_length,
|
||||
lcid,
|
||||
buflen);
|
||||
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = lcid;
|
||||
header->L = htons(sdu_length);
|
||||
pdu += sdu_length;
|
||||
sdu_length_total += sdu_length;
|
||||
total_mac_pdu_header_len += sh_size;
|
||||
buflen_remain -= sdu_length;
|
||||
LOG_D(NR_PHY, "buflen_remain %d, subtracting (sh_size + sdu_length) %d, total_mac_pdu_header_len %hhu sdu total length %d, sdu_length %d\n", buflen_remain, (sh_size + sdu_length), total_mac_pdu_header_len, sdu_length_total, sdu_length);
|
||||
num_sdus++;
|
||||
|
||||
} else {
|
||||
pdu -= sh_size;
|
||||
buflen_remain += sh_size;
|
||||
LOG_D(NR_MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n", __FUNCTION__, lcid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (buflen_remain > 0) {
|
||||
NR_UE_MAC_CE_INFO *mac_ce_p = (NR_UE_MAC_CE_INFO *) pdu;
|
||||
// EpiSci TODO: Check this code block esp. tx_powerand P_CMAX
|
||||
int tx_power = 0;
|
||||
int P_CMAX = 0;
|
||||
// Call BSR procedure as described in Section 5.4.5 in 38.321
|
||||
// Check whether BSR is triggered before scheduling ULSCH
|
||||
uint32_t LCG_bytes[NR_MAX_NUM_LCGID] = {0};
|
||||
nr_update_bsr(mac, LCG_bytes);
|
||||
nr_ue_get_sdu_mac_ce_pre(mac, 0, frame, slot, 0, pdu, buflen_remain, LCG_bytes, mac_ce_p, tx_power, P_CMAX);
|
||||
buflen_remain -= (mac_ce_p->pdu_end - mac_ce_p->end_for_tailer);
|
||||
pdu += (mac_ce_p->pdu_end - mac_ce_p->end_for_tailer);
|
||||
LOG_D(NR_PHY, "buflen_remain %d, sdu_length_total %d, total_mac_pdu_header_len %d, adding tot_mac_ce_len %ld \n", buflen_remain, sdu_length_total, total_mac_pdu_header_len, (mac_ce_p->pdu_end - mac_ce_p->end_for_tailer));
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t sizeof_csi_report = (sizeof(NR_MAC_SUBHEADER_FIXED) + sizeof(nr_sl_csi_report_t));
|
||||
LOG_D(NR_MAC, "%4d.%2d buflen_remain %d ative %d, report slots: %4d.%2d size %d\n",
|
||||
frame,
|
||||
slot,
|
||||
buflen_remain,
|
||||
sched_ctrl->sched_csi_report.active,
|
||||
sched_ctrl->sched_csi_report.frame,
|
||||
sched_ctrl->sched_csi_report.slot,
|
||||
sizeof_csi_report);
|
||||
|
||||
if (sched_ctrl->sched_csi_report.active &&
|
||||
(sched_ctrl->sched_csi_report.frame == frame) &&
|
||||
(sched_ctrl->sched_csi_report.slot == slot)) {
|
||||
|
||||
if (buflen_remain >= sizeof_csi_report) {
|
||||
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
|
||||
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = SL_SCH_LCID_SL_CSI_REPORT;
|
||||
pdu++;
|
||||
buflen_remain -= sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
((nr_sl_csi_report_t *) pdu)->RI = sched_ctrl->sched_csi_report.ri;
|
||||
((nr_sl_csi_report_t *) pdu)->CQI = sched_ctrl->sched_csi_report.cqi;
|
||||
((nr_sl_csi_report_t *) pdu)->R = 0;
|
||||
if (!get_nrUE_params()->sync_ref)
|
||||
LOG_D(NR_MAC, "%4d.%2d Sending sl_csi_report with CQI %i, RI %i\n",
|
||||
frame,
|
||||
slot,
|
||||
((nr_sl_csi_report_t *) pdu)->CQI,
|
||||
((nr_sl_csi_report_t *) pdu)->RI);
|
||||
pdu++;
|
||||
buflen_remain -= sizeof(nr_sl_csi_report_t);
|
||||
}
|
||||
sched_ctrl->sched_csi_report.active = false;
|
||||
}
|
||||
|
||||
if (buflen_remain > 0) {
|
||||
LOG_D(NR_MAC, "In %s filling remainder %d bytes to the UL PDU \n", __FUNCTION__, buflen_remain);
|
||||
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
|
||||
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = SL_SCH_LCID_SL_PADDING;
|
||||
pdu++;
|
||||
buflen_remain--;
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
for (int j = 0; j < buflen_remain; j++) {
|
||||
pdu[j] = (unsigned char) rand();
|
||||
}
|
||||
} else {
|
||||
memset(pdu, 0, buflen_remain);
|
||||
}
|
||||
}
|
||||
|
||||
sl_mac_stats->current_bytes = sched_pssch->tb_size;
|
||||
sl_mac_stats->current_rbs = sched_pssch->rbSize;
|
||||
sl_mac_stats->total_bytes += pscch_pssch_pdu->tb_size;
|
||||
sl_mac_stats->num_mac_sdu += num_sdus;
|
||||
sl_mac_stats->total_sdu_bytes += sdu_length_total;
|
||||
|
||||
/* Save information on MCS, TBS etc for the current initial transmission
|
||||
* so we have access to it when retransmitting */
|
||||
cur_harq->sched_pssch = *sched_pssch;
|
||||
} // end of initial transmission
|
||||
|
||||
const uint32_t TBS = pscch_pssch_pdu->tb_size;
|
||||
memcpy(pscch_pssch_pdu->slsch_payload, cur_harq->transportBlock, TBS);
|
||||
// mark UE as scheduled
|
||||
sched_pssch->rbSize = 0;
|
||||
is_resource_allocated = true;
|
||||
}
|
||||
return is_resource_allocated;
|
||||
}
|
||||
|
||||
void nr_ue_sl_pscch_rx_scheduler(nr_sidelink_indication_t *sl_ind,
|
||||
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
const NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_nr_rx_config_request_t *rx_config,
|
||||
uint8_t *config_type,
|
||||
bool sl_has_psfch) {
|
||||
|
||||
*config_type = SL_NR_CONFIG_TYPE_RX_PSCCH;
|
||||
rx_config->number_pdus = 1;
|
||||
rx_config->sfn = sl_ind->frame_rx;
|
||||
rx_config->slot = sl_ind->slot_rx;
|
||||
rx_config->sl_rx_config_list[0].pdu_type = *config_type;
|
||||
config_pscch_pdu_rx(&rx_config->sl_rx_config_list[0].rx_pscch_config_pdu,
|
||||
sl_bwp,
|
||||
sl_res_pool,
|
||||
sl_has_psfch);
|
||||
|
||||
|
||||
LOG_D(NR_MAC, "[UE%d] TTI-%d:%d RX PSCCH REQ \n", sl_ind->module_id,sl_ind->frame_rx, sl_ind->slot_rx);
|
||||
|
||||
}
|
||||
|
||||
static uint8_t sl_tx_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
int frame,
|
||||
int slot,
|
||||
sl_nr_tx_config_request_t *tx_config,
|
||||
sl_resource_info_t *resource,
|
||||
nr_sidelink_indication_t *sl_ind,
|
||||
long psfch_period,
|
||||
uint8_t mu) {
|
||||
|
||||
//Check if reserved slot or a sidelink resource configured in Rx/Tx resource pool timeresource bitmap
|
||||
uint8_t tti_action = 0;
|
||||
bool is_resource_allocated = nr_ue_sl_pssch_scheduler(mac, sl_ind, mac->sl_bwp, mac->sl_tx_res_pool, tx_config, resource, &tti_action);
|
||||
|
||||
if (is_resource_allocated && mac->sci2_pdu.csi_req) {
|
||||
nr_ue_sl_csi_rs_scheduler(mac, mu, mac->sl_bwp, tx_config, NULL, &tti_action);
|
||||
LOG_D(NR_MAC, "%4d.%2d Scheduling CSI-RS\n", frame, slot);
|
||||
}
|
||||
|
||||
bool is_feedback_slot = mac->sl_tx_res_pool->sl_PSFCH_Config_r16 ? is_feedback_scheduled(mac, frame, slot) : false;
|
||||
|
||||
if (is_resource_allocated && is_feedback_slot && mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup) {
|
||||
if (is_feedback_slot) {
|
||||
nr_ue_sl_psfch_scheduler(mac, frame, slot, psfch_period, sl_ind, mac->sl_bwp, tx_config, &tti_action);
|
||||
reset_sched_psfch(mac, frame, slot);
|
||||
}
|
||||
}
|
||||
|
||||
tx_config->sfn = frame;
|
||||
tx_config->slot = slot;
|
||||
sl_nr_ue_mac_params_t *sl_mac_params = mac->SL_MAC_PARAMS;
|
||||
sl_mac_params->future_ttis[slot].frame = frame;
|
||||
sl_mac_params->future_ttis[slot].slot = slot;
|
||||
sl_mac_params->future_ttis[slot].sl_action = tti_action;
|
||||
|
||||
return tti_action;
|
||||
}
|
||||
|
||||
static uint8_t sl_rx_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
int frame,
|
||||
int slot,
|
||||
sl_nr_rx_config_request_t *rx_config,
|
||||
nr_sidelink_indication_t *sl_ind,
|
||||
long psfch_period,
|
||||
uint8_t mu) {
|
||||
static uint16_t prev_slot = 0;
|
||||
uint8_t tti_action = 0;
|
||||
sl_nr_ue_mac_params_t *sl_mac_params = mac->SL_MAC_PARAMS;
|
||||
|
||||
if (prev_slot != slot) {
|
||||
frameslot_t fs;
|
||||
fs.frame = frame;
|
||||
fs.slot = slot;
|
||||
uint64_t rx_abs_slot = normalize(&fs, mu);
|
||||
uint8_t pool_id = 0;
|
||||
SL_ResourcePool_params_t *sl_rx_rsrc_pool = sl_mac_params->sl_RxPool[pool_id];
|
||||
uint16_t phy_map_sz = ((sl_rx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_rx_rsrc_pool->phy_sl_bitmap.bits_unused);
|
||||
bool sl_has_psfch = slot_has_psfch(mac, &sl_rx_rsrc_pool->phy_sl_bitmap, rx_abs_slot, psfch_period, phy_map_sz, mac->SL_MAC_PARAMS->sl_TDD_config);
|
||||
LOG_D(NR_MAC, "%4d.%2d RX sl_has_psfch %d, psfch_period %ld\n", frame, slot, sl_has_psfch, psfch_period);
|
||||
nr_ue_sl_pscch_rx_scheduler(sl_ind, mac->sl_bwp, mac->sl_rx_res_pool, rx_config, &tti_action, sl_has_psfch);
|
||||
prev_slot = slot;
|
||||
}
|
||||
|
||||
rx_config->sfn = frame;
|
||||
rx_config->slot = slot;
|
||||
sl_mac_params->future_ttis[slot].frame = frame;
|
||||
sl_mac_params->future_ttis[slot].slot = slot;
|
||||
sl_mac_params->future_ttis[slot].sl_action = tti_action;
|
||||
|
||||
return tti_action;
|
||||
}
|
||||
|
||||
static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac, sl_nr_rx_config_request_t *rx_config)
|
||||
{
|
||||
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
int ue_id = mac->ue_id;
|
||||
int rx_action = 0;
|
||||
|
||||
sl_nr_rx_config_request_t rx_config;
|
||||
rx_config.number_pdus = 0;
|
||||
rx_config.sfn = sl_ind->frame_rx;
|
||||
rx_config.slot = sl_ind->slot_rx;
|
||||
if (sl_mac->future_ttis == NULL) {
|
||||
AssertFatal(!get_softmodem_params()->sync_ref, "SyncRef should have allocated future_ttis.");
|
||||
LOG_I(NR_MAC, "[UE%d] %d:%d Nearby UE has not acquired new timing !!!\n",
|
||||
ue_id, sl_ind->frame_rx, sl_ind->slot_rx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sl_ind->sci_ind != NULL) {
|
||||
// TBD..
|
||||
@@ -292,8 +893,8 @@ static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_I
|
||||
}
|
||||
|
||||
if (rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH) {
|
||||
rx_config.number_pdus = 1;
|
||||
rx_config.sl_rx_config_list[0].pdu_type = rx_action;
|
||||
rx_config->number_pdus = 1;
|
||||
rx_config->sl_rx_config_list[0].pdu_type = rx_action;
|
||||
|
||||
LOG_I(NR_MAC, "[UE%d] %d:%d CMD to PHY: RX PSBCH \n", ue_id, sl_ind->frame_rx, sl_ind->slot_rx);
|
||||
|
||||
@@ -304,11 +905,11 @@ static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_I
|
||||
// TBD..
|
||||
}
|
||||
|
||||
if (rx_config.number_pdus) {
|
||||
if (rx_config->number_pdus) {
|
||||
AssertFatal(sl_ind->slot_type == SIDELINK_SLOT_TYPE_RX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH,
|
||||
"RX action cannot be scheduled in non Sidelink RX slot\n");
|
||||
|
||||
nr_scheduled_response_t scheduled_response = {.sl_rx_config = &rx_config,
|
||||
nr_scheduled_response_t scheduled_response = {.sl_rx_config = rx_config,
|
||||
.module_id = sl_ind->module_id,
|
||||
.CC_id = sl_ind->cc_id,
|
||||
.phy_data = sl_ind->phy_data,
|
||||
@@ -321,41 +922,38 @@ static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_I
|
||||
}
|
||||
}
|
||||
|
||||
static void sl_schedule_tx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac)
|
||||
static void sl_schedule_tx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac, sl_nr_tx_config_request_t *tx_config)
|
||||
{
|
||||
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
int ue_id = mac->ue_id;
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
memset(&scheduled_response, 0, sizeof(nr_scheduled_response_t));
|
||||
|
||||
int tx_action = 0;
|
||||
sl_nr_tx_config_request_t tx_config;
|
||||
tx_config.number_pdus = 0;
|
||||
tx_config.sfn = sl_ind->frame_tx;
|
||||
tx_config.slot = sl_ind->slot_tx;
|
||||
|
||||
tx_action = sl_mac->future_ttis[sl_ind->slot_tx].sl_action;
|
||||
|
||||
if (tx_action == SL_NR_CONFIG_TYPE_TX_PSBCH) {
|
||||
tx_config.number_pdus = 1;
|
||||
tx_config.tx_config_list[0].pdu_type = tx_action;
|
||||
tx_config.tx_config_list[0].tx_psbch_config_pdu.tx_slss_id = sl_mac->tx_sl_bch.slss_id;
|
||||
tx_config.tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power = 0; // TBD...
|
||||
memcpy(tx_config.tx_config_list[0].tx_psbch_config_pdu.psbch_payload, sl_mac->tx_sl_bch.sl_mib, 4);
|
||||
tx_config->number_pdus = 1;
|
||||
tx_config->tx_config_list[0].pdu_type = tx_action;
|
||||
tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id = sl_mac->tx_sl_bch.slss_id;
|
||||
tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power = 0; // TBD...
|
||||
memcpy(tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_payload, sl_mac->tx_sl_bch.sl_mib, 4);
|
||||
|
||||
LOG_I(NR_MAC, "[UE%d] %d:%d CMD to PHY: TX PSBCH \n", ue_id, sl_ind->frame_tx, sl_ind->slot_tx);
|
||||
|
||||
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH) {
|
||||
// TBD....
|
||||
|
||||
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSFCH) {
|
||||
// TBD....
|
||||
} else if ((tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH) ||
|
||||
(tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) ||
|
||||
(tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)) {
|
||||
tx_config->number_pdus = 1;
|
||||
fill_scheduled_response(&scheduled_response, NULL, NULL, NULL, NULL, tx_config, sl_ind->module_id, 0, sl_ind->frame_tx, sl_ind->slot_tx, sl_ind->phy_data);
|
||||
}
|
||||
|
||||
if (tx_config.number_pdus == 1) {
|
||||
if (tx_config->number_pdus == 1) {
|
||||
AssertFatal(sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH,
|
||||
"TX action cannot be scheduled in non Sidelink TX slot\n");
|
||||
|
||||
nr_scheduled_response_t scheduled_response = {.sl_tx_config = &tx_config,
|
||||
nr_scheduled_response_t scheduled_response = {.sl_tx_config = tx_config,
|
||||
.module_id = sl_ind->module_id,
|
||||
.CC_id = sl_ind->cc_id,
|
||||
.phy_data = sl_ind->phy_data,
|
||||
@@ -389,6 +987,12 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t
|
||||
sl_mac->timing_acquired = false;
|
||||
}
|
||||
|
||||
sl_nr_rx_config_request_t rx_config;
|
||||
sl_nr_tx_config_request_t tx_config;
|
||||
|
||||
rx_config.number_pdus = 0;
|
||||
tx_config.number_pdus = 0;
|
||||
|
||||
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH) {
|
||||
int frame = sl_ind->frame_tx;
|
||||
int slot = sl_ind->slot_tx;
|
||||
@@ -396,20 +1000,77 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t
|
||||
is_sl_slot = sl_mac->sl_slot_bitmap & (1 << slot);
|
||||
|
||||
if (is_sl_slot) {
|
||||
frameslot_t frame_slot;
|
||||
frame_slot.frame = frame;
|
||||
frame_slot.slot = slot;
|
||||
|
||||
sl_resource_info_t *resource = NULL;
|
||||
if (mac->sl_candidate_resources && mac->sl_candidate_resources->size > 0) {
|
||||
LOG_D(NR_MAC, "%4d.%2d sl_candidate_resources %p size %ld, capacity %ld slot_type %d\n", frame, slot, mac->sl_candidate_resources, mac->sl_candidate_resources->size, mac->sl_candidate_resources->capacity, sl_ind->slot_type);
|
||||
resource = get_resource_element(mac->sl_candidate_resources, frame_slot);
|
||||
if (resource) {
|
||||
LOG_D(NR_MAC, "SELECTED_RESOURCE %4d.%2d slot_type %d, num_sl_pscch_rbs %d, sl_max_num_per_reserve %d, sl_min_time_gap_psfch %d, sl_pscch_sym_start %d, \
|
||||
sl_pscch_sym_len %d, sl_psfch_period %d, sl_pssch_sym_start %d, sl_pssch_sym_len %d, sl_subchan_len %d, sl_subchan_size %d\n",
|
||||
resource->sfn.frame, resource->sfn.slot, sl_ind->slot_type,
|
||||
resource->num_sl_pscch_rbs,
|
||||
resource->sl_max_num_per_reserve,
|
||||
resource->sl_min_time_gap_psfch,
|
||||
resource->sl_pscch_sym_start,
|
||||
resource->sl_pscch_sym_len,
|
||||
resource->sl_psfch_period,
|
||||
resource->sl_pssch_sym_start,
|
||||
resource->sl_pssch_sym_len,
|
||||
resource->sl_subchan_len,
|
||||
resource->sl_subchan_size);
|
||||
}
|
||||
}
|
||||
|
||||
nr_sl_transmission_params_t *sl_tx_params = &sl_mac->mac_tx_params;
|
||||
sl_nr_phy_config_request_t *sl_cfg = &sl_mac->sl_phy_config.sl_config_req;
|
||||
uint8_t mu = sl_cfg->sl_bwp_config.sl_scs;
|
||||
uint16_t p_prime_rsvp_tx = time_to_slots(mu, sl_tx_params->resel_counter);
|
||||
static int8_t is_rsrc_selected = false;
|
||||
|
||||
if (mac->rsc_selection_method == c1 ||
|
||||
mac->rsc_selection_method == c4 ||
|
||||
mac->rsc_selection_method == c5 ||
|
||||
mac->rsc_selection_method == c7) {
|
||||
LOG_D(NR_MAC, "%4d.%2d is_rsrc_selected %d, reselection_timer %d, p_prime_rsvp_tx %d, slot_type %d\n",
|
||||
frame, slot, is_rsrc_selected, mac->reselection_timer, p_prime_rsvp_tx, sl_ind->slot_type);
|
||||
if(is_rsrc_selected && (mac->reselection_timer < p_prime_rsvp_tx)) {
|
||||
mac->reselection_timer++;
|
||||
} else {
|
||||
if (mac->reselection_timer < p_prime_rsvp_tx) {
|
||||
mac->sl_candidate_resources = get_candidate_resources(&frame_slot, mac, &mac->sl_sensing_data, &mac->sl_transmit_history);
|
||||
if (mac->sl_candidate_resources) {
|
||||
LOG_D(NR_MAC, "%4d.%2d Returned resources %p\n", frame, slot, mac->sl_candidate_resources);
|
||||
print_candidate_list(mac->sl_candidate_resources, __LINE__);
|
||||
}
|
||||
is_rsrc_selected = true;
|
||||
} else {
|
||||
mac->reselection_timer = 0;
|
||||
is_rsrc_selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t tti_action = 0;
|
||||
|
||||
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16 ? mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup : NULL;
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
long psfch_period = (sl_psfch_config && sl_psfch_config->sl_PSFCH_Period_r16)
|
||||
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
|
||||
|
||||
// Check if PSBCH slot and PSBCH should be transmitted or Received
|
||||
tti_action = sl_psbch_scheduler(sl_mac, ue_id, frame, slot);
|
||||
|
||||
#if 0 // To be expanded later
|
||||
// TBD .. Check for Actions coming out of TX resource pool
|
||||
if (!tti_action && sl_mac->sl_TxPool[0])
|
||||
tti_action = sl_tx_scheduler(ue_id, frame, slot, sl_mac, sl_mac->sl_TxPool[0]);
|
||||
// Check for Actions coming out of TX resource pool
|
||||
if (resource && sl_mac->is_synced && !tti_action && sl_mac->sl_TxPool[0])
|
||||
tti_action = sl_tx_scheduler(mac, frame, slot, &tx_config, resource, sl_ind, psfch_period, mu);
|
||||
|
||||
//TBD .. Check for Actions coming out of RX resource pool
|
||||
// Check for Actions coming out of RX resource pool
|
||||
if (!tti_action && sl_mac->sl_RxPool[0])
|
||||
tti_action = sl_rx_scheduler(ue_id, frame, slot, sl_mac, sl_mac->sl_RxPool[0]);
|
||||
#endif
|
||||
tti_action = sl_rx_scheduler(mac, frame, slot, &rx_config, sl_ind, psfch_period, mu);
|
||||
|
||||
LOG_D(NR_MAC, "[UE%d]SL-SCHED: TTI - %d:%d scheduled action:%d\n", ue_id, frame, slot, tti_action);
|
||||
|
||||
@@ -418,9 +1079,43 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t
|
||||
}
|
||||
|
||||
// Schedule the Tx actions if any
|
||||
sl_schedule_tx_actions(sl_ind, mac);
|
||||
sl_schedule_tx_actions(sl_ind, mac, &tx_config);
|
||||
}
|
||||
|
||||
if (sl_ind->slot_type == SIDELINK_SLOT_TYPE_RX || sl_ind->slot_type == SIDELINK_SLOT_TYPE_BOTH)
|
||||
sl_schedule_rx_actions(sl_ind, mac);
|
||||
sl_schedule_rx_actions(sl_ind, mac, &rx_config);
|
||||
}
|
||||
|
||||
void print_candidate_list(List_t *candidate_resources, int line) {
|
||||
for (int i = 0; i < candidate_resources->size; i++) {
|
||||
sl_resource_info_t *itr_rsrc = (sl_resource_info_t*)((char*)candidate_resources->data + i * candidate_resources->element_size);
|
||||
LOG_D(NR_MAC, "line %d, %4d.%2d, %ld, sl_subchan_len %d\n", line, itr_rsrc->sfn.frame, itr_rsrc->sfn.slot, normalize(&itr_rsrc->sfn, 1), itr_rsrc->sl_subchan_len);
|
||||
}
|
||||
}
|
||||
|
||||
void print_reserved_list(List_t *candidate_resources, int line) {
|
||||
for (int i = 0; i < candidate_resources->size; i++) {
|
||||
reserved_resource_t *itr_rsrc = (reserved_resource_t*)((char*)candidate_resources->data + i * candidate_resources->element_size);
|
||||
LOG_D(NR_MAC, "line %d, %4d.%2d, %ld, sl_subchan_len %d\n", line, itr_rsrc->sfn.frame, itr_rsrc->sfn.slot, normalize(&itr_rsrc->sfn, 1), itr_rsrc->sb_ch_length);
|
||||
}
|
||||
}
|
||||
|
||||
void print_sensing_data_list(List_t *sensing_data, int line) {
|
||||
for (int i = 0; i < sensing_data->size; i++) {
|
||||
sensing_data_t *itr_rsrc = (sensing_data_t*)((char*)sensing_data->data + i * sensing_data->element_size);
|
||||
LOG_D(NR_MAC, "line %d, %4d.%2d, %ld, sl_subchan_len %d\n", line, itr_rsrc->frame_slot.frame, itr_rsrc->frame_slot.slot, normalize(&itr_rsrc->frame_slot, 1), itr_rsrc->subch_len);
|
||||
}
|
||||
}
|
||||
|
||||
sl_resource_info_t* get_resource_element(List_t* resource_list, frameslot_t sfn) {
|
||||
for (int i = 0; i < resource_list->size; i++) {
|
||||
sl_resource_info_t *itr_rsrc = (sl_resource_info_t*)((char*)resource_list->data + i * resource_list->element_size);
|
||||
LOG_D(NR_MAC, "%s %4d.%2d, %ld, sl_subchan_len %d, current sfn %4d.%2d\n",
|
||||
__FUNCTION__, itr_rsrc->sfn.frame, itr_rsrc->sfn.slot, normalize(&itr_rsrc->sfn, 1), itr_rsrc->sl_subchan_len, sfn.frame, sfn.slot);
|
||||
// TODO: currently, following condition is based on num_subchan = 1, needs to update for multi-subchannels
|
||||
if (itr_rsrc->sfn.frame == sfn.frame && itr_rsrc->sfn.slot == sfn.slot) {
|
||||
return itr_rsrc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
77
openair2/LAYER2/NR_MAC_UE/nr_ue_sci.h
Normal file
77
openair2/LAYER2/NR_MAC_UE/nr_ue_sci.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* \file nr_ue_sci.h
|
||||
* \brief Definitions and Structures for sci/slsch procedures for Sidelink UE
|
||||
* \author R. Knopp
|
||||
* \date 2023
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef __LAYER2_NR_UE_SCI_H__
|
||||
#define __LAYER2_NR_UE_SCI_H__
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
|
||||
typedef enum {
|
||||
NR_SL_SCI_FORMAT_1A = 0,
|
||||
NR_SL_SCI_FORMAT_2A = 1,
|
||||
NR_SL_SCI_FORMAT_2B = 2,
|
||||
NR_SL_SCI_FORMAT_2C = 3
|
||||
} nr_sci_format_t;
|
||||
|
||||
typedef struct {
|
||||
// 1st stage fields
|
||||
uint8_t priority; // 3 bits
|
||||
dci_field_t frequency_resource_assignment; // depending on sl-MaxNumPerReserve and N_subChannel
|
||||
dci_field_t time_resource_assignment; // depending on sl_MaxNumPerReserve
|
||||
dci_field_t resource_reservation_period; // sl-ResourceReservePeriodList and sl-MultiReserveResource
|
||||
dci_field_t dmrs_pattern; // depending on N_pattern and sl-PSSCH-DMRS-TimePatternList
|
||||
uint8_t second_stage_sci_format; // 2 bits - Table 8.3.1.1-1
|
||||
uint8_t beta_offset_indicator; // 2 bits - depending sl-BetaOffsets2ndSCI and Table 8.3.1.1-2
|
||||
uint8_t number_of_dmrs_port; // 1 bit - Table 8.3.1.1-3
|
||||
uint8_t mcs; // 5 bits
|
||||
dci_field_t additional_mcs; // depending on sl-Additional-MCS-Table
|
||||
dci_field_t psfch_overhead; // depending on sl-PSFCH-Period
|
||||
dci_field_t reserved; // depending on N_reserved (sl-NumReservedBits) and sl-IndicationUE-B
|
||||
dci_field_t conflict_information_receiver; // depending on sl-IndicationUE-B
|
||||
// 2nd stage fields
|
||||
uint8_t harq_pid; // 4 bits
|
||||
uint8_t ndi; // 1 bit
|
||||
uint8_t rv_index; // 2 bits
|
||||
uint8_t source_id; // 8 bits
|
||||
uint16_t dest_id; // 16 bits
|
||||
uint8_t harq_feedback; //1 bit
|
||||
uint8_t cast_type; // 2 bits formac 2A
|
||||
uint8_t csi_req; // 1 bit format 2A, format 2C
|
||||
uint16_t zone_id; // 12 bits format 2B
|
||||
dci_field_t communication_range; // 4 bits depending on sl-ZoneConfigMCR-Index, format 2B
|
||||
uint8_t providing_req_ind; // 1 bit, format 2C
|
||||
dci_field_t resource_combinations; // depending on n_subChannel^SL (sl-NumSubchennel), N_rsv_period (sl-ResourceReservePeriodList) and sl-MultiReservedResource, format 2C
|
||||
uint8_t first_resource_location; // 8 bits, format 2C
|
||||
dci_field_t reference_slot_location; // depending on mu, format 2C
|
||||
uint8_t resource_set_type; // 1 bit, format 2C
|
||||
dci_field_t lowest_subchannel_indices; // depending on n_subChannel^SL, format 2C
|
||||
} nr_sci_pdu_t;
|
||||
#endif
|
||||
1051
openair2/LAYER2/NR_MAC_UE/nr_ue_sci_slsch.c
Normal file
1051
openair2/LAYER2/NR_MAC_UE/nr_ue_sci_slsch.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -53,8 +53,6 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
const uint8_t nr_rv_round_map[4] = {0, 2, 3, 1};
|
||||
|
||||
void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
|
||||
int CC_idP,
|
||||
frame_t frameP,
|
||||
|
||||
@@ -236,47 +236,6 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac,
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx)
|
||||
{
|
||||
if (cqi_idx <= 0) {
|
||||
LOG_E(NR_MAC, "invalid cqi_idx %d, default to MCS 9\n", cqi_idx);
|
||||
return 9;
|
||||
}
|
||||
|
||||
if (mcs_table != cqi_table) {
|
||||
LOG_E(NR_MAC, "indices of CQI (%d) and MCS (%d) tables don't correspond yet\n", cqi_table, mcs_table);
|
||||
return 9;
|
||||
}
|
||||
|
||||
uint16_t target_coderate, target_qm;
|
||||
switch (cqi_table) {
|
||||
case 0:
|
||||
target_qm = cqi_table1[cqi_idx][0];
|
||||
target_coderate = cqi_table1[cqi_idx][1];
|
||||
break;
|
||||
case 1:
|
||||
target_qm = cqi_table2[cqi_idx][0];
|
||||
target_coderate = cqi_table2[cqi_idx][1];
|
||||
break;
|
||||
case 2:
|
||||
target_qm = cqi_table3[cqi_idx][0];
|
||||
target_coderate = cqi_table3[cqi_idx][1];
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid cqi table index %d\n",cqi_table);
|
||||
}
|
||||
const int max_mcs = mcs_table == 1 ? 27 : 28;
|
||||
for (int i = 0; i <= max_mcs; i++) {
|
||||
const int R = nr_get_code_rate_dl(i, mcs_table);
|
||||
const int Qm = nr_get_Qm_dl(i, mcs_table);
|
||||
if (Qm == target_qm && target_coderate <= R)
|
||||
return i;
|
||||
}
|
||||
|
||||
LOG_E(NR_MAC, "could not find maximum MCS from cqi_idx %d, default to 9\n", cqi_idx);
|
||||
return 9;
|
||||
}
|
||||
|
||||
NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_UE_DL_BWP_t *dl_bwp,
|
||||
const NR_tda_info_t *tda_info,
|
||||
@@ -720,51 +679,6 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
|
||||
return dmrs;
|
||||
}
|
||||
|
||||
#define BLER_UPDATE_FRAME 10
|
||||
#define BLER_FILTER 0.9f
|
||||
int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
const NR_mac_dir_stats_t *stats,
|
||||
NR_bler_stats_t *bler_stats,
|
||||
int max_mcs,
|
||||
frame_t frame)
|
||||
{
|
||||
/* first call: everything is zero. Initialize to sensible default */
|
||||
if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) {
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = 9;
|
||||
bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f;
|
||||
}
|
||||
int diff = frame - bler_stats->last_frame;
|
||||
if (diff < 0) // wrap around
|
||||
diff += 1024;
|
||||
|
||||
max_mcs = min(max_mcs, bler_options->max_mcs);
|
||||
const uint8_t old_mcs = min(bler_stats->mcs, max_mcs);
|
||||
if (diff < BLER_UPDATE_FRAME)
|
||||
return old_mcs; // no update
|
||||
|
||||
// last update is longer than x frames ago
|
||||
const int num_dl_sched = (int)(stats->rounds[0] - bler_stats->rounds[0]);
|
||||
const int num_dl_retx = (int)(stats->rounds[1] - bler_stats->rounds[1]);
|
||||
const float bler_window = num_dl_sched > 0 ? (float) num_dl_retx / num_dl_sched : bler_stats->bler;
|
||||
bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window;
|
||||
|
||||
int new_mcs = old_mcs;
|
||||
if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && num_dl_sched > 3)
|
||||
new_mcs += 1;
|
||||
else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold
|
||||
|| (num_dl_sched <= 3 && old_mcs > 9)) // no activity
|
||||
new_mcs -= 1;
|
||||
// else we are within threshold boundaries
|
||||
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = new_mcs;
|
||||
memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds));
|
||||
LOG_D(MAC, "frame %4d MCS %d -> %d (num_dl_sched %d, num_dl_retx %d, BLER wnd %.3f avg %.6f)\n",
|
||||
frame, old_mcs, new_mcs, num_dl_sched, num_dl_retx, bler_window, bler_stats->bler);
|
||||
return new_mcs;
|
||||
}
|
||||
|
||||
void config_uldci(const NR_UE_ServingCell_Info_t *sc_info,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
@@ -1925,132 +1839,6 @@ void dump_nr_list(NR_UE_info_t **list)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new NR_list
|
||||
*/
|
||||
void create_nr_list(NR_list_t *list, int len)
|
||||
{
|
||||
list->head = -1;
|
||||
list->next = malloc(len * sizeof(*list->next));
|
||||
AssertFatal(list->next, "cannot malloc() memory for NR_list_t->next\n");
|
||||
for (int i = 0; i < len; ++i)
|
||||
list->next[i] = -1;
|
||||
list->tail = -1;
|
||||
list->len = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize an NR_list
|
||||
*/
|
||||
void resize_nr_list(NR_list_t *list, int new_len)
|
||||
{
|
||||
if (new_len == list->len)
|
||||
return;
|
||||
if (new_len > list->len) {
|
||||
/* list->head remains */
|
||||
const int old_len = list->len;
|
||||
int* n = realloc(list->next, new_len * sizeof(*list->next));
|
||||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||||
list->next = n;
|
||||
for (int i = old_len; i < new_len; ++i)
|
||||
list->next[i] = -1;
|
||||
/* list->tail remains */
|
||||
list->len = new_len;
|
||||
} else { /* new_len < len */
|
||||
AssertFatal(list->head < new_len, "shortened list head out of index %d (new len %d)\n", list->head, new_len);
|
||||
AssertFatal(list->tail < new_len, "shortened list tail out of index %d (new len %d)\n", list->head, new_len);
|
||||
for (int i = 0; i < list->len; ++i)
|
||||
AssertFatal(list->next[i] < new_len, "shortened list entry out of index %d (new len %d)\n", list->next[i], new_len);
|
||||
/* list->head remains */
|
||||
int *n = realloc(list->next, new_len * sizeof(*list->next));
|
||||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||||
list->next = n;
|
||||
/* list->tail remains */
|
||||
list->len = new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an NR_list
|
||||
*/
|
||||
void destroy_nr_list(NR_list_t *list)
|
||||
{
|
||||
free(list->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ID to an NR_list at the end, traversing the whole list. Note:
|
||||
* add_tail_nr_list() is a faster alternative, but this implementation ensures
|
||||
* we do not add an existing ID.
|
||||
*/
|
||||
void add_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
int *cur = &listP->head;
|
||||
while (*cur >= 0) {
|
||||
AssertFatal(*cur != id, "id %d already in NR_UE_list!\n", id);
|
||||
cur = &listP->next[*cur];
|
||||
}
|
||||
*cur = id;
|
||||
if (listP->next[id] < 0)
|
||||
listP->tail = id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an ID from an NR_list
|
||||
*/
|
||||
void remove_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
int *cur = &listP->head;
|
||||
int *prev = &listP->head;
|
||||
while (*cur != -1 && *cur != id) {
|
||||
prev = cur;
|
||||
cur = &listP->next[*cur];
|
||||
}
|
||||
AssertFatal(*cur != -1, "ID %d not found in UE_list\n", id);
|
||||
int *next = &listP->next[*cur];
|
||||
*cur = listP->next[*cur];
|
||||
*next = -1;
|
||||
listP->tail = *prev >= 0 && listP->next[*prev] >= 0 ? listP->tail : *prev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ID to the tail of the NR_list in O(1). Note that there is
|
||||
* corresponding remove_tail_nr_list(), as we cannot set the tail backwards and
|
||||
* therefore need to go through the whole list (use remove_nr_list())
|
||||
*/
|
||||
void add_tail_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
int *last = listP->tail < 0 ? &listP->head : &listP->next[listP->tail];
|
||||
*last = id;
|
||||
listP->next[id] = -1;
|
||||
listP->tail = id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ID to the front of the NR_list in O(1)
|
||||
*/
|
||||
void add_front_nr_list(NR_list_t *listP, int id)
|
||||
{
|
||||
const int ohead = listP->head;
|
||||
listP->head = id;
|
||||
listP->next[id] = ohead;
|
||||
if (listP->tail < 0)
|
||||
listP->tail = id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an ID from the front of the NR_list in O(1)
|
||||
*/
|
||||
void remove_front_nr_list(NR_list_t *listP)
|
||||
{
|
||||
AssertFatal(listP->head >= 0, "Nothing to remove\n");
|
||||
const int ohead = listP->head;
|
||||
listP->head = listP->next[ohead];
|
||||
listP->next[ohead] = -1;
|
||||
if (listP->head < 0)
|
||||
listP->tail = -1;
|
||||
}
|
||||
|
||||
NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
|
||||
{
|
||||
|
||||
|
||||
@@ -553,7 +553,8 @@ static void evaluate_cqi_report(uint8_t *payload,
|
||||
// TODO for wideband case and multiple TB
|
||||
const int cqi_idx = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
|
||||
const int mcs_table = UE->current_DL_BWP.mcsTableIdx;
|
||||
sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_Table, cqi_idx);
|
||||
int default_mcs = 9;
|
||||
sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_Table, cqi_idx, default_mcs);
|
||||
}
|
||||
|
||||
static uint8_t evaluate_pmi_report(uint8_t *payload,
|
||||
|
||||
@@ -318,16 +318,6 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB);
|
||||
|
||||
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
|
||||
|
||||
/* Functions to manage an NR_list_t */
|
||||
void create_nr_list(NR_list_t *listP, int len);
|
||||
void resize_nr_list(NR_list_t *list, int new_len);
|
||||
void destroy_nr_list(NR_list_t *list);
|
||||
void add_nr_list(NR_list_t *listP, int id);
|
||||
void remove_nr_list(NR_list_t *listP, int id);
|
||||
void add_tail_nr_list(NR_list_t *listP, int id);
|
||||
void add_front_nr_list(NR_list_t *listP, int id);
|
||||
void remove_front_nr_list(NR_list_t *listP);
|
||||
|
||||
NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP);
|
||||
|
||||
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
@@ -412,8 +402,6 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac,
|
||||
int layers,
|
||||
int xp_pdsch_antenna_ports);
|
||||
|
||||
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx);
|
||||
|
||||
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
|
||||
|
||||
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
@@ -444,12 +432,6 @@ bool nr_find_nb_rb(uint16_t Qm,
|
||||
uint32_t *tbs,
|
||||
uint16_t *nb_rb);
|
||||
|
||||
int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
const NR_mac_dir_stats_t *stats,
|
||||
NR_bler_stats_t *bler_stats,
|
||||
int max_mcs,
|
||||
frame_t frame);
|
||||
|
||||
int ul_buffer_index(int frame, int slot, int scs, int size);
|
||||
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
|
||||
|
||||
@@ -491,4 +473,5 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
|
||||
|
||||
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti);
|
||||
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -103,16 +103,6 @@
|
||||
#define MAX_NUM_NR_PRACH_PREAMBLES 64
|
||||
#define MIN_NUM_PRBS_TO_SCHEDULE 5
|
||||
|
||||
extern const uint8_t nr_rv_round_map[4];
|
||||
|
||||
/*! \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,
|
||||
@@ -490,15 +480,6 @@ typedef struct NR_UE_harq {
|
||||
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];
|
||||
} 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
|
||||
@@ -694,19 +675,6 @@ typedef struct {
|
||||
uicc_t *uicc;
|
||||
} NRUEcontext_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;
|
||||
} NR_mac_dir_stats_t;
|
||||
|
||||
typedef struct NR_mac_stats {
|
||||
NR_mac_dir_stats_t dl;
|
||||
NR_mac_dir_stats_t ul;
|
||||
@@ -721,13 +689,6 @@ typedef struct NR_mac_stats {
|
||||
int NPRB;
|
||||
} NR_mac_stats_t;
|
||||
|
||||
typedef struct NR_bler_options {
|
||||
double upper;
|
||||
double lower;
|
||||
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;
|
||||
|
||||
@@ -79,3 +79,34 @@ int decode_discard_timer(long v)
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_discard_timer_sl(long v)
|
||||
{
|
||||
static const int tab[18] = {
|
||||
3,
|
||||
10,
|
||||
20,
|
||||
25,
|
||||
30,
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
75,
|
||||
100,
|
||||
150,
|
||||
200,
|
||||
250,
|
||||
300,
|
||||
500,
|
||||
750,
|
||||
1500,
|
||||
-1,
|
||||
};
|
||||
|
||||
if (v < 0 || v > 17) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
@@ -26,5 +26,6 @@ int decode_t_reordering(int v);
|
||||
int decode_sn_size_ul(long s);
|
||||
int decode_sn_size_dl(long s);
|
||||
int decode_discard_timer(long v);
|
||||
int decode_discard_timer_sl(long v);
|
||||
|
||||
#endif /* _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ */
|
||||
|
||||
@@ -187,10 +187,12 @@ static void init_nr_rlc_data_req_queue(void)
|
||||
pthread_mutex_init(&q.m, NULL);
|
||||
pthread_cond_init(&q.c, NULL);
|
||||
|
||||
if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) {
|
||||
/*if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}*/
|
||||
|
||||
threadCreate(&t,rlc_data_req_thread,NULL,"rlc_data_req_thread",-1,OAI_PRIORITY_RT_MAX-1);
|
||||
}
|
||||
|
||||
static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
|
||||
@@ -563,11 +565,12 @@ static void start_pdcp_tun_ue(void)
|
||||
pthread_t t;
|
||||
|
||||
reblock_tun_socket();
|
||||
|
||||
/*
|
||||
if (pthread_create(&t, NULL, ue_tun_read_thread, NULL) != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}*/
|
||||
threadCreate(&t,ue_tun_read_thread,NULL,"ue_tun_read_thread",-1,OAI_PRIORITY_RT_MAX-1);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -826,6 +829,56 @@ void add_srb(int is_gnb,
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, const nr_pdcp_entity_security_keys_and_algos_t *security_parameters)
|
||||
{
|
||||
nr_pdcp_entity_t *pdcp_drb;
|
||||
|
||||
AssertFatal(s->sl_PDCP_Config_r16 != NULL, "SL PDCP config is not there!\n");
|
||||
int slrb_id = s->slrb_Uu_ConfigIndex_r16;
|
||||
int sn_size = decode_sn_size_ul(*s->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16);
|
||||
int discard_timer = decode_discard_timer_sl(*s->sl_PDCP_Config_r16->sl_DiscardTimer_r16);
|
||||
|
||||
// int has_rohc = 0;
|
||||
|
||||
int t_reordering = 20;
|
||||
bool has_sdap = s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_SDAP_Header_r16 == NR_SL_SDAP_Config_r16__sl_SDAP_Header_r16_present;
|
||||
bool is_sdap_DefaultRB = s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_DefaultRB_r16 == true ? true : false;
|
||||
/* TODO(?): accept different UL and DL SN sizes? */
|
||||
|
||||
uint8_t mappedQFIs2AddCount = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16->list.count;
|
||||
NR_QFI_t *mappedQFIs2Add = calloc(mappedQFIs2AddCount, sizeof(*mappedQFIs2Add));
|
||||
LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd from RRC: count %d\n", mappedQFIs2AddCount);
|
||||
|
||||
long standardized_PQI = 0;
|
||||
for (int i = 0; i < mappedQFIs2AddCount; i++) {
|
||||
standardized_PQI = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16->list.array[i]->sl_PQI_r16->choice.sl_StandardizedPQI_r16;
|
||||
if (standardized_PQI < 64)
|
||||
mappedQFIs2Add[i] = standardized_PQI;
|
||||
}
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, srcid);
|
||||
if (ue->drb[slrb_id-1] != NULL) {
|
||||
LOG_W(PDCP, "%s:%d:%s: warning DRB %d already exist for UE ID/RNTI %ld, do nothing\n", __FILE__, __LINE__, __FUNCTION__, slrb_id, srcid);
|
||||
} else {
|
||||
pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, 0, slrb_id, 0,
|
||||
has_sdap, has_sdap,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb_ue, ue,
|
||||
sn_size, t_reordering, discard_timer,
|
||||
security_parameters);
|
||||
// has_ciphering ? ciphering_algorithm : 0,
|
||||
// has_integrity ? integrity_algorithm : 0,
|
||||
// has_ciphering ? ciphering_key : NULL,
|
||||
// has_integrity ? integrity_key : NULL);
|
||||
nr_pdcp_ue_add_drb_pdcp_entity(ue, slrb_id, pdcp_drb);
|
||||
|
||||
LOG_I(PDCP, "%s:%d:%s: added slrb %d to UE ID %ld\n", __FILE__, __LINE__, __FUNCTION__, slrb_id, srcid);
|
||||
|
||||
new_nr_sdap_entity(0, has_sdap, has_sdap, srcid, 0, is_sdap_DefaultRB, slrb_id, mappedQFIs2Add, mappedQFIs2AddCount);
|
||||
}
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
void add_drb(int is_gnb,
|
||||
ue_id_t UEid,
|
||||
struct NR_DRB_ToAddMod *s,
|
||||
|
||||
@@ -140,4 +140,6 @@ int nr_pdcp_get_num_ues(ue_id_t *ue_list, int len);
|
||||
|
||||
bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out);
|
||||
|
||||
void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, const nr_pdcp_entity_security_keys_and_algos_t *security_parameters);
|
||||
|
||||
#endif /* NR_PDCP_OAI_API_H */
|
||||
|
||||
@@ -877,6 +877,68 @@ static void add_drb_am(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B
|
||||
nr_rlc_manager_unlock(nr_rlc_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb_am_sl(int src_id, int drb_id, const NR_SL_RLC_BearerConfig_r16_t *rlc_BearerConfig)
|
||||
{
|
||||
nr_rlc_entity_t *nr_rlc_am;
|
||||
nr_rlc_ue_t *ue;
|
||||
|
||||
struct NR_SL_RLC_Config_r16 *r = rlc_BearerConfig->sl_RLC_Config_r16;
|
||||
struct NR_SL_LogicalChannelConfig_r16 *l = rlc_BearerConfig->sl_MAC_LogicalChannelConfig_r16;
|
||||
int logical_channel_group;
|
||||
|
||||
int t_status_prohibit;
|
||||
int t_poll_retransmit;
|
||||
int poll_pdu;
|
||||
int poll_byte;
|
||||
int max_retx_threshold;
|
||||
int t_reassembly;
|
||||
int sn_field_length;
|
||||
|
||||
if (!(drb_id >= 1 && drb_id <= MAX_DRBS_PER_UE)) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
logical_channel_group = *l->sl_LogicalChannelGroup_r16;
|
||||
|
||||
/* TODO: accept other values? */
|
||||
if (logical_channel_group != 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
//exit(1);
|
||||
}
|
||||
|
||||
struct NR_SL_RLC_Config_r16__sl_AM_RLC_r16 *am;
|
||||
am = r->choice.sl_AM_RLC_r16;
|
||||
t_reassembly = 35;
|
||||
t_status_prohibit = 35;
|
||||
t_poll_retransmit = decode_t_poll_retransmit(am->sl_T_PollRetransmit_r16);
|
||||
poll_pdu = decode_poll_pdu(am->sl_PollPDU_r16);
|
||||
poll_byte = decode_poll_byte(am->sl_PollByte_r16);
|
||||
max_retx_threshold = decode_max_retx_threshold(am->sl_MaxRetxThreshold_r16);
|
||||
sn_field_length = decode_sn_field_length_am(*am->sl_SN_FieldLengthAM_r16);
|
||||
|
||||
nr_rlc_manager_lock(nr_rlc_ue_manager);
|
||||
ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, src_id);
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_W(RLC, "%s:%d:%s: DRB %d already exists for SL UE with src_id %04x, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, src_id);
|
||||
} else {
|
||||
nr_rlc_am = new_nr_rlc_entity_am(RLC_RX_MAXSIZE,
|
||||
RLC_TX_MAXSIZE,
|
||||
deliver_sdu, ue,
|
||||
successful_delivery, ue,
|
||||
max_retx_reached, ue,
|
||||
t_poll_retransmit,
|
||||
t_reassembly, t_status_prohibit,
|
||||
poll_pdu, poll_byte, max_retx_threshold,
|
||||
sn_field_length);
|
||||
nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_am);
|
||||
|
||||
LOG_I(RLC, "%s:%d:%s: added drb %d to UE with SRCID 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, src_id);
|
||||
}
|
||||
nr_rlc_manager_unlock(nr_rlc_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb_um(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig)
|
||||
{
|
||||
struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config;
|
||||
@@ -928,6 +990,54 @@ static void add_drb_um(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B
|
||||
nr_rlc_manager_unlock(nr_rlc_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb_um_sl(int src_id, int drb_id, const NR_SL_RLC_BearerConfig_r16_t *rlc_BearerConfig)
|
||||
{
|
||||
nr_rlc_entity_t *nr_rlc_um;
|
||||
nr_rlc_ue_t *ue;
|
||||
|
||||
struct NR_SL_RLC_Config_r16 *r = rlc_BearerConfig->sl_RLC_Config_r16;
|
||||
struct NR_SL_LogicalChannelConfig_r16 *l = rlc_BearerConfig->sl_MAC_LogicalChannelConfig_r16;
|
||||
int logical_channel_group;
|
||||
|
||||
int sn_field_length;
|
||||
int t_reassembly;
|
||||
|
||||
if (!(drb_id >= 1 && drb_id <= MAX_DRBS_PER_UE)) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
logical_channel_group = *l->sl_LogicalChannelGroup_r16;
|
||||
|
||||
/* TODO: accept other values? */
|
||||
if (logical_channel_group != 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct NR_SL_RLC_Config_r16__sl_UM_RLC_r16 *um;
|
||||
um = r->choice.sl_UM_RLC_r16;
|
||||
t_reassembly = 35; // up to UE implementation, choose 35ms
|
||||
sn_field_length = decode_sn_field_length_um(*um->sl_SN_FieldLengthUM_r16);
|
||||
|
||||
nr_rlc_manager_lock(nr_rlc_ue_manager);
|
||||
ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, src_id);
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_W(RLC, "DEBUG add_drb_um %s:%d:%s: warning DRB %d already exist for SL ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, src_id);
|
||||
} else {
|
||||
nr_rlc_um = new_nr_rlc_entity_um(RLC_RX_MAXSIZE,
|
||||
RLC_TX_MAXSIZE,
|
||||
deliver_sdu, ue,
|
||||
t_reassembly,
|
||||
sn_field_length);
|
||||
nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_um);
|
||||
|
||||
LOG_D(RLC, "%s:%d:%s: added drb %d to UE with SRCID 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, src_id);
|
||||
}
|
||||
nr_rlc_manager_unlock(nr_rlc_ue_manager);
|
||||
}
|
||||
|
||||
void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig)
|
||||
{
|
||||
switch (rlc_BearerConfig->rlc_Config->present) {
|
||||
@@ -944,6 +1054,23 @@ void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_Bear
|
||||
LOG_I(RLC, "Added DRB to UE %d\n", ue_id);
|
||||
}
|
||||
|
||||
void nr_rlc_add_drb_sl(int srcid, int drb_id, const NR_SL_RLC_BearerConfig_r16_t *rlc_BearerConfig)
|
||||
{
|
||||
switch (rlc_BearerConfig->sl_RLC_Config_r16->present) {
|
||||
case NR_SL_RLC_Config_r16_PR_sl_AM_RLC_r16:
|
||||
add_drb_am_sl(srcid, drb_id, rlc_BearerConfig);
|
||||
break;
|
||||
case NR_SL_RLC_Config_r16_PR_sl_UM_RLC_r16:
|
||||
add_drb_um_sl(srcid, drb_id, rlc_BearerConfig);
|
||||
break;
|
||||
default:
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
LOG_I(RLC, "%s:%s:%d: added SL_DRB %d to UE with SRCID 0x%x\n", __FILE__, __FUNCTION__, __LINE__, drb_id,srcid);
|
||||
}
|
||||
|
||||
/* Dummy function due to dependency from LTE libraries */
|
||||
rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
|
||||
const LTE_SRB_ToAddModList_t * const srb2add_listP,
|
||||
|
||||
@@ -43,6 +43,7 @@ struct NR_LogicalChannelConfig;
|
||||
|
||||
void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
|
||||
void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
|
||||
void nr_rlc_add_drb_sl(int srcid, int drb_id, const NR_SL_RLC_BearerConfig_r16_t *rlc_BearerConfig);
|
||||
|
||||
void nr_rlc_set_rlf_handler(int ue_id, rlf_handler_t rlf_h);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "radio/ETHERNET/if_defs.h"
|
||||
#include <stdio.h>
|
||||
#include "openair2/GNB_APP/MACRLC_nr_paramdef.h"
|
||||
#include "colors.h"
|
||||
|
||||
#define MAX_IF_MODULES 100
|
||||
|
||||
@@ -1416,6 +1417,7 @@ static void handle_sl_bch(int ue_id,
|
||||
frame_1 = ((frame_1 & 0x06) >> 1) << 8;
|
||||
uint16_t frame = frame_1 | frame_0;
|
||||
uint8_t slot = ((sl_mib[2] & 0x01) << 6) | ((sl_mib[3] & 0xFC) >> 2);
|
||||
sl_mac->is_synced = true;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"[UE%d]In %d:%d Received SL-MIB:%x .Contents- SL-TDD config:%x, Incov:%d, FN:%d, Slot:%d\n",
|
||||
@@ -1435,6 +1437,23 @@ static void handle_sl_bch(int ue_id,
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t handle_slsch(int module_idP,sl_nr_rx_indication_t *rx_ind,int pdu_id)
|
||||
{
|
||||
nr_ue_process_mac_sl_pdu(module_idP,rx_ind,pdu_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handle_sl_sci1a(module_id_t module_id,uint32_t frame, uint32_t slot, sl_nr_sci_indication_pdu_t *const sci,void *phy_data) {
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
nr_ue_process_sci1_indication_pdu(mac,module_id,frame,slot,sci,phy_data);
|
||||
}
|
||||
|
||||
void handle_sl_sci2(module_id_t module_id, int cc_id, uint32_t frame, uint32_t slot, sl_nr_sci_indication_pdu_t *const sci, void *phy_data) {
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
nr_ue_process_sci2_indication_pdu(mac, module_id, cc_id, frame, slot, sci, phy_data);
|
||||
}
|
||||
|
||||
/*
|
||||
if PSBCH rx - handle_psbch()
|
||||
- Extract FN, Slot
|
||||
@@ -1476,6 +1495,15 @@ void sl_nr_process_rx_ind(int ue_id,
|
||||
|
||||
break;
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH:
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH_PSFCH:
|
||||
|
||||
LOG_D(NR_MAC, "%s[UE%d]SL-MAC Received SLSCH: rx_slsch_pdu:%p, rx_slsch_len %d, ack_nack %d, harq_pid %d\n",KGRN,
|
||||
ue_id, rx_ind->rx_indication_body[num_pdus - 1].rx_slsch_pdu.pdu,
|
||||
rx_ind->rx_indication_body[num_pdus - 1].rx_slsch_pdu.pdu_length,
|
||||
rx_ind->rx_indication_body[num_pdus - 1].rx_slsch_pdu.ack_nack,
|
||||
rx_ind->rx_indication_body[num_pdus - 1].rx_slsch_pdu.harq_pid);
|
||||
|
||||
handle_slsch(ue_id, rx_ind, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1484,6 +1512,29 @@ void sl_nr_process_rx_ind(int ue_id,
|
||||
}
|
||||
}
|
||||
|
||||
/* Process SCI indication from PHY */
|
||||
|
||||
void sl_nr_process_sci_ind(uint16_t module_id, int cc_id, uint32_t frame, uint32_t slot, sl_nr_ue_mac_params_t *sl_mac, sl_nr_sci_indication_t *sci_ind, void *phy_data) {
|
||||
uint8_t num_SCIs = sci_ind->number_of_SCIs;
|
||||
|
||||
for (int idx=0;idx<num_SCIs;idx++) {
|
||||
|
||||
switch (sci_ind->sci_pdu[idx].sci_format_type) {
|
||||
case SL_SCI_FORMAT_1A_ON_PSCCH:
|
||||
LOG_D(NR_MAC,"%s%d.%d Received PSCCH PDU %d/%d PSCCH RSRP %d, length %d, sub-channel index %d, Nid %x, payload %llx\n", KBLU,sci_ind->sfn,sci_ind->slot,1+idx,num_SCIs,sci_ind->sci_pdu[idx].pscch_rsrp,sci_ind->sci_pdu[idx].sci_payloadlen,sci_ind->sci_pdu[idx].subch_index,sci_ind->sci_pdu[idx].Nid,*(unsigned long long*)sci_ind->sci_pdu[idx].sci_payloadBits);
|
||||
handle_sl_sci1a(module_id,frame,slot,&sci_ind->sci_pdu[idx],phy_data);
|
||||
break;
|
||||
case SL_SCI_FORMAT_2_ON_PSSCH:
|
||||
LOG_D(NR_MAC,"%s%d.%d Received PSSCH PDU %d/%d PSSCH RSRP %d, length %d, payload %llx\n", KBLU,sci_ind->sfn,sci_ind->slot,1+idx,num_SCIs,sci_ind->sci_pdu[idx].pscch_rsrp,sci_ind->sci_pdu[idx].sci_payloadlen,*(unsigned long long*)sci_ind->sci_pdu[idx].sci_payloadBits);
|
||||
handle_sl_sci2(module_id, cc_id, frame, slot, &sci_ind->sci_pdu[idx], phy_data);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Unhandled or unknown sci format %d\n",sci_ind->sci_pdu[idx].sci_format_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidelink indication is sent from PHY->MAC.
|
||||
* This interface function handles these
|
||||
@@ -1494,6 +1545,7 @@ void nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication)
|
||||
{
|
||||
// NR_UE_L2_STATE_t ret;
|
||||
int ue_id = sl_indication->module_id;
|
||||
int cc_id = sl_indication->cc_id;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(ue_id);
|
||||
|
||||
uint16_t slot = sl_indication->slot_rx;
|
||||
@@ -1503,6 +1555,9 @@ void nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication)
|
||||
|
||||
if (sl_indication->rx_ind) {
|
||||
sl_nr_process_rx_ind(ue_id, frame, slot, sl_mac, sl_indication->rx_ind);
|
||||
}
|
||||
else if (sl_indication->sci_ind) {
|
||||
sl_nr_process_sci_ind(ue_id, cc_id, frame, slot, sl_mac, sl_indication->sci_ind, sl_indication->phy_data);
|
||||
} else {
|
||||
nr_ue_sidelink_scheduler(sl_indication, mac);
|
||||
}
|
||||
|
||||
@@ -163,6 +163,9 @@ typedef struct {
|
||||
// Sidelink TX configuration request
|
||||
sl_nr_tx_config_request_t *sl_tx_config;
|
||||
|
||||
/// data transmission request structure
|
||||
fapi_nr_tx_request_t *tx_request;
|
||||
|
||||
/// PHY data structure initially passed on to L2 via the nr_downlink_indication_t and
|
||||
/// returned to L1 via nr_scheduled_response_t
|
||||
void *phy_data;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
|
||||
|
||||
nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
slot_rnti_mcs_s slot_rnti_mcs[NUM_NFAPI_SLOT];
|
||||
void read_channel_param(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t * pdu, int slot, int index)
|
||||
{
|
||||
|
||||
@@ -399,7 +399,7 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
|
||||
pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
|
||||
|
||||
int SNRtimes10 = 640; // TODO: Replace with EpiSci SNR * 10
|
||||
int SNRtimes10 = 640; // EpiSci TODO: Replace with SNR * 10
|
||||
|
||||
if (SNRtimes10 < -640)
|
||||
pdu->ul_cqi_information.ul_cqi = 0;
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
#include "nr_nas_msg.h"
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
|
||||
|
||||
static NR_UE_RRC_INST_t *NR_UE_rrc_inst;
|
||||
NR_UE_RRC_INST_t *NR_UE_rrc_inst;
|
||||
/* NAS Attach request with IMSI */
|
||||
static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = {
|
||||
0x07,
|
||||
@@ -2603,7 +2603,7 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc)
|
||||
}
|
||||
|
||||
//This calls the sidelink preconf message after RRC, MAC instances are created.
|
||||
void start_sidelink(int instance)
|
||||
void start_sidelink(int instance, ueinfo_t *ueinfo)
|
||||
{
|
||||
|
||||
NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance];
|
||||
@@ -2611,7 +2611,7 @@ void start_sidelink(int instance)
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
|
||||
//Process the Sidelink Preconfiguration
|
||||
rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref);
|
||||
rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref, ueinfo);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,12 @@ typedef struct NR_UE_RRC_INST_s {
|
||||
NR_RB_status_t status_DRBs[MAX_DRBS_PER_UE];
|
||||
bool active_RLC_entity[NR_MAX_NUM_LCID];
|
||||
|
||||
NR_MIB_t *mib;
|
||||
|
||||
// active BWPs
|
||||
NR_BWP_DownlinkDedicated_t *bwpd;
|
||||
NR_BWP_UplinkDedicated_t *ubwpd;
|
||||
|
||||
/* KgNB as computed from parameters within USIM card */
|
||||
uint8_t kgnb[32];
|
||||
/* Used integrity/ciphering algorithms */
|
||||
@@ -241,6 +247,10 @@ typedef struct NR_UE_RRC_INST_s {
|
||||
bool reconfig_after_reestab;
|
||||
//Sidelink params
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig;
|
||||
NR_MasterInformationBlockSidelink_t *sl_mib;
|
||||
|
||||
struct position *position_coordinates;
|
||||
|
||||
} NR_UE_RRC_INST_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
#include "common/utils/ocp_itti/intertask_interface.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
|
||||
NR_UE_RRC_INST_t *nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx);
|
||||
NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance);
|
||||
@@ -92,9 +93,9 @@ void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc,
|
||||
int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source);
|
||||
|
||||
void init_sidelink(NR_UE_RRC_INST_t *rrc);
|
||||
void start_sidelink(int instance);
|
||||
void start_sidelink(int instance, ueinfo_t *ueinfo);
|
||||
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst, int sync_ref);
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst, int sync_ref, ueinfo_t *ueinfo);
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
|
||||
@@ -28,15 +28,30 @@
|
||||
#include "sl_preconfig_paramvalues.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "rrc_defs.h"
|
||||
#include "rrc_vars.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "nr-uesoftmodem.h"
|
||||
|
||||
#define GNSS_SUPPORT 0
|
||||
|
||||
#define SL_SYNC_SOURCE_NONE 0 //No sync source selected
|
||||
#define SL_SYNC_SOURCE_GNBENB 1 // GNB/ENB as sync source
|
||||
#define SL_SYNC_SOURCE_GNSS 2 // GPS as sync source
|
||||
#define SL_SYNC_SOURCE_SYNC_REF_UE 3 // another SYNC REF UE as sync source
|
||||
#define SL_SYNC_SOURCE_LOCAL_TIMING 4 //UE acts as sync source
|
||||
|
||||
|
||||
void free_sl_rrc(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
|
||||
if (rrc->sl_preconfig) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, rrc->sl_preconfig);
|
||||
}
|
||||
if (rrc->sl_mib) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, rrc->sl_mib);
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_NR_SL_SyncConfig(NR_SL_SyncConfig_r16_t *sl_syncconfig)
|
||||
@@ -117,8 +132,35 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
ASN_SEQUENCE_ADD(&sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_PSSCH_DMRS_TimePatternList_r16->list, p);
|
||||
}
|
||||
|
||||
//PSFCH configuration
|
||||
sl_res_pool->sl_PSFCH_Config_r16 = NULL;
|
||||
// This should be added to configuration file
|
||||
sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_Scaling_r16 = calloc(1,sizeof(*sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_Scaling_r16));
|
||||
*sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_Scaling_r16 = NR_SL_PSSCH_Config_r16__sl_Scaling_r16_f0p5;
|
||||
|
||||
// PSFCH configuration
|
||||
sl_res_pool->sl_PSFCH_Config_r16 = calloc(1, sizeof(*sl_res_pool->sl_PSFCH_Config_r16));
|
||||
sl_res_pool->sl_PSFCH_Config_r16->present = NR_SetupRelease_SL_PSFCH_Config_r16_PR_setup;
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup = calloc(1, sizeof(NR_SL_PSFCH_Config_r16_t));
|
||||
|
||||
// Period of PSFCH resource in the unit of slots within this resource pool. If set to sl0, no resource for PSFCH,
|
||||
//and HARQ feedback for all transmissions in the resource pool is disabled.
|
||||
// {sl0, sl1, sl2, sl4}
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16 = calloc(1, sizeof(long));
|
||||
|
||||
// Set of PRBs that are actually used for PSFCH transmission and reception (bitmap)
|
||||
// 0xFFFFFFFFFFFF (PRBs bitmap) Multiple of sl_NumSubchannel * sl_PSFCH_Period
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16 = calloc(1, sizeof(*sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16));
|
||||
|
||||
// Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_NumMuxCS_Pair_r16 = calloc(1, sizeof(long));
|
||||
|
||||
// The minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_MinTimeGapPSFCH_r16 = calloc(1, sizeof(long));
|
||||
|
||||
// Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_HopID_r16 = calloc(1, sizeof(long));
|
||||
|
||||
// Indicates the number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_CandidateResourceType_r16 = calloc(1, sizeof(long));
|
||||
|
||||
// indicates allowed sync sources which are allowed to use this resource pool
|
||||
sl_res_pool->sl_SyncAllowed_r16 = calloc(1, sizeof(NR_SL_SyncAllowed_r16_t));
|
||||
@@ -153,7 +195,9 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_res_pool->sl_TimeWindowSizeCBR_r16 = NULL;
|
||||
sl_res_pool->sl_TimeWindowSizeCR_r16 = NULL;
|
||||
sl_res_pool->sl_PTRS_Config_r16 = NULL;
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16 = NULL;
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16 = calloc(1,sizeof(*sl_res_pool->sl_UE_SelectedConfigRP_r16));
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_MaxNumPerReserve_r16 = calloc(1,sizeof(*sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_MaxNumPerReserve_r16));
|
||||
|
||||
sl_res_pool->sl_RxParametersNcell_r16 = NULL;
|
||||
sl_res_pool->sl_ZoneConfigMCR_List_r16 = NULL;
|
||||
sl_res_pool->sl_FilterCoefficient_r16 = NULL;
|
||||
@@ -165,7 +209,10 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_res_pool->sl_PriorityThreshold_UL_URLLC_r16 = NULL;
|
||||
sl_res_pool->sl_PriorityThreshold_r16 = NULL;
|
||||
sl_res_pool->sl_X_Overhead_r16 = NULL;
|
||||
sl_res_pool->sl_PowerControl_r16 = NULL;
|
||||
sl_res_pool->sl_PowerControl_r16 = calloc(1,sizeof(*sl_res_pool->sl_PowerControl_r16));
|
||||
sl_res_pool->sl_PowerControl_r16->sl_Alpha_PSSCH_PSCCH_r16 = calloc(1,sizeof(*sl_res_pool->sl_PowerControl_r16->sl_Alpha_PSSCH_PSCCH_r16));
|
||||
*sl_res_pool->sl_PowerControl_r16->sl_Alpha_PSSCH_PSCCH_r16 = 0;
|
||||
|
||||
sl_res_pool->sl_TxPercentageList_r16 = NULL;
|
||||
sl_res_pool->sl_MinMaxMCS_List_r16 = NULL;
|
||||
|
||||
@@ -177,11 +224,11 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
// EX: BITMAP 10101010.. indicating every alternating slot supported for sidelink
|
||||
for (int i=0;i<sl_res_pool->ext1->sl_TimeResource_r16->size;i++) {
|
||||
if (is_txpool) {
|
||||
sl_res_pool->ext1->sl_TimeResource_r16->buf[i] = (is_sl_syncsource) ? 0xAA //0x88;//0xAA;
|
||||
: 0x55;//0x11;//0x55;
|
||||
sl_res_pool->ext1->sl_TimeResource_r16->buf[i] = (is_sl_syncsource) ? 0xF0 //0x88;//0xAA;
|
||||
: 0x0F;//0x11;//0x55;
|
||||
} else {
|
||||
sl_res_pool->ext1->sl_TimeResource_r16->buf[i] = (is_sl_syncsource) ? 0x55 //0x88;//0xAA;
|
||||
: 0xAA;//0x11;//0x55;
|
||||
sl_res_pool->ext1->sl_TimeResource_r16->buf[i] = (is_sl_syncsource) ? 0x0F //0x88;//0xAA;
|
||||
: 0xF0;//0x11;//0x55;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +243,67 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0,SL_CONFIG_STRING_SL_RX_RPOOL_LIST, 0);
|
||||
|
||||
config_get(config_get_if(), SL_POOLPARAMS, sizeofArray(SL_POOLPARAMS), aprefix);
|
||||
|
||||
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SelectionWindowList_r16 = calloc(1, sizeof(*sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SelectionWindowList_r16));
|
||||
struct NR_SL_UE_SelectedConfigRP_r16 *nr_sl_ue_Selected_config = sl_res_pool->sl_UE_SelectedConfigRP_r16;
|
||||
nr_sl_ue_Selected_config->sl_SelectionWindowList_r16->list.array = (NR_SL_SelectionWindowConfig_r16_t**)malloc16_clear(sizeof(NR_SL_SelectionWindowConfig_r16_t*));
|
||||
nr_sl_ue_Selected_config->sl_SelectionWindowList_r16->list.array[0] = (NR_SL_SelectionWindowConfig_r16_t*)malloc16_clear(sizeof(NR_SL_SelectionWindowConfig_r16_t));
|
||||
|
||||
nr_sl_ue_Selected_config->sl_SensingWindow_r16 = calloc(1, sizeof(*nr_sl_ue_Selected_config->sl_SensingWindow_r16));
|
||||
|
||||
nr_sl_ue_Selected_config->sl_Thres_RSRP_List_r16 = calloc(1, sizeof(*nr_sl_ue_Selected_config->sl_Thres_RSRP_List_r16));
|
||||
nr_sl_ue_Selected_config->sl_Thres_RSRP_List_r16->list.array = (NR_SL_Thres_RSRP_r16_t**)malloc16_clear(sizeof(NR_SL_Thres_RSRP_r16_t*));
|
||||
nr_sl_ue_Selected_config->sl_Thres_RSRP_List_r16->list.array[0] = (NR_SL_Thres_RSRP_r16_t*)malloc16_clear(sizeof(NR_SL_Thres_RSRP_r16_t));
|
||||
|
||||
nr_sl_ue_Selected_config->sl_MaxNumPerReserve_r16 = calloc(1, sizeof(*nr_sl_ue_Selected_config->sl_MaxNumPerReserve_r16));
|
||||
|
||||
nr_sl_ue_Selected_config->sl_ResourceReservePeriodList_r16 = calloc(1, sizeof(*nr_sl_ue_Selected_config->sl_ResourceReservePeriodList_r16));
|
||||
nr_sl_ue_Selected_config->sl_ResourceReservePeriodList_r16->list.array = (NR_SL_ResourceReservePeriod_r16_t**)malloc16_clear(sizeof(NR_SL_ResourceReservePeriod_r16_t*));
|
||||
nr_sl_ue_Selected_config->sl_ResourceReservePeriodList_r16->list.array[0] = (NR_SL_ResourceReservePeriod_r16_t*)malloc16_clear(sizeof(NR_SL_ResourceReservePeriod_r16_t));
|
||||
|
||||
char aprefix_rsc_sel[MAX_OPTNAME_SIZE*2 + 8];
|
||||
paramdef_t SL_RSCSELECTIONPARAMS[] = SL_RSRCSELPARAMS_DESC(sl_res_pool);
|
||||
sprintf(aprefix_rsc_sel, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0,SL_CONFIG_STRING_RSRC_SEL_PARAMS_LIST, 0);
|
||||
config_get(config_get_if(), SL_RSCSELECTIONPARAMS, sizeofArray(SL_RSCSELECTIONPARAMS), aprefix_rsc_sel);
|
||||
LOG_D(NR_RRC, "sl_MaxNumPerReserve %ld, sl_SensingWindow %ld, sl_Priority %ld, sl_SelectionWindow %ld, sl_ResourceReservePeriod1 %ld\n",
|
||||
*sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_MaxNumPerReserve_r16,
|
||||
*sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SensingWindow_r16,
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SelectionWindowList_r16->list.array[0]->sl_Priority_r16,
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SelectionWindowList_r16->list.array[0]->sl_SelectionWindow_r16,
|
||||
sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_ResourceReservePeriodList_r16->list.array[0]->choice.sl_ResourceReservePeriod1_r16);
|
||||
struct NR_SL_PSFCH_Config_r16 *nr_sl_psfch_config = sl_res_pool->sl_PSFCH_Config_r16->choice.setup;
|
||||
if (*nr_sl_psfch_config->sl_PSFCH_Period_r16 > 0) {
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
AssertFatal(*nr_sl_psfch_config->sl_PSFCH_Period_r16 < 4, "sl_PSFCH_Period_r16 index must be less than 4\n");
|
||||
LOG_D(NR_PHY, "Configuring PSFCH Period %d\n", psfch_periods[*nr_sl_psfch_config->sl_PSFCH_Period_r16]);
|
||||
uint8_t psfch_period = psfch_periods[*nr_sl_psfch_config->sl_PSFCH_Period_r16];
|
||||
uint16_t prod_numCh_period = *sl_res_pool->sl_NumSubchannel_r16*psfch_period;
|
||||
uint16_t num_prbs = (*sl_res_pool->sl_RB_Number_r16 / prod_numCh_period) * prod_numCh_period;
|
||||
uint16_t num_bytes = (num_prbs % 8) ? (num_prbs / 8) + 1 : (num_prbs / 8);
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16->size = num_bytes;
|
||||
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16->bits_unused = (num_prbs % 8) ? 8 - (num_prbs % 8) : 0;
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16->buf = calloc(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16->size, sizeof(uint8_t));
|
||||
memset(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16->buf, 0xFF, num_prbs / 8);
|
||||
uint8_t remaining_prbs = 0;
|
||||
for (int i = 8 - (num_prbs % 8); i < 8; i++)
|
||||
remaining_prbs |= 1 << i;
|
||||
if ( num_prbs % 8 != 0 )
|
||||
sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16->buf[num_prbs/8] = remaining_prbs;
|
||||
LOG_D(RRC, "M: %d, PRBs %d, size in bytes %d, unused bits %d, full size bytes %d, remaining prbs %d\n", prod_numCh_period, num_prbs, num_bytes, (num_prbs % 8) ? 8 - (num_prbs % 8) : 0, num_prbs / 8, remaining_prbs);
|
||||
} else {
|
||||
LOG_I(NR_RRC,"Freeing sl_PSFCH_Config_r16\n");
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_CandidateResourceType_r16);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_HopID_r16);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_MinTimeGapPSFCH_r16);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_NumMuxCS_Pair_r16);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_RB_Set_r16);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16->choice.setup);
|
||||
free(sl_res_pool->sl_PSFCH_Config_r16);
|
||||
sl_res_pool->sl_PSFCH_Config_r16 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_NR_SL_BWPConfigCommon(NR_SL_BWP_ConfigCommon_r16_t *sl_bwp,
|
||||
@@ -352,11 +460,64 @@ NR_SL_PreconfigurationNR_r16_t *prepare_NR_SL_PRECONFIGURATION(uint16_t num_tx_p
|
||||
sl_preconfig->sl_PreconfigEUTRA_AnchorCarrierFreqList_r16 = NULL;
|
||||
|
||||
// NR sidelink radio bearer(s) configuration(s)
|
||||
sl_preconfig->sl_RadioBearerPreConfigList_r16 = NULL; // fill later
|
||||
sl_preconfig->sl_RadioBearerPreConfigList_r16 = calloc(1,sizeof(*sl_preconfig->sl_RadioBearerPreConfigList_r16)); // fill later
|
||||
struct NR_SL_RadioBearerConfig_r16 *sl_RadioBearerConfig_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16));
|
||||
|
||||
sl_RadioBearerConfig_r16->slrb_Uu_ConfigIndex_r16 = 1;
|
||||
sl_RadioBearerConfig_r16->sl_SDAP_Config_r16 = calloc(1, sizeof(*sl_RadioBearerConfig_r16->sl_SDAP_Config_r16));
|
||||
struct NR_SL_SDAP_Config_r16* sl_SDAP_Config = sl_RadioBearerConfig_r16->sl_SDAP_Config_r16;
|
||||
sl_SDAP_Config->sl_SDAP_Header_r16 = NR_SL_SDAP_Config_r16__sl_SDAP_Header_r16_present;
|
||||
sl_SDAP_Config->sl_DefaultRB_r16 = true;
|
||||
sl_SDAP_Config->sl_CastType_r16 = calloc(1, sizeof(*sl_SDAP_Config->sl_CastType_r16));
|
||||
*sl_SDAP_Config->sl_CastType_r16 = NR_SL_SDAP_Config_r16__sl_CastType_r16_unicast;
|
||||
sl_SDAP_Config->sl_MappedQoS_Flows_r16 = calloc(1, sizeof(*sl_SDAP_Config->sl_MappedQoS_Flows_r16));
|
||||
sl_SDAP_Config->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16 = calloc(1, sizeof(*sl_SDAP_Config->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16));
|
||||
struct NR_SL_SDAP_Config_r16__sl_MappedQoS_Flows_r16__sl_MappedQoS_FlowsList_r16* sl_MappedQoS_FlowList = sl_SDAP_Config->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16;
|
||||
|
||||
NR_SL_QoS_Profile_r16_t *sl_QoS_Profile_r16_f1 = calloc(1, sizeof(*sl_QoS_Profile_r16_f1));
|
||||
sl_QoS_Profile_r16_f1->sl_PQI_r16 = calloc(1, sizeof(*sl_QoS_Profile_r16_f1->sl_PQI_r16));
|
||||
struct NR_SL_PQI_r16 *sl_PQI = sl_QoS_Profile_r16_f1->sl_PQI_r16;
|
||||
sl_PQI->choice.sl_StandardizedPQI_r16 = 55;
|
||||
|
||||
ASN_SEQUENCE_ADD(&sl_MappedQoS_FlowList->list, sl_QoS_Profile_r16_f1);
|
||||
|
||||
sl_RadioBearerConfig_r16->sl_TransRange_r16 = NULL;
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16));
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_DiscardTimer_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_DiscardTimer_r16));
|
||||
*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_DiscardTimer_r16 = NR_SL_PDCP_Config_r16__sl_DiscardTimer_r16_infinity;
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16));
|
||||
*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16 = NR_SL_PDCP_Config_r16__sl_PDCP_SN_Size_r16_len12bits;
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_OutOfOrderDelivery = NULL;
|
||||
ASN_SEQUENCE_ADD(&sl_preconfig->sl_RadioBearerPreConfigList_r16->list,sl_RadioBearerConfig_r16);
|
||||
|
||||
// NR sidelink RLC bearer(s) configuration(s)
|
||||
sl_preconfig->sl_RLC_BearerPreConfigList_r16 = NULL; // fill later
|
||||
sl_preconfig->sl_RLC_BearerPreConfigList_r16 = calloc(1,sizeof(*sl_preconfig->sl_RLC_BearerPreConfigList_r16));
|
||||
struct NR_SL_RLC_BearerConfig_r16 *sl_RLC_BearerConfig_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16));
|
||||
// initialize with UM for now
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_BearerConfigIndex_r16 = 0;
|
||||
sl_RLC_BearerConfig_r16->sl_ServedRadioBearer_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_ServedRadioBearer_r16));
|
||||
*sl_RLC_BearerConfig_r16->sl_ServedRadioBearer_r16 = 1;
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16));
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->present = NR_SL_RLC_Config_r16_PR_sl_UM_RLC_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16));
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16->sl_SN_FieldLengthUM_r16=calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16));
|
||||
|
||||
*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16->sl_SN_FieldLengthUM_r16=NR_SN_FieldLengthUM_size6;
|
||||
// Logical Channel Config for default link
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16));
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_Priority_r16 = 1;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_PrioritisedBitRate_r16 = NR_SL_LogicalChannelConfig_r16__sl_PrioritisedBitRate_r16_infinity;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_BucketSizeDuration_r16 = NR_SL_LogicalChannelConfig_r16__sl_BucketSizeDuration_r16_ms5;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_ConfiguredGrantType1Allowed_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_HARQ_FeedbackEnabled_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_HARQ_FeedbackEnabled_r16));
|
||||
*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_HARQ_FeedbackEnabled_r16 = NR_SL_LogicalChannelConfig_r16__sl_HARQ_FeedbackEnabled_r16_enabled;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_AllowedCG_List_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_AllowedSCS_List_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelGroup_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelGroup_r16));
|
||||
*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelGroup_r16 = 1;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_SchedulingRequestId_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelSR_DelayTimerApplied_r16 = NULL;
|
||||
ASN_SEQUENCE_ADD(&sl_preconfig->sl_RLC_BearerPreConfigList_r16->list,sl_RLC_BearerConfig_r16);
|
||||
//Measurement and reporting configuration
|
||||
sl_preconfig->sl_MeasPreConfig_r16 = NULL;
|
||||
|
||||
@@ -398,7 +559,7 @@ NR_SL_PreconfigurationNR_r16_t *prepare_NR_SL_PRECONFIGURATION(uint16_t num_tx_p
|
||||
sl_preconfig->sl_UE_SelectedPreConfig_r16 = NULL;
|
||||
|
||||
// indicates if CSI reporting supported in SL unicast.
|
||||
sl_preconfig->sl_CSI_Acquisition_r16 = NULL;
|
||||
sl_preconfig->sl_CSI_Acquisition_r16 = calloc(1, sizeof(*sl_preconfig->sl_CSI_Acquisition_r16));
|
||||
|
||||
// ROHC profiles for NR SL
|
||||
sl_preconfig->sl_RoHC_Profiles_r16 = NULL;
|
||||
@@ -440,9 +601,10 @@ int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source)
|
||||
}
|
||||
|
||||
/*decode SL-BCH (SL-MIB) message*/
|
||||
static int8_t nr_sl_rrc_ue_decode_SL_MIB(const uint8_t gNB_index,
|
||||
uint8_t *const bufferP,
|
||||
const uint8_t buffer_len)
|
||||
static int8_t nr_sl_rrc_ue_decode_SL_MIB(const module_id_t module_id,
|
||||
const uint8_t gNB_index,
|
||||
uint8_t *const bufferP,
|
||||
const uint8_t buffer_len)
|
||||
{
|
||||
NR_MasterInformationBlockSidelink_t *sl_mib = NULL;
|
||||
|
||||
@@ -450,30 +612,33 @@ static int8_t nr_sl_rrc_ue_decode_SL_MIB(const uint8_t gNB_index,
|
||||
(void **)&sl_mib,
|
||||
(const void *)bufferP, buffer_len);
|
||||
|
||||
int ret = 0;
|
||||
uint16_t val_fn = sl_mib->directFrameNumber_r16.buf[0];
|
||||
val_fn = (val_fn << 2) + (sl_mib->directFrameNumber_r16.buf[1] >> sl_mib->directFrameNumber_r16.bits_unused);
|
||||
|
||||
uint8_t val_slot = sl_mib->slotIndex_r16.buf[0];
|
||||
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - DFN:%d\n" , val_fn);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - SLOT:%d\n" , val_slot >> 1);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - Incoverage:%d\n", sl_mib->inCoverage_r16);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - sl-TDD-Config:%x\n" , *((uint16_t *)(sl_mib->sl_TDD_Config_r16.buf)));
|
||||
|
||||
int ret = 1;
|
||||
if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) {
|
||||
LOG_E(NR_RRC, "SL-MIB decode error\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
|
||||
int bits_unused = sl_mib->directFrameNumber_r16.bits_unused;
|
||||
uint16_t val_fn = sl_mib->directFrameNumber_r16.buf[0];
|
||||
val_fn = (val_fn << (8 - bits_unused)) + (sl_mib->directFrameNumber_r16.buf[1] >> bits_unused);
|
||||
|
||||
uint8_t val_slot = sl_mib->slotIndex_r16.buf[0];
|
||||
|
||||
LOG_D(NR_RRC, "%d:%d SL-RRC - Received MIB.\n", val_fn, val_slot >> 1);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - Incoverage:%d\n", sl_mib->inCoverage_r16);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - sl-TDD-Config:%x\n" , *((uint16_t *)(sl_mib->sl_TDD_Config_r16.buf)));
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, sl_mib);
|
||||
|
||||
ret = 0;
|
||||
if (NR_UE_rrc_inst[module_id].sl_mib == NULL) {
|
||||
LOG_I(NR_RRC, "Sidelink RRC first MIB reception\n");
|
||||
} else {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, NR_UE_rrc_inst[module_id].sl_mib);
|
||||
}
|
||||
NR_UE_rrc_inst[module_id].sl_mib = sl_mib;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
@@ -483,7 +648,7 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint16_t rx_slss_id)
|
||||
{
|
||||
|
||||
nr_sl_rrc_ue_decode_SL_MIB(gNB_index, (uint8_t*)pduP, pdu_len);
|
||||
nr_sl_rrc_ue_decode_SL_MIB(rrc->ue_id, gNB_index, (uint8_t*)pduP, pdu_len);
|
||||
|
||||
DevAssert(rrc->sl_preconfig);
|
||||
|
||||
@@ -509,7 +674,8 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
}
|
||||
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
|
||||
sl_sync_source_enum_t sync_source)
|
||||
sl_sync_source_enum_t is_sync_source,
|
||||
ueinfo_t *ueinfo)
|
||||
{
|
||||
|
||||
AssertFatal(rrc_inst, "RRC instance not created.\n");
|
||||
@@ -517,10 +683,27 @@ void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = rrc_inst->sl_preconfig;
|
||||
AssertFatal(rrc_inst->sl_preconfig, "Check if SL-preconfig was created");
|
||||
|
||||
uint8_t sync_source = SL_SYNC_SOURCE_NONE;
|
||||
|
||||
if (is_sync_source) {
|
||||
sync_source = (GNSS_SUPPORT) ? SL_SYNC_SOURCE_GNSS
|
||||
: SL_SYNC_SOURCE_LOCAL_TIMING;
|
||||
}
|
||||
|
||||
AssertFatal(sync_source != SL_SYNC_SOURCE_GNBENB, "Sync source GNB not supported\n");
|
||||
|
||||
nr_rrc_mac_config_req_sl_preconfig(rrc_inst->ue_id, sl_preconfig, sync_source);
|
||||
|
||||
|
||||
// SL RadioBearers
|
||||
nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0};
|
||||
for (int i=0; i<sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.count; i++) {
|
||||
add_drb_sl(ueinfo->srcid, (NR_SL_RadioBearerConfig_r16_t *)sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.array[i], &null_security_parameters);
|
||||
}
|
||||
// configure RLC
|
||||
for (int i=0; i<sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.count; i++) {
|
||||
nr_rlc_add_drb_sl(ueinfo->srcid, 1, (NR_SL_RLC_BearerConfig_r16_t *)sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.array[i]);
|
||||
}
|
||||
//TBD.. These should be chosen by RRC according to 3GPP 38.331 RRC specification.
|
||||
//Currently hardcoding the values to these
|
||||
uint16_t slss_id = 671, ssb_ta_index = 1;
|
||||
@@ -554,6 +737,42 @@ void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
|
||||
|
||||
}
|
||||
|
||||
void nr_mac_rrc_sl_mib_ind(const module_id_t module_id,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
const int slot,
|
||||
const channel_t channel,
|
||||
uint8_t* pduP,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id)
|
||||
{
|
||||
|
||||
nr_sl_rrc_ue_decode_SL_MIB(module_id, gNB_index, (uint8_t*)pduP, pdu_len);
|
||||
|
||||
DevAssert(NR_UE_rrc_inst[module_id].sl_preconfig);
|
||||
|
||||
NR_SL_FreqConfigCommon_r16_t *fcfg = NULL;
|
||||
if (NR_UE_rrc_inst[module_id].sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
|
||||
fcfg = NR_UE_rrc_inst[module_id].sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0];
|
||||
DevAssert(fcfg);
|
||||
|
||||
NR_SL_SSB_TimeAllocation_r16_t *sl_SSB_TimeAllocation = NULL;
|
||||
|
||||
//Current implementation only supports one SSB Timeallocation
|
||||
//Extend RRC to use multiple SSB Time allocations TBD....
|
||||
if (fcfg->sl_SyncConfigList_r16)
|
||||
sl_SSB_TimeAllocation = fcfg->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation1_r16;
|
||||
DevAssert(sl_SSB_TimeAllocation);
|
||||
|
||||
nr_rrc_mac_config_req_sl_mib(module_id,
|
||||
sl_SSB_TimeAllocation,
|
||||
rx_slss_id,
|
||||
pduP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//For Sidelink mode 2 operation this prepares the sidelink preconfiguration
|
||||
void init_sidelink(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
|
||||
42
openair2/RRC/NR_UE/rrc_vars.h
Normal file
42
openair2/RRC/NR_UE/rrc_vars.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* \file vars.h
|
||||
* \brief RRC layer variables
|
||||
* \author R. Knopp, K.H. HSU
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom / NTUST
|
||||
* \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __OPENAIR_NR_RRC_VARS_H__
|
||||
#define __OPENAIR_NR_RRC_VARS_H__
|
||||
|
||||
#include "rrc_defs.h"
|
||||
|
||||
extern NR_UE_RRC_INST_t *NR_UE_rrc_inst;
|
||||
extern uint16_t ue_id_g;
|
||||
|
||||
#endif
|
||||
@@ -74,9 +74,26 @@
|
||||
#define SL_CONFIG_STRING_RESPOOL_SUBCH_START_RB "sl_StartRB_Subchannel"
|
||||
#define SL_CONFIG_STRING_RESPOOL_NUM_RBS "sl_RB_Number"
|
||||
#define SL_CONFIG_STRING_RESPOOL_NUM_SUBCHS "sl_NumSubchannel"
|
||||
#define SL_CONFIG_STRING_RESPOOL_PSFCH_PERIOD "sl_PSFCH_Period"
|
||||
#define SL_CONFIG_STRING_RESPOOL_PSFCH_RB_SET "sl_PSFCH_RB_Set"
|
||||
#define SL_CONFIG_STRING_RESPOOL_PSFCH_NUMMUXCS_PAIR "sl_NumMuxCS_Pair"
|
||||
#define SL_CONFIG_STRING_RESPOOL_PSFCH_MINTIMEGAP "sl_MinTimeGapPSFCH"
|
||||
#define SL_CONFIG_STRING_RESPOOL_PSFCH_HOPID "sl_PSFCH_HopID"
|
||||
#define SL_CONFIG_STRING_RESPOOL_PSFCH_CANDIDATERESOURCETYPE "sl_PSFCH_CandidateResourceType"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_PRIORITY "sl_Priority"
|
||||
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_PARAMS_LIST "rsrc_selection_params"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_SELECTION_WINDOW "sl_SelectionWindow"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_SENSING_WINDOW "sl_SensingWindow"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_TRESHOLD_RSRP "sl_Thres_RSRP"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_MAXNUM_PER_RESERVE "sl_MaxNumPerReserve"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_RESOURCE_RESERVED_PERIOD "sl_ResourceReservePeriod"
|
||||
#define SL_CONFIG_STRING_RSRC_SEL_RS_FOR_SENSING "sl_RS_ForSensing"
|
||||
|
||||
|
||||
#define SL_CONFIG_STRING_UEINFO "sl_UEINFO"
|
||||
#define SL_CONFIG_STRING_UEINFO_SRCID "srcid"
|
||||
#define SL_CONFIG_STRING_UEINFO_IPV4ADDR_THIRD_OCTET "thirdOctet"
|
||||
#define SL_CONFIG_STRING_UEINFO_IPV4ADDR_FOURTH_OCTET "fourthOctet"
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* Sidelink Frequency common Cell Config parameters */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
@@ -148,11 +165,35 @@
|
||||
*/
|
||||
#define SL_RESPOOLPARAMS_DESC(sl_res_pool) { \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSCCH_NUMSYM,NULL,0,.i64ptr=sl_res_pool->sl_PSCCH_Config_r16->choice.setup->sl_TimeResourcePSCCH_r16,.defint64val=1,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSCCH_NUMRBS,NULL,0,.i64ptr=sl_res_pool->sl_PSCCH_Config_r16->choice.setup->sl_FreqResourcePSCCH_r16,.defint64val=4,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSCCH_NUMRBS,NULL,0,.i64ptr=sl_res_pool->sl_PSCCH_Config_r16->choice.setup->sl_FreqResourcePSCCH_r16,.defint64val=1,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_SUBCH_SIZE_IN_RBS,NULL,0,.i64ptr=sl_res_pool->sl_SubchannelSize_r16,.defint64val=0,TYPE_INT64,0},\
|
||||
{SL_CONFIG_STRING_RESPOOL_SUBCH_START_RB,NULL,0,.i64ptr=sl_res_pool->sl_StartRB_Subchannel_r16,.defint64val=0,TYPE_INT64,0},\
|
||||
{SL_CONFIG_STRING_RESPOOL_NUM_RBS,NULL,0,.i64ptr=sl_res_pool->sl_RB_Number_r16,.defint64val=106,TYPE_INT64,0},\
|
||||
{SL_CONFIG_STRING_RESPOOL_NUM_SUBCHS,NULL,0,.i64ptr=sl_res_pool->sl_NumSubchannel_r16,.defint64val=10,TYPE_INT64,0}}
|
||||
{SL_CONFIG_STRING_RESPOOL_NUM_SUBCHS,NULL,0,.i64ptr=sl_res_pool->sl_NumSubchannel_r16,.defint64val=10,TYPE_INT64,0},\
|
||||
{SL_CONFIG_STRING_RESPOOL_PSFCH_PERIOD,NULL,0,.i64ptr=sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16,.defint64val=3,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSFCH_NUMMUXCS_PAIR,NULL,0,.i64ptr=sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_NumMuxCS_Pair_r16,.defint64val=1,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSFCH_MINTIMEGAP,NULL,0,.i64ptr=sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_MinTimeGapPSFCH_r16,.defint64val=1,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSFCH_HOPID,NULL,0,.i64ptr=sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_HopID_r16,.defint64val=1,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RESPOOL_PSFCH_CANDIDATERESOURCETYPE,NULL,0,.i64ptr=sl_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_CandidateResourceType_r16,.defint64val=0,TYPE_INT64,0}}
|
||||
|
||||
#define SL_RSRCSELPARAMS_DESC(sl_rsrc_sel_pool) { \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_PRIORITY,NULL,0,.i64ptr=&sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SelectionWindowList_r16->list.array[0]->sl_Priority_r16,.defint64val=7,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_SELECTION_WINDOW,NULL,0,.i64ptr=&sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SelectionWindowList_r16->list.array[0]->sl_SelectionWindow_r16,.defint64val=5,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_SENSING_WINDOW,NULL,0,.i64ptr=sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_SensingWindow_r16,.defint64val=6,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_TRESHOLD_RSRP,NULL,0,.i64ptr=sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_Thres_RSRP_List_r16->list.array[0],.defint64val=-128,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_MAXNUM_PER_RESERVE,NULL,0,.i64ptr=sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_MaxNumPerReserve_r16,.defint64val=1,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_RESOURCE_RESERVED_PERIOD,NULL,0,.i64ptr=&sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_ResourceReservePeriodList_r16->list.array[0]->choice.sl_ResourceReservePeriod1_r16,.defint64val=100,TYPE_INT64,0}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_RS_FOR_SENSING,NULL,0,.i64ptr=&sl_res_pool->sl_UE_SelectedConfigRP_r16->sl_RS_ForSensing_r16,.defint64val=1,TYPE_INT64,0}}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* Sidelink Top-Level UE Info */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
sl_srcid - 16-bit source ID used for LCID information and indexing in L2 stack
|
||||
sl_ipv4addr - string containing ipv4 address for default SLRB
|
||||
*/
|
||||
#define SL_UEINFO_DESC(sl_ueinfo) { \
|
||||
{SL_CONFIG_STRING_UEINFO_SRCID,NULL,0,.iptr=&ueinfo.srcid,.defintval=1,TYPE_INT,0}, \
|
||||
{SL_CONFIG_STRING_UEINFO_IPV4ADDR_THIRD_OCTET,NULL,0,.iptr=&ueinfo.thirdOctet,.defintval=0,TYPE_INT,0}, \
|
||||
{SL_CONFIG_STRING_UEINFO_IPV4ADDR_FOURTH_OCTET,NULL,0,.iptr=&ueinfo.fourthOctet,.defintval=1,TYPE_INT,0}}
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "nr_sdap.h"
|
||||
#include "nr_sdap_entity.h"
|
||||
#include <openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h>
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
@@ -431,6 +432,7 @@ static void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity,
|
||||
LOG_D(SDAP, "RRC Configuring SDAP Entity\n");
|
||||
for(int i = 0; i < mappedQFIs2AddCount; i++){
|
||||
uint8_t qfi = mapped_qfi_2_add[i];
|
||||
set_qfi_pduid(qfi, 0);
|
||||
/* a default DRB exists and there is no QFI to DRB mapping rule for the QFI */
|
||||
if (existing_sdap_entity->default_drb && existing_sdap_entity->qfi2drb_table[qfi].drb_id == SDAP_NO_MAPPING_RULE) {
|
||||
nr_sdap_ul_hdr_t sdap_ctrl_pdu = existing_sdap_entity->sdap_construct_ctrl_pdu(qfi);
|
||||
@@ -518,8 +520,12 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb,
|
||||
sdap_entity->default_drb = drb_identity;
|
||||
LOG_I(SDAP, "Default DRB for the created SDAP entity: %ld \n", sdap_entity->default_drb);
|
||||
LOG_D(SDAP, "RRC updating mapping rules: %d\n", mappedQFIs2AddCount);
|
||||
for (int i = 0; i < mappedQFIs2AddCount; i++)
|
||||
sdap_entity->qfi2drb_map_update(sdap_entity, mapped_qfi_2_add[i], sdap_entity->default_drb, has_sdap_rx, has_sdap_tx);
|
||||
uint8_t qfi = 0;
|
||||
for (int i = 0; i < mappedQFIs2AddCount; i++) {
|
||||
qfi = (uint8_t)mapped_qfi_2_add[i];
|
||||
set_qfi_pduid(qfi, 0);
|
||||
sdap_entity->qfi2drb_map_update(sdap_entity, qfi, sdap_entity->default_drb, has_sdap_rx, has_sdap_tx);
|
||||
}
|
||||
}
|
||||
|
||||
sdap_entity->next_entity = sdap_info.sdap_entity_llist;
|
||||
|
||||
@@ -188,11 +188,11 @@ void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data,
|
||||
network_record_t record = networks.items[user_plmns->operators.items[i]].record;
|
||||
usim_data->pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG;
|
||||
usim_data->pnn[i].fullname.length = strlen(record.fullname);
|
||||
strncpy((char*) usim_data->pnn[i].fullname.value, record.fullname,
|
||||
memcpy((char*) usim_data->pnn[i].fullname.value, record.fullname,
|
||||
usim_data->pnn[i].fullname.length);
|
||||
usim_data->pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG;
|
||||
usim_data->pnn[i].shortname.length = strlen(record.shortname);
|
||||
strncpy((char*) usim_data->pnn[i].shortname.value, record.shortname,
|
||||
memcpy((char*) usim_data->pnn[i].shortname.value, record.shortname,
|
||||
usim_data->pnn[i].shortname.length);
|
||||
usim_data->opl[i].plmn = record.plmn;
|
||||
usim_data->opl[i].start = record.tac_start;
|
||||
|
||||
154
targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf
Normal file
154
targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf
Normal file
@@ -0,0 +1,154 @@
|
||||
SIDELINK_PRECONFIGURATION = (
|
||||
{
|
||||
# TDD ULDL CONFIG used for sidelink
|
||||
sl_dl_UL_TransmissionPeriodicity = 6;
|
||||
sl_nrofDownlinkSlots = 6;
|
||||
sl_nrofDownlinkSymbols = 0;
|
||||
sl_nrofUplinkSlots = 4;
|
||||
sl_nrofUplinkSymbols = 0;
|
||||
sl_csi_rs = (
|
||||
{
|
||||
symb_l0 = 5;
|
||||
# csi_type 2 is not supported 38211, 8.4.1.5.3
|
||||
csi_Type = 1;
|
||||
sl_powerControlOffset = 1;
|
||||
sl_powerControlOffsetSS = 1;
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
sl_AllowedResourceSelectionConfig = 3; // Supported only {0, 3, 4, 6}
|
||||
|
||||
sl_FrequencyCommonConfig = (
|
||||
{
|
||||
sl_offstToCarrier = 0;
|
||||
sl_subcarrierSpacing = 1;//0-15Khz, 1-30Khz
|
||||
sl_carrierBandwidth = 106;//numPRBs
|
||||
#NR bands for Sidelink n47, n38. N47 - 5855Mhz - 5925Mhz
|
||||
#SL SSB chosen to be located from RB10 to RB21. points to the middle of the SSB block.
|
||||
#SSB location should be within Sidelink BWP
|
||||
# this is 2584.95 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
sl_absoluteFrequencySSB = 516990;
|
||||
# this is 2575.92 MHz (center frequency is 2585.1 MHz
|
||||
sl_absoluteFrequencyPointA = 515184;
|
||||
}
|
||||
);
|
||||
|
||||
sl_BWP = (
|
||||
{
|
||||
#RB start 0, RB size = 106. occupies complete Bw.
|
||||
sl_locationAndBandwidth = 28875;
|
||||
# Num Symbols used for Sidelink in an uplink slot
|
||||
# Herein, sl_LengthSymbols represents an index; not the number of symbols.
|
||||
# This index value can be from 0 to 7 representing the (7 to 14 symbols)
|
||||
sl_LengthSymbols = 7;
|
||||
#Sidelink Starting symbol in a slot
|
||||
#Value can be between symbols 0 to 7
|
||||
sl_StartSymbol = 0;
|
||||
}
|
||||
);
|
||||
|
||||
sl_syncCfg = (
|
||||
{
|
||||
#NUM SL-SSB within 16 frames
|
||||
sl_NumSSB_WithinPeriod_0 = 4;
|
||||
#Slot Offset for the first txn in the 16 frame period
|
||||
sl_TimeOffsetSSB_0 = 8;
|
||||
#interval in slots for repetition of SL-SSB
|
||||
sl_TimeInterval_0 = 120;
|
||||
}
|
||||
);
|
||||
|
||||
sl_ConfiguredGrantConfig = (
|
||||
{
|
||||
sl_NrOfHARQ_Processes = 16;
|
||||
sl_HARQ_ProcID_offset = 0;
|
||||
sl_periodic_rsc_rsr_interval = 100;
|
||||
}
|
||||
);
|
||||
sl_RxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//10RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
sl_TxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//50RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
rsrc_selection_params = (
|
||||
{
|
||||
# Resource selection parameters
|
||||
sl_SelectionWindow = 5; // n1, n5, n10, n20}
|
||||
sl_Thres_RSRP = 0; // (-128 + (n-1)*2) dBm n is 0..66
|
||||
sl_MaxNumPerReserve = 0; // n2, n3
|
||||
sl_SensingWindow = 100; // {ms100, ms1100}
|
||||
sl_ResourceReservePeriod = 100; //{ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}
|
||||
sl_RS_ForSensing = 0; // 0 pscch, 1 pssch
|
||||
}
|
||||
);
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 0;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
155
targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf
Normal file
155
targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf
Normal file
@@ -0,0 +1,155 @@
|
||||
SIDELINK_PRECONFIGURATION = (
|
||||
{
|
||||
# TDD ULDL CONFIG used for sidelink
|
||||
sl_dl_UL_TransmissionPeriodicity = 6;
|
||||
sl_nrofDownlinkSlots = 6;
|
||||
sl_nrofDownlinkSymbols = 0;
|
||||
sl_nrofUplinkSlots = 4;
|
||||
sl_nrofUplinkSymbols = 0;
|
||||
sl_csi_rs = (
|
||||
{
|
||||
symb_l0 = 5;
|
||||
# csi_type 2 is not supported 38211, 8.4.1.5.3
|
||||
csi_Type = 1;
|
||||
sl_powerControlOffset = 1;
|
||||
sl_powerControlOffsetSS = 1;
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
sl_AllowedResourceSelectionConfig = 3; // Supported only {0, 3, 4, 6}
|
||||
|
||||
sl_FrequencyCommonConfig = (
|
||||
{
|
||||
sl_offstToCarrier = 0;
|
||||
sl_subcarrierSpacing = 1;//0-15Khz, 1-30Khz
|
||||
sl_carrierBandwidth = 106;//numPRBs
|
||||
#NR bands for Sidelink n47, n38. N47 - 5855Mhz - 5925Mhz
|
||||
#SL SSB chosen to be located from RB10 to RB21. points to the middle of the SSB block.
|
||||
#SSB location should be within Sidelink BWP
|
||||
# this is 2584.95 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
sl_absoluteFrequencySSB = 516990;
|
||||
# this is 2575.92 MHz (center frequency is 2585.1 MHz
|
||||
sl_absoluteFrequencyPointA = 515184;
|
||||
}
|
||||
);
|
||||
|
||||
sl_BWP = (
|
||||
{
|
||||
#RB start 0, RB size = 106. occupies complete Bw.
|
||||
sl_locationAndBandwidth = 28875;
|
||||
# Num Symbols used for Sidelink in an uplink slot
|
||||
# Herein, sl_LengthSymbols represents an index; not the number of symbols.
|
||||
# This index value can be from 0 to 7 representing the (7 to 14 symbols)
|
||||
sl_LengthSymbols = 7;
|
||||
#Sidelink Starting symbol in a slot
|
||||
#Value can be between symbols 0 to 7
|
||||
sl_StartSymbol = 0;
|
||||
}
|
||||
);
|
||||
|
||||
sl_syncCfg = (
|
||||
{
|
||||
#NUM SL-SSB within 16 frames
|
||||
sl_NumSSB_WithinPeriod_0 = 4;
|
||||
#Slot Offset for the first txn in the 16 frame period
|
||||
sl_TimeOffsetSSB_0 = 8;
|
||||
#interval in slots for repetition of SL-SSB
|
||||
sl_TimeInterval_0 = 120;
|
||||
}
|
||||
);
|
||||
sl_ConfiguredGrantConfig = (
|
||||
{
|
||||
sl_NrOfHARQ_Processes = 16;
|
||||
sl_HARQ_ProcID_offset = 0;
|
||||
sl_periodic_rsc_rsr_interval = 100;
|
||||
}
|
||||
);
|
||||
sl_RxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//10RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
sl_TxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//50RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
rsrc_selection_params = (
|
||||
{
|
||||
# Resource selection parameters
|
||||
# sl_Priority = 1;
|
||||
sl_SelectionWindow = 5; // n1, n5, n10, n20} {1,5,10,20}*2^μ
|
||||
sl_Thres_RSRP = 0; // (-128 + (n-1)*2) dBm n is 0..66
|
||||
sl_MaxNumPerReserve = 0; // n2, n3
|
||||
sl_SensingWindow = 100; // {ms100, ms1100}
|
||||
sl_ResourceReservePeriod = 100; //{ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}
|
||||
sl_RS_ForSensing = 0; // 0 pscch, 1 pssch
|
||||
}
|
||||
);
|
||||
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 1;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 2;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user