Compare commits

...

26 Commits

Author SHA1 Message Date
Raymond Knopp
435bbc1abe resolved missing function that were removed (get_first_ul_slot()) but used for SL 2025-02-12 01:53:16 +01:00
Raymond Knopp
77b7fd6255 Merge branch 'sl-eurecom2-rebase' of https://gitlab.eurecom.fr/oai/openairinterface5g into sl-eurecom2-rebase 2025-02-12 01:27:19 +01:00
Raymond Knopp
075482e673 Merge remote-tracking branch 'origin/develop' into sl-eurecom2-rebase 2025-02-10 21:08:59 +01:00
David Kim
02919e9fa6 Fixed a bug related to calling sequence of nr_ue_sidelink_scheduler.
In case of valid rx_ind, we do not call nr_ue_sidelink_scheduler.
2025-02-07 12:25:57 -08:00
David Kim
a2760cdeac Added log and AssertFatal to make sure timing acquitision in Nearby UE. 2025-02-04 17:17:32 -08:00
David Kim
32b2398b02 Added a condition to fix segment fault in sl schedule rx action. 2025-02-03 14:39:37 -08:00
Ejaz Ahmed
cf0e037708 Added sidelink configurations for sync-ref UE and nearby UE 2025-01-30 16:58:52 -08:00
Ejaz Ahmed
73e3abed4e Fixed sub-channel index 2025-01-30 16:54:06 -08:00
Ejaz Ahmed
ffad2609dd Addressed edge cases of frame number for sensing window
Following changes are made:

1) Fix bug related to the edge case of frame number
2025-01-30 16:45:27 -08:00
Ejaz Ahmed
4854f772b5 Updated sync_source assignment; Passed FR1 as argument 2025-01-30 16:42:38 -08:00
Ejaz Ahmed
78fc85c2f3 Implemented handling of sci1, sci2 & SLSCH at receiver 2025-01-28 13:10:37 -08:00
Ejaz Ahmed
bc94bd04f0 Updating tdd configuration code for SL NR UE 2025-01-27 12:16:49 -08:00
Ejaz Ahmed
61ea4c4ec3 Integrated our Tx sidelink scheduler code into develop branch
Following updates are included in this commit:

1) Updated CMakeLists.txt to include sidelink files
2) Included resource selection code
3) Integrated our sidelink_scheduler code into the corresponding function of develop branch
4) Moved functions from nr_ue_scheduler.c to nr_ue_scheduler_sl.c
5) Fixed warnings
2025-01-24 12:05:28 -08:00
Ejaz Ahmed
e67fb077ad Included functions for resource sensing/selection, CSI reporting and PSFCH
Following changes are included in this commit:
1) Initialized sensing window/candidate resources related lists
2) Sensing window/resource selection related functions
3) CSI report related function definitions
4) PSFCH params tx and rx configuration functions
5) Sidelink harq functions
2025-01-22 18:47:07 -08:00
Ejaz Ahmed
3ad16c4071 Fixed multiple nr_bler_data definitions; Removed NDEBUG warnings 2025-01-22 10:57:51 -08:00
David Kim
75695da903 Data path update on RRC, NR_RLC, NR_PDCP, and SDAP layers related to Sidelink.
1. Preconfiguration setting in RRC layer
2. Data handling in RLC and PDCP layers.
3. qfi setting in SDAP layer.
4. Adding IP traffic types in COMMON.
2025-01-21 23:15:27 -08:00
David Kim
63da9c4794 Further update related to ueinfo up to rrc layer. 2025-01-21 22:37:13 -08:00
Ejaz Ahmed
62a594e137 Added basic Resource selection, Included CSI-RS configurations
Following features are included:
1) Added CSI-RS configuration support, functions and related structure
2) Included fundamental code for resource sensing
2025-01-21 18:39:26 -08:00
Ejaz Ahmed
e962382498 Moved NR_list_t funcs declarations to nr mac common header file 2025-01-21 14:52:55 -08:00
Ejaz Ahmed
e698bb284f Added MACROs definitions for different SL_SCH_LCIDs and SLSCH subheader 2025-01-21 14:06:57 -08:00
Ejaz Ahmed
56f8fa77bc Added config pdu structures 2025-01-21 13:58:52 -08:00
Ejaz Ahmed
9369728b3d Added code for configuring/processing/sending indications of sci1&sci2
Following functions are included:
1) nr_sci_size()
2) get_nREDMRS()
3) get_nRECSI_RS()
4) convNRFRIV()
5) get_NREsci2()
6) fill_pssch_pscch_pdu()
7) config_pscch_pdu_rx()
8) extract_pscch_pdu()
9) config_pssch_slsch_pdu_rx()
10) config_pssch_sci_pdu_rx()
11) nr_ue_process_sci2_indication_pdu()
12) extract_pssch_sci_pdu()
2025-01-21 13:16:08 -08:00
Ejaz Ahmed
d3e501c827 Moved NR_List_t; Added SL/SCI structures; Updated SL_ResourcePool
Following modifications are included:
1) Moved NR_list_t and related function to nr_mac_common file
2) Added SL and SCI structures
3) Implemented SL SCHED LOCK code
4) Included SL_ResourcePool members
5) Added dump_mac_stats_sl function
2025-01-21 11:14:56 -08:00
Ejaz Ahmed
e161d2c9ae Moved bler and cqi related structures and functions from gNB to nr_mac_common files 2025-01-21 09:44:59 -08:00
Ejaz Ahmed
23e74c5c8c Added command line argument support for sync-ref, mcs and snr 2025-01-21 08:57:16 -08:00
Ejaz Ahmed
b77a6f202d Added ueinfo for configuring UE info; Fixed MALLOC warnings 2025-01-20 13:47:29 -08:00
55 changed files with 7069 additions and 526 deletions

View File

@@ -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
)

View File

@@ -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 {

View File

@@ -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
View 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"

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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 // 419 Identity of the logical channel
#define SL_SCH_LCID_20_55 20 // 2055 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__ */

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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;
}

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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,

View File

@@ -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)
{

View File

@@ -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,

View File

@@ -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__*/

View File

@@ -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;

View File

@@ -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];
}

View File

@@ -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_ */

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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)
{

View 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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View 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;
}
);
}
);

View 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;
}
);
}
);