mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
324 Commits
simple-sta
...
sl-eurecom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71056006a9 | ||
|
|
47cf9df46f | ||
|
|
3339aa0fac | ||
|
|
acfba637cf | ||
|
|
9c9e34d206 | ||
|
|
5559b17fe1 | ||
|
|
88dfcc8722 | ||
|
|
3cc086821f | ||
|
|
a8b4080383 | ||
|
|
a32aba4ec5 | ||
|
|
41552c0ea8 | ||
|
|
762e68c327 | ||
|
|
737155131b | ||
|
|
75cf67dcf2 | ||
|
|
ad2c7372e0 | ||
|
|
65f3dd803f | ||
|
|
f1ee81c22e | ||
|
|
56898c81d3 | ||
|
|
9b37a05a71 | ||
|
|
b960ede044 | ||
|
|
a60aa4250a | ||
|
|
6bdcac9e0b | ||
|
|
50892fa07f | ||
|
|
6cb94c69bd | ||
|
|
f44aa9b86e | ||
|
|
336db01213 | ||
|
|
a6a6fe043e | ||
|
|
41fc98eda5 | ||
|
|
230ebaea70 | ||
|
|
87348885b4 | ||
|
|
9b60e7f4ec | ||
|
|
ea14ae4a15 | ||
|
|
8c8408ba8f | ||
|
|
c8ec792c3e | ||
|
|
c9486cb4f8 | ||
|
|
30cb74b96c | ||
|
|
c608abe8a1 | ||
|
|
5831ceada3 | ||
|
|
174e39b417 | ||
|
|
6ee1ed99a0 | ||
|
|
e766185363 | ||
|
|
7dbe690dcf | ||
|
|
b7e443a2ed | ||
|
|
95c143657f | ||
|
|
98ea7cf8a8 | ||
|
|
817aeb6e1b | ||
|
|
aaccfe4beb | ||
|
|
3cdd8e2221 | ||
|
|
2b6e7e105e | ||
|
|
39fb255189 | ||
|
|
e9dd1d9bf0 | ||
|
|
3bf811e903 | ||
|
|
3782926ae5 | ||
|
|
6ced256931 | ||
|
|
e5f6ec76ec | ||
|
|
c3b314ab67 | ||
|
|
16bd6d4421 | ||
|
|
6e00505f98 | ||
|
|
bb792807ab | ||
|
|
852d0dc2b9 | ||
|
|
1f47719f95 | ||
|
|
383a573665 | ||
|
|
a376968ba4 | ||
|
|
7f7c343856 | ||
|
|
98ae1a296a | ||
|
|
9bab4005fe | ||
|
|
e2746c9e62 | ||
|
|
20ae13fa41 | ||
|
|
3b520e933b | ||
|
|
e214756682 | ||
|
|
fb5e590d44 | ||
|
|
bde50f2e63 | ||
|
|
55042e7b9f | ||
|
|
2fd7150702 | ||
|
|
74adc9eeb5 | ||
|
|
419eb6c81f | ||
|
|
6873c38471 | ||
|
|
70d1e6e52c | ||
|
|
8216cbf79a | ||
|
|
bd210f9961 | ||
|
|
c23170f895 | ||
|
|
ecc78c1bea | ||
|
|
aa57104123 | ||
|
|
d09522d616 | ||
|
|
a522b2dcb5 | ||
|
|
c53d66f140 | ||
|
|
c8b84b8e50 | ||
|
|
47a94020cd | ||
|
|
95b9990ef5 | ||
|
|
16f75be9fd | ||
|
|
aed1eb1841 | ||
|
|
f5511fec98 | ||
|
|
5db24ade57 | ||
|
|
171ba6f765 | ||
|
|
d6dc49bc4a | ||
|
|
302b64cc07 | ||
|
|
19d1eb25ba | ||
|
|
0bcbc7401c | ||
|
|
d56d68332e | ||
|
|
4600b1bba6 | ||
|
|
c282e8700a | ||
|
|
5314c750e8 | ||
|
|
6e708111d9 | ||
|
|
fd2ac5a881 | ||
|
|
8fdc275c98 | ||
|
|
ae692d25ac | ||
|
|
1d3b40a602 | ||
|
|
e4508b1d01 | ||
|
|
a2184d2430 | ||
|
|
3645c75ba8 | ||
|
|
88032eaa6f | ||
|
|
eb7214ed1e | ||
|
|
9ebfc7df80 | ||
|
|
c5dd477299 | ||
|
|
de8bde2eb1 | ||
|
|
041a74ad55 | ||
|
|
dd4c1851f3 | ||
|
|
665143e3f6 | ||
|
|
1a904623e1 | ||
|
|
c9e48b8ce9 | ||
|
|
2abf30ad6e | ||
|
|
d37bf06d39 | ||
|
|
eca4d6a572 | ||
|
|
b4b73f2dea | ||
|
|
bc316b1cec | ||
|
|
0ff70cc496 | ||
|
|
816bfec661 | ||
|
|
e8afaa8cca | ||
|
|
f94fe2ac80 | ||
|
|
b1d76e157c | ||
|
|
eea92750b0 | ||
|
|
3743e20f87 | ||
|
|
497858ef37 | ||
|
|
c56f246dd1 | ||
|
|
0fae27e94c | ||
|
|
e12bf1500d | ||
|
|
ba90296301 | ||
|
|
9530eefa24 | ||
|
|
ea4ed2abd8 | ||
|
|
aab3fd92f2 | ||
|
|
31985289a2 | ||
|
|
2c686dd805 | ||
|
|
368a599dc7 | ||
|
|
8ab77553ad | ||
|
|
0788a62aaf | ||
|
|
865df9eea6 | ||
|
|
4aa058efd8 | ||
|
|
0aa31e7af2 | ||
|
|
4c065efd22 | ||
|
|
2e5c6f7d8d | ||
|
|
bb3fb6cbd0 | ||
|
|
b6f04e3ccf | ||
|
|
92340ebd77 | ||
|
|
8c9588739f | ||
|
|
42112e849d | ||
|
|
c40d0d1cb1 | ||
|
|
a1ec6c9ba2 | ||
|
|
bcc632dbdd | ||
|
|
a7f3cd98ec | ||
|
|
16f63c749d | ||
|
|
7e8d791010 | ||
|
|
7ed097874a | ||
|
|
06bccb4087 | ||
|
|
f41b149a58 | ||
|
|
5f829ddb35 | ||
|
|
59a69b5020 | ||
|
|
0845154ef8 | ||
|
|
34d2c4d917 | ||
|
|
9c6c8366af | ||
|
|
d9ede841a1 | ||
|
|
47dc503ca6 | ||
|
|
2516b5b3f1 | ||
|
|
e6e925f9ab | ||
|
|
105f2b57ef | ||
|
|
848e380cd0 | ||
|
|
1cacd66352 | ||
|
|
286ef21839 | ||
|
|
e88f0f5539 | ||
|
|
b1d830adc2 | ||
|
|
36a29714ff | ||
|
|
9fd148dedd | ||
|
|
378e6f5643 | ||
|
|
15f8f5aeea | ||
|
|
f776b88d7f | ||
|
|
ea9289b2de | ||
|
|
30ce40cf03 | ||
|
|
23300df806 | ||
|
|
d9acb85bfa | ||
|
|
ec7b44e6dd | ||
|
|
076c83b6f2 | ||
|
|
616f759661 | ||
|
|
61e62abb7f | ||
|
|
281dc32c26 | ||
|
|
bb35caebed | ||
|
|
1ff86924ff | ||
|
|
e13e26759e | ||
|
|
9588e10de0 | ||
|
|
885d5cd426 | ||
|
|
6536425c4b | ||
|
|
c7e08dffbe | ||
|
|
d2475e0dd6 | ||
|
|
c584baf9e1 | ||
|
|
6fcda3dcc0 | ||
|
|
3e81184deb | ||
|
|
4e2b8ddb92 | ||
|
|
e8ca12049a | ||
|
|
e9ff59611d | ||
|
|
fb6baf3f76 | ||
|
|
18e9694f31 | ||
|
|
183e029c8c | ||
|
|
da97a8f016 | ||
|
|
1a470d5af6 | ||
|
|
c4250dcd2b | ||
|
|
4c4a667fd6 | ||
|
|
da6f3251f3 | ||
|
|
c534570eec | ||
|
|
9642a70e6d | ||
|
|
1c84699e00 | ||
|
|
9d8db83ebd | ||
|
|
9ceb3ddf93 | ||
|
|
289991b0fe | ||
|
|
38a43f3be6 | ||
|
|
6fc72eae0f | ||
|
|
14420f24cb | ||
|
|
53aa746075 | ||
|
|
4e10e4fa2c | ||
|
|
9879c13cd4 | ||
|
|
63454cebf8 | ||
|
|
813b600305 | ||
|
|
9f9dadf621 | ||
|
|
bb13bfa195 | ||
|
|
ee7244ca05 | ||
|
|
05604174e0 | ||
|
|
cbcd09cbca | ||
|
|
4af8be50bd | ||
|
|
ef9f804da7 | ||
|
|
a465e39bb9 | ||
|
|
3370570ecd | ||
|
|
29b74e7410 | ||
|
|
3fa03965a1 | ||
|
|
d7b1a78e71 | ||
|
|
a2e75e10d3 | ||
|
|
714629c26f | ||
|
|
9e686e448d | ||
|
|
5a88bb670a | ||
|
|
b4a314b64e | ||
|
|
6be609a59f | ||
|
|
69c357655e | ||
|
|
45dd2a7fb0 | ||
|
|
b5dd8de98f | ||
|
|
a42a4d1a06 | ||
|
|
3c485239ba | ||
|
|
14b972e878 | ||
|
|
aff9391806 | ||
|
|
c734cfab93 | ||
|
|
3dd8395c8f | ||
|
|
99a750d672 | ||
|
|
82dfb5c4ec | ||
|
|
7fd180f30b | ||
|
|
f52f258eec | ||
|
|
fdad2f7d17 | ||
|
|
1245c05385 | ||
|
|
e534761719 | ||
|
|
2976628409 | ||
|
|
34aede6ee5 | ||
|
|
d2bbbb16ad | ||
|
|
7e83f75d21 | ||
|
|
c4706eda69 | ||
|
|
28f2129d3e | ||
|
|
238a7837cf | ||
|
|
e474090459 | ||
|
|
6f5205ec1c | ||
|
|
f5250c1ec4 | ||
|
|
156b806abb | ||
|
|
d4e030cc3b | ||
|
|
cb17a2530c | ||
|
|
907130d999 | ||
|
|
d201d89c94 | ||
|
|
5cc6d9e5c3 | ||
|
|
1a815f7e15 | ||
|
|
05cb48d29c | ||
|
|
911bd2be5d | ||
|
|
5ea68eb132 | ||
|
|
94188666ce | ||
|
|
a6d86ea8c9 | ||
|
|
d3702751ec | ||
|
|
63b3d8a92f | ||
|
|
597c897977 | ||
|
|
d1bbbb5dd3 | ||
|
|
18853ab6cc | ||
|
|
9cc948635c | ||
|
|
93d4a07932 | ||
|
|
6bfe76b086 | ||
|
|
e568b2c85a | ||
|
|
435b636d89 | ||
|
|
84504a38a0 | ||
|
|
4bd3007565 | ||
|
|
dad4240016 | ||
|
|
2cda03b016 | ||
|
|
198c319788 | ||
|
|
18d720f377 | ||
|
|
ba6a8554a3 | ||
|
|
ffda9c758a | ||
|
|
60a7eb326c | ||
|
|
6a5a9f18bf | ||
|
|
4bf5166aed | ||
|
|
d4e30b972b | ||
|
|
858a13119b | ||
|
|
5b16b58496 | ||
|
|
0588003034 | ||
|
|
b8d9da2e81 | ||
|
|
8199a1e093 | ||
|
|
7efe5880a1 | ||
|
|
b9caf3ecc4 | ||
|
|
4ca508228f | ||
|
|
9ecd473a41 | ||
|
|
f32c759ecf | ||
|
|
88b6cdd209 | ||
|
|
8bb2f3991b | ||
|
|
4d369a6993 | ||
|
|
70f586cb3c | ||
|
|
745cc733ea | ||
|
|
ee7aacf2ca | ||
|
|
fef6303cc9 |
@@ -980,6 +980,8 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
@@ -1253,7 +1255,10 @@ 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_scheduler_sl_v2x.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_sci_slsch.c
|
||||
${NR_UE_MAC_DIR}/nr_slsch_scheduler.c
|
||||
)
|
||||
|
||||
set (ENB_APP_SRC
|
||||
|
||||
8
common/utils/colors.h
Normal file
8
common/utils/colors.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "common/utils/assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "nr_common.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <simde/x86/gfni.h>
|
||||
|
||||
@@ -970,8 +970,35 @@ void *UE_thread(void *arg)
|
||||
curMsg.proc.frame_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
if (UE->received_config_request) {
|
||||
if (UE->sl_mode) {
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
|
||||
uint8_t pool_id = 0;
|
||||
|
||||
// Temporarily setting this to this initial NON_NR_SIDELINK_SLOT slot type.
|
||||
// Later we should properly determine if the current slot is an NR_DOWNLINK_SLOT, NR_UPLINK_SLOT, or NR_MIXED_SLOT
|
||||
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD);
|
||||
curMsg.proc.tx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_tx, TDD);
|
||||
|
||||
SL_ResourcePool_params_t *sl_tx_rsrc_pool = mac->SL_MAC_PARAMS->sl_TxPool[pool_id];
|
||||
uint16_t phy_map_sz_tx = ((sl_tx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_tx_rsrc_pool->phy_sl_bitmap.bits_unused);
|
||||
bool sl_tx_slot = is_sl_slot(mac, &sl_tx_rsrc_pool->phy_sl_bitmap, phy_map_sz_tx, absolute_slot + duration_rx_to_tx);
|
||||
if (sl_tx_slot) {
|
||||
frameslot_t frame_slot_tx;
|
||||
frame_slot_tx.frame = curMsg.proc.frame_tx;
|
||||
frame_slot_tx.slot = curMsg.proc.nr_slot_tx;
|
||||
validate_selected_sl_slot(mac, true, false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_tx);
|
||||
curMsg.proc.tx_slot_type = NR_SIDELINK_SLOT;
|
||||
}
|
||||
|
||||
SL_ResourcePool_params_t *sl_rx_rsrc_pool = mac->SL_MAC_PARAMS->sl_RxPool[pool_id];
|
||||
uint16_t phy_map_sz_rx = ((sl_rx_rsrc_pool->phy_sl_bitmap.size << 3) - sl_rx_rsrc_pool->phy_sl_bitmap.bits_unused);
|
||||
bool sl_rx_slot = is_sl_slot(mac, &sl_rx_rsrc_pool->phy_sl_bitmap, phy_map_sz_rx, absolute_slot);
|
||||
if (sl_rx_slot) {
|
||||
frameslot_t frame_slot_rx;
|
||||
frame_slot_rx.frame = curMsg.proc.frame_rx;
|
||||
frame_slot_rx.slot = curMsg.proc.nr_slot_rx;
|
||||
validate_selected_sl_slot(mac, false, true, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_rx);
|
||||
curMsg.proc.rx_slot_type = NR_SIDELINK_SLOT;
|
||||
}
|
||||
} else {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_tx);
|
||||
@@ -1095,11 +1122,11 @@ 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)
|
||||
{
|
||||
for (int instance_id = 0; instance_id < nb_inst; instance_id++) {
|
||||
NR_UE_RRC_INST_t* rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx);
|
||||
NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id);
|
||||
NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id, ueinfo);
|
||||
|
||||
nr_rrc_set_mac_queue(instance_id, &mac->input_nf);
|
||||
mac->if_module = nr_ue_if_module_init(instance_id);
|
||||
@@ -1109,7 +1136,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
|
||||
nr_rlc_activate_srb0(mac->crnti, NULL, send_srb0_rrc);
|
||||
}
|
||||
//TODO: Move this call to RRC
|
||||
start_sidelink(instance_id);
|
||||
start_sidelink(instance_id, ueinfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "nr_nas_msg.h"
|
||||
#include <openair1/PHY/MODULATION/nr_modulation.h>
|
||||
#include "openair2/GNB_APP/gnb_paramdef.h"
|
||||
#include "openair2/RRC/NR_UE/sl_preconfig_paramvalues.h"
|
||||
#include "actor.h"
|
||||
|
||||
THREAD_STRUCT thread_struct;
|
||||
@@ -380,7 +381,16 @@ int main(int argc, char **argv)
|
||||
nr_pdcp_layer_init();
|
||||
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);
|
||||
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);
|
||||
|
||||
init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file, &ueinfo);
|
||||
|
||||
// start time manager with some reasonable default for the running mode
|
||||
// (may be overwritten in configuration file or command line)
|
||||
@@ -530,4 +540,3 @@ int main(int argc, char **argv)
|
||||
free(pckg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
extern int NB_UE_INST;
|
||||
extern uint16_t ue_id_g;
|
||||
|
||||
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"
|
||||
@@ -26,8 +32,11 @@ extern uint16_t ue_id_g;
|
||||
#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to disable UL actor framework and do processing inline\n"
|
||||
#define CONFIG_HLP_NUM_DL_ACTORS "Number of DL actors to use. Set to 0 to disable DL actor framework and do processing inline\n"
|
||||
#define CONFIG_HLP_EXTRA_PDU_ID "ID of an additional PDU session to configure alongside default PDU session\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"
|
||||
|
||||
/***************************************************************************************************************************************/
|
||||
/*********************SL_UE_iterator******************************************************************************************************************/
|
||||
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
|
||||
when calling config_get or config_getlist functions */
|
||||
|
||||
@@ -39,6 +48,8 @@ extern uint16_t ue_id_g;
|
||||
#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 */
|
||||
@@ -84,6 +95,9 @@ extern uint16_t ue_id_g;
|
||||
{"num-ul-actors", CONFIG_HLP_NUM_UL_ACTORS, 0, .iptr=&nrUE_params.num_ul_actors, .defintval=2, TYPE_INT, 0}, \
|
||||
{"num-dl-actors", CONFIG_HLP_NUM_DL_ACTORS, 0, .iptr=&nrUE_params.num_dl_actors, .defintval=4, TYPE_INT, 0}, \
|
||||
{"extra-pdu-id", CONFIG_HLP_EXTRA_PDU_ID, 0, .iptr=&nrUE_params.extra_pdu_id, .defintval=-1, 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
|
||||
|
||||
@@ -126,6 +140,9 @@ typedef struct {
|
||||
int num_ul_actors;
|
||||
int num_dl_actors;
|
||||
int extra_pdu_id;
|
||||
uint32_t sync_ref;
|
||||
uint8_t mcs;
|
||||
double snr;
|
||||
} nrUE_params_t;
|
||||
extern uint64_t get_nrUE_optmask(void);
|
||||
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
||||
@@ -135,7 +152,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 *UE_thread(void *arg);
|
||||
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id);
|
||||
|
||||
@@ -124,6 +124,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint8_t harq_pid;
|
||||
uint8_t ack_nack;
|
||||
uint8_t *ack_nack_rcvd;
|
||||
uint8_t num_acks_rcvd;
|
||||
uint32_t pdu_length;
|
||||
uint8_t* pdu;
|
||||
} fapi_nr_pdsch_pdu_t;
|
||||
|
||||
@@ -5,11 +5,30 @@
|
||||
|
||||
#define SL_NR_RX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_TX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_RX_IND_MAX_PDU 1
|
||||
#define SL_NR_RX_IND_MAX_PDU 2
|
||||
#define SL_NR_SCI_IND_MAX_PDU 2
|
||||
#define SL_NR_MAX_PSCCH_SCI_LENGTH_IN_BYTES 8
|
||||
#define SL_NR_MAX_PSSCH_SCI_LENGTH_IN_BYTES 8
|
||||
#define SL_NR_MAX_SCI_LENGTH_IN_BYTES 8
|
||||
|
||||
typedef struct sl_nr_tti_csi_rs_pdu {
|
||||
uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4
|
||||
uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended
|
||||
uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274
|
||||
uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276
|
||||
uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP
|
||||
uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18
|
||||
uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter
|
||||
uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13
|
||||
uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12
|
||||
uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4
|
||||
uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three
|
||||
uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023
|
||||
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
|
||||
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
|
||||
uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1
|
||||
} sl_nr_tti_csi_rs_pdu_t;
|
||||
|
||||
typedef enum sl_sci_format_type_enum {
|
||||
SL_SCI_INVALID_FORMAT,
|
||||
SL_SCI_FORMAT_1A_ON_PSCCH,
|
||||
@@ -20,7 +39,8 @@ typedef enum sl_sci_format_type_enum {
|
||||
typedef enum sl_rx_pdu_type_enum {
|
||||
SL_NR_RX_PDU_TYPE_NONE,
|
||||
SL_NR_RX_PDU_TYPE_SSB,
|
||||
SL_NR_RX_PDU_TYPE_SLSCH
|
||||
SL_NR_RX_PDU_TYPE_SLSCH,
|
||||
SL_NR_RX_PDU_TYPE_SLSCH_PSFCH
|
||||
} sl_rx_pdu_type_enum_t;
|
||||
|
||||
//Type of SL-RX CONFIG requests from MAC to PHY
|
||||
@@ -30,6 +50,7 @@ typedef enum sl_nr_rx_config_type_enum {
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SCI,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSFCH,
|
||||
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS,
|
||||
SL_NR_CONFIG_TYPE_RX_MAXIMUM
|
||||
} sl_nr_rx_config_type_enum_t;
|
||||
|
||||
@@ -38,6 +59,7 @@ 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_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
|
||||
@@ -266,14 +310,21 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
|
||||
// Table from SPEC 38.211, Table 8.4.1.1.2-1
|
||||
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 +434,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
|
||||
|
||||
@@ -337,6 +337,10 @@ int check_crc(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type)
|
||||
for (int i=0; i<crc_len; i++)
|
||||
oldcrc |= (decoded_bytes[(n>>3)-crc_len+i])<<((crc_len-1-i)<<3);
|
||||
|
||||
if (oldcrc == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (crc_type) {
|
||||
|
||||
case CRC24_A:
|
||||
|
||||
@@ -274,6 +274,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
}
|
||||
|
||||
ue->init_averaging = 1;
|
||||
|
||||
init_symbol_rotation(fp);
|
||||
init_timeshift_rotation(fp);
|
||||
|
||||
|
||||
@@ -97,6 +97,18 @@ static const int nr_ssb_table[][3] = {
|
||||
{256, 15, nr_ssb_type_A}};
|
||||
|
||||
void set_Lmax(NR_DL_FRAME_PARMS *fp) {
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
int sl_NumSSB_WithinPeriod = 1; //TODO: Needs to be updated from RRC parameters
|
||||
int sl_TimeOffsetSSB = 1; //TODO: Needs to be updated from RRC parameters
|
||||
int sl_TimeInterval = 1; //TODO: Needs to be updated from RRC parameters
|
||||
if ((sl_NumSSB_WithinPeriod == 4) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + 3 * sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME * 2))
|
||||
fp->Lmax = 4;
|
||||
else if ((sl_NumSSB_WithinPeriod == 2) && ((sl_TimeOffsetSSB % fp->slots_per_frame) + sl_TimeInterval < NR_NUMBER_OF_SUBFRAMES_PER_FRAME))
|
||||
fp->Lmax = 2;
|
||||
else
|
||||
fp->Lmax = 1;
|
||||
return;
|
||||
}
|
||||
// definition of Lmax according to ts 38.213 section 4.1
|
||||
if (fp->dl_CarrierFreq < 6e9) {
|
||||
if(fp->frame_type && (fp->ssb_type==2))
|
||||
@@ -208,6 +220,9 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
|
||||
fp->ofdm_symbol_size <<= 1;
|
||||
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
// TODO: Temporarily setting fp->first_carrier_offset = 0 for SL until MAC is developed
|
||||
if (get_softmodem_params()->sl_mode == 2)
|
||||
fp->first_carrier_offset = 0;
|
||||
fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9;
|
||||
fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
|
||||
LOG_I(PHY,
|
||||
@@ -370,6 +385,11 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz);
|
||||
LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq);
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
uint64_t sl_bw_khz = (12 * config->carrier_config.sl_grid_size[config->ssb_config.scs_common]) * (15 << config->ssb_config.scs_common);
|
||||
fp->sl_CarrierFreq = ((sl_bw_khz >> 1) + config->carrier_config.sl_frequency) * 1000;
|
||||
}
|
||||
|
||||
uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<<config->ssb_config.scs_common);
|
||||
fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ;
|
||||
|
||||
@@ -393,7 +413,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
AssertFatal(fp->numerology_index == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, fp->numerology_index);
|
||||
|
||||
fp->Ncp = Ncp;
|
||||
int N_RB = fp->N_RB_DL;
|
||||
int N_RB = (get_softmodem_params()->sl_mode == 2) ? fp->N_RB_SL : fp->N_RB_DL;
|
||||
set_scs_parameters(fp, fp->numerology_index, N_RB);
|
||||
|
||||
fp->slots_per_frame = 10* fp->slots_per_subframe;
|
||||
@@ -420,6 +440,10 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
}
|
||||
|
||||
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
|
||||
// TODO: Temporarily setting fp->ssb_start_subcarrier = 0 for SL until MAC is developed
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
fp->ssb_start_subcarrier = 0;
|
||||
}
|
||||
set_Lmax(fp);
|
||||
|
||||
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
|
||||
|
||||
@@ -48,7 +48,6 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
|
||||
{
|
||||
|
||||
|
||||
|
||||
PHY_ofdm_mod((int *)txdataF, // input
|
||||
(int *)txdata, // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
@@ -75,6 +74,7 @@ void nr_normal_prefix_mod(c16_t *txdataF,
|
||||
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT])
|
||||
{
|
||||
// This function works only slot wise. For more generic symbol generation refer nr_feptx0()
|
||||
LOG_D(NR_PHY,"normal_prefix_mod: prefix0 %d, prefix %d, nsymb %d\n",frame_parms->nb_prefix_samples0,frame_parms->nb_prefix_samples,nsymb);
|
||||
if (frame_parms->numerology_index != 0) { // case where numerology != 0
|
||||
if (!(slot%(frame_parms->slots_per_subframe/2))) {
|
||||
if (was_symbol_used[0]) {
|
||||
|
||||
@@ -103,7 +103,7 @@ int slot_fep(PHY_VARS_UE *ue,
|
||||
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
|
||||
#ifdef DEBUG_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
|
||||
LOG_D(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
|
||||
ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
|
||||
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
|
||||
#endif
|
||||
@@ -178,7 +178,7 @@ int slot_fep(PHY_VARS_UE *ue,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
printf("slot_fep: done\n");
|
||||
printf("slot_fep: Ns %d l %d, done\n",Ns,l);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
@@ -261,7 +261,7 @@ int front_end_fft(PHY_VARS_UE *ue,
|
||||
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
|
||||
#ifdef DEBUG_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY,
|
||||
LOG_D(PHY,
|
||||
"slot_fep: frame %d: slot %d, threadId %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n",
|
||||
ue->proc.proc_rxtx[threadId].frame_rx,Ns, threadId,symbol,
|
||||
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
|
||||
|
||||
@@ -58,6 +58,97 @@ void nr_symbol_fep(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
}
|
||||
}
|
||||
|
||||
int sl_nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
unsigned char Ns,
|
||||
uint32_t sample_offset,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP])
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_params = &ue->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
NR_UE_COMMON *common_vars = &ue->common_vars;
|
||||
|
||||
AssertFatal(symbol < frame_params->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_params->symbols_per_slot-1);
|
||||
AssertFatal(Ns < frame_params->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_params->slots_per_frame-1);
|
||||
|
||||
unsigned int nb_prefix_samples = frame_params->nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0 = frame_params->nb_prefix_samples0;
|
||||
|
||||
|
||||
dft_size_idx_t dftsize = get_dft(frame_params->ofdm_symbol_size);
|
||||
// This is for misalignment issues
|
||||
int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
|
||||
|
||||
unsigned int rx_offset = frame_params->get_samples_slot_timestamp(Ns,frame_params,0);
|
||||
unsigned int abs_symbol = Ns * frame_params->symbols_per_slot + symbol;
|
||||
|
||||
rx_offset += sample_offset;
|
||||
rx_offset += ue->rx_offset;
|
||||
|
||||
for (int idx_symb = Ns*frame_params->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (idx_symb%(0x7<<frame_params->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
rx_offset += frame_params->ofdm_symbol_size * symbol;
|
||||
|
||||
// use OFDM symbol from within 1/8th of the CP to avoid ISI
|
||||
rx_offset -= (nb_prefix_samples / frame_params->ofdm_offset_divisor);
|
||||
|
||||
#ifdef SL_DEBUG_SLOT_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY, "slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n",
|
||||
Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset);
|
||||
#endif
|
||||
|
||||
for (unsigned char aa=0; aa<frame_params->nb_antennas_rx; aa++) {
|
||||
memset(&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],0,frame_params->ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
|
||||
|
||||
// if input to dft is not 256-bit aligned
|
||||
if ((rx_offset & 7) != 0) {
|
||||
memcpy((void *)&tmp_dft_in[0],
|
||||
(void *)&common_vars->rxdata[aa][rx_offset],
|
||||
frame_params->ofdm_symbol_size * sizeof(int32_t));
|
||||
|
||||
rxdata_ptr = (int16_t *)tmp_dft_in;
|
||||
}
|
||||
|
||||
dft(dftsize,
|
||||
rxdata_ptr,
|
||||
(int16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
1);
|
||||
|
||||
|
||||
int symb_offset = (Ns%frame_params->slots_per_subframe)*frame_params->symbols_per_slot;
|
||||
int32_t rot2 = ((uint32_t*)frame_params->symbol_rotation[1])[symbol+symb_offset];
|
||||
((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
|
||||
|
||||
#ifdef SL_DEBUG_SLOT_FEP
|
||||
// if (ue->frame <100)
|
||||
LOG_I(PHY, "slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset,
|
||||
symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]);
|
||||
#endif
|
||||
|
||||
rotate_cpx_vector((c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
(c16_t *)&rot2,
|
||||
(c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
frame_params->ofdm_symbol_size,
|
||||
15);
|
||||
|
||||
c16_t *shift_rot = (c16_t *)frame_params->timeshift_symbol_rotation;
|
||||
|
||||
multadd_cpx_vector((c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
shift_rot,
|
||||
(c16_t *)&rxdataF[aa][frame_params->ofdm_symbol_size*symbol],
|
||||
frame_params->ofdm_symbol_size,
|
||||
15);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOG_D(PHY, "SIDELINK RX: Slot FEP: done for symbol:%d\n", symbol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
unsigned int slot,
|
||||
|
||||
@@ -65,6 +65,8 @@ uint32_t nr_get_G(uint16_t nb_rb,
|
||||
|
||||
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r);
|
||||
|
||||
uint32_t nr_get_G_SL(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t sci1_dmrs_overlap, uint16_t sci1_re, uint16_t sci1_rb, uint16_t sci2_re, uint16_t csi_rs_re, uint8_t Qm, uint8_t Nl);
|
||||
|
||||
void compute_nr_prach_seq(uint8_t short_sequence, uint8_t num_sequences, uint8_t rootSequenceIndex, c16_t X_u[64][839]);
|
||||
|
||||
void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map, uint16_t nr_du[NR_PRACH_SEQ_LEN_L - 1]);
|
||||
|
||||
@@ -123,35 +123,6 @@ int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB,nfapi_nr_pucch_pdu_t* pucch_pdu) {
|
||||
return(gNB->pucch0_lut.nb_id-1);
|
||||
}
|
||||
|
||||
static const int16_t idft12_re[12][12] = {
|
||||
{23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}
|
||||
};
|
||||
|
||||
static const int16_t idft12_im[12][12] = {
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585},
|
||||
{0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066},
|
||||
{0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170},
|
||||
{0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066},
|
||||
{0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585},
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585},
|
||||
{0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066},
|
||||
{0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170},
|
||||
{0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066},
|
||||
{0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585}
|
||||
};
|
||||
//************************************************************************//
|
||||
void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
c16_t **rxdataF,
|
||||
|
||||
@@ -319,6 +319,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
{
|
||||
TracyCZone(ctx, true);
|
||||
int symbol;
|
||||
|
||||
uint8_t Lmax=frame_parms->Lmax;
|
||||
int M = NR_POLAR_PBCH_E;
|
||||
int nushift = (Lmax == 4) ? i_ssb & 3 : i_ssb & 7;
|
||||
|
||||
75
openair1/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
Normal file
75
openair1/PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 PHY/NR_UE_TRANSPORT/nr_pscch_tx.c
|
||||
* \brief Top-level routines for generating and decoding the PSCCH physical channel
|
||||
* \author R. Knopp
|
||||
* \date 2023
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
//#include "PHY/defs.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
uint32_t nr_generate_dci(void *gNB, PHY_VARS_NR_UE *ue,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot);
|
||||
|
||||
uint32_t nr_generate_sci1(const PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu)
|
||||
{
|
||||
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t pdcch_pdu_rel15={0};
|
||||
// for SCI we put the startRB and number of RBs for PSCCH in the first 2 FAPI FreqDomainResource fields
|
||||
pdcch_pdu_rel15.FreqDomainResource[0] = pscch_pssch_pdu->startrb;
|
||||
pdcch_pdu_rel15.FreqDomainResource[1] = pscch_pssch_pdu->pscch_numrbs;
|
||||
pdcch_pdu_rel15.StartSymbolIndex = 1;
|
||||
pdcch_pdu_rel15.DurationSymbols = pscch_pssch_pdu->pscch_numsym;
|
||||
pdcch_pdu_rel15.numDlDci = 1;
|
||||
pdcch_pdu_rel15.dci_pdu[0].ScramblingId = pscch_pssch_pdu->pscch_dmrs_scrambling_id;
|
||||
pdcch_pdu_rel15.dci_pdu[0].PayloadSizeBits = pscch_pssch_pdu->pscch_sci_payload_len;
|
||||
// for SCI we put the number of PRBs in the FAPI AggregationLevel field
|
||||
pdcch_pdu_rel15.dci_pdu[0].AggregationLevel = pscch_pssch_pdu->pscch_numrbs*pscch_pssch_pdu->pscch_numsym;
|
||||
pdcch_pdu_rel15.dci_pdu[0].ScramblingRNTI = 1010;
|
||||
*(uint64_t*)pdcch_pdu_rel15.dci_pdu[0].Payload = *(uint64_t *)pscch_pssch_pdu->pscch_sci_payload;
|
||||
return(nr_generate_dci(NULL,(PHY_VARS_NR_UE *)ue,&pdcch_pdu_rel15,(int32_t *)txdataF,amp,(NR_DL_FRAME_PARMS*)frame_parms,nr_slot_tx));
|
||||
}
|
||||
70
openair1/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
Normal file
70
openair1/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 PHY/NR_UE_TRANSPORT/pucch_nr.c
|
||||
* \brief Top-level routines for generating and decoding the PSFCH physical channel
|
||||
* \author R. Knopp
|
||||
* \date 2023
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
//#include "PHY/defs.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
|
||||
void nr_generate_psfch0(const PHY_VARS_NR_UE *ue,
|
||||
c16_t **txdataF,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int nr_slot_tx,
|
||||
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu)
|
||||
{
|
||||
|
||||
fapi_nr_ul_config_pucch_pdu pucch_pdu;
|
||||
|
||||
pucch_pdu.start_symbol_index = psfch_pdu->start_symbol_index;
|
||||
pucch_pdu.hopping_id = psfch_pdu->hopping_id;
|
||||
pucch_pdu.prb_start = psfch_pdu->prb;
|
||||
pucch_pdu.initial_cyclic_shift = psfch_pdu->initial_cyclic_shift;
|
||||
pucch_pdu.mcs = psfch_pdu->mcs;
|
||||
pucch_pdu.nr_of_symbols = psfch_pdu->nr_of_symbols;
|
||||
pucch_pdu.n_bit = psfch_pdu->bit_len_harq;
|
||||
pucch_pdu.bwp_start = psfch_pdu->sl_bwp_start;
|
||||
pucch_pdu.freq_hop_flag = psfch_pdu->freq_hop_flag;
|
||||
pucch_pdu.group_hop_flag = psfch_pdu->group_hop_flag;
|
||||
pucch_pdu.second_hop_prb = psfch_pdu->second_hop_prb;
|
||||
pucch_pdu.sequence_hop_flag = psfch_pdu->sequence_hop_flag;
|
||||
nr_generate_pucch0(ue, txdataF, frame_parms, amp, nr_slot_tx, &pucch_pdu);
|
||||
}
|
||||
337
openair1/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
Normal file
337
openair1/PHY/NR_UE_TRANSPORT/nr_ue_pucch_rx.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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 PHY/NR_TRANSPORT/pucch_rx.c
|
||||
* \brief Top-level routines for decoding the PUCCH physical channel
|
||||
* \author A. Mico Pereperez, Padarthi Naga Prasanth, Francesco Mani, Raymond Knopp
|
||||
* \date 2020
|
||||
* \version 0.2
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include<stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
|
||||
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "T.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
|
||||
//#define DEBUG_NR_PUCCH_RX 1
|
||||
|
||||
int get_pucch0_cs_lut_index(PHY_VARS_NR_UE *ue, nfapi_nr_pucch_pdu_t* pucch_pdu) {
|
||||
|
||||
int i = 0;
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "getting index for LUT with %d entries, Nid %d\n", ue->pucch0_lut.nb_id, pucch_pdu->hopping_id);
|
||||
#endif
|
||||
|
||||
for (i=0; i<ue->pucch0_lut.nb_id; i++) {
|
||||
if (ue->pucch0_lut.Nid[i] == pucch_pdu->hopping_id) break;
|
||||
}
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "found index %d\n", i);
|
||||
#endif
|
||||
if (i < ue->pucch0_lut.nb_id) return(i);
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "Initializing PUCCH0 LUT index %i with Nid %d\n", i, pucch_pdu->hopping_id);
|
||||
#endif
|
||||
// initialize
|
||||
ue->pucch0_lut.Nid[ue->pucch0_lut.nb_id] = pucch_pdu->hopping_id;
|
||||
for (int slot=0; slot<10<<pucch_pdu->subcarrier_spacing; slot++)
|
||||
for (int symbol=0; symbol<14; symbol++)
|
||||
ue->pucch0_lut.lut[ue->pucch0_lut.nb_id][slot][symbol] = (int)floor(nr_cyclic_shift_hopping(pucch_pdu->hopping_id, 0, 0, 0, symbol, slot) / 0.5235987756);
|
||||
ue->pucch0_lut.nb_id++;
|
||||
return(ue->pucch0_lut.nb_id-1);
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_psfch0(PHY_VARS_NR_UE *ue,
|
||||
int frame,
|
||||
int slot,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
|
||||
const sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu) {
|
||||
int8_t ack_nack_rcvd = -1;
|
||||
nfapi_nr_pucch_pdu_t pucch_pdu;
|
||||
pucch_pdu.freq_hop_flag = psfch_pdu->freq_hop_flag;
|
||||
pucch_pdu.group_hop_flag = psfch_pdu->group_hop_flag;
|
||||
pucch_pdu.sequence_hop_flag = psfch_pdu->sequence_hop_flag;
|
||||
pucch_pdu.second_hop_prb = psfch_pdu->second_hop_prb;
|
||||
pucch_pdu.nr_of_symbols = psfch_pdu->nr_of_symbols;
|
||||
pucch_pdu.start_symbol_index = psfch_pdu->start_symbol_index;
|
||||
pucch_pdu.hopping_id = psfch_pdu->hopping_id;
|
||||
pucch_pdu.prb_start = psfch_pdu->prb;
|
||||
pucch_pdu.prb_size = 1;
|
||||
pucch_pdu.bwp_start = psfch_pdu->sl_bwp_start;
|
||||
pucch_pdu.initial_cyclic_shift = psfch_pdu->initial_cyclic_shift;
|
||||
pucch_pdu.bit_len_harq = psfch_pdu->bit_len_harq;
|
||||
pucch_pdu.sr_flag = 0;
|
||||
pucch_pdu.subcarrier_spacing = 1;
|
||||
ack_nack_rcvd = nr_ue_decode_pucch0(ue,
|
||||
frame,
|
||||
slot,
|
||||
rxdataF,
|
||||
NULL,
|
||||
&pucch_pdu);
|
||||
return ack_nack_rcvd;
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_pucch0(PHY_VARS_NR_UE *ue,
|
||||
int frame,
|
||||
int slot,
|
||||
c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP],
|
||||
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = get_softmodem_params()->sl_mode ? &ue->SL_UE_PHY_PARAMS.sl_frame_params : &ue->frame_parms;
|
||||
|
||||
int soffset = 0;
|
||||
int nr_sequences;
|
||||
const uint8_t *mcs;
|
||||
AssertFatal(pucch_pdu->sr_flag == 0, "SR flag MUST be 0 in SL\n");
|
||||
AssertFatal(pucch_pdu->bit_len_harq == 0 || pucch_pdu->bit_len_harq == 1, "Invalid value for bit_len_harq %d\n", pucch_pdu->bit_len_harq);
|
||||
if(pucch_pdu->bit_len_harq == 0){
|
||||
mcs = table1_mcs;
|
||||
nr_sequences = 1;
|
||||
}
|
||||
else if(pucch_pdu->bit_len_harq == 1){
|
||||
mcs = table1_mcs;
|
||||
nr_sequences = 4 >> 1;
|
||||
}
|
||||
|
||||
AssertFatal(nr_sequences == 1 || nr_sequences == 2, "nr_sequences must be either 1 or 2, nr_sequences %d\n", nr_sequences);
|
||||
|
||||
LOG_D(PHY, "%s pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, O_ACK %d, O_SR %d, mcs %d, initial_cyclic_shift %d, subcarrier_spacing %d\n",
|
||||
__FUNCTION__,
|
||||
pucch_pdu->nr_of_symbols,
|
||||
pucch_pdu->start_symbol_index,
|
||||
pucch_pdu->prb_start,
|
||||
pucch_pdu->second_hop_prb,
|
||||
pucch_pdu->group_hop_flag,
|
||||
pucch_pdu->sequence_hop_flag,
|
||||
pucch_pdu->bit_len_harq,
|
||||
pucch_pdu->sr_flag,
|
||||
mcs[0],
|
||||
pucch_pdu->initial_cyclic_shift,
|
||||
pucch_pdu->subcarrier_spacing);
|
||||
|
||||
int cs_ind = get_pucch0_cs_lut_index(ue, pucch_pdu);
|
||||
/*
|
||||
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
|
||||
*/
|
||||
/*
|
||||
* in TS 38.213 Subclause 9.2.1 it is said that:
|
||||
* for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
|
||||
* is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to:
|
||||
* x(l*12+n) = r_u_v_alpha_delta(n)
|
||||
*/
|
||||
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
|
||||
uint8_t u[2] = {0}, v[2] = {0};
|
||||
|
||||
// // x_n contains the sequence r_u_v_alpha_delta(n)
|
||||
int n, i;
|
||||
int prb_offset[2] = {pucch_pdu->bwp_start + pucch_pdu->prb_start, pucch_pdu->bwp_start + pucch_pdu->prb_start};
|
||||
|
||||
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1);
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,
|
||||
pucch_pdu->hopping_id,
|
||||
0,
|
||||
slot,
|
||||
&u[0],
|
||||
&v[0]); // calculating u and v value first hop
|
||||
LOG_D(PHY, "pucch0: u %d, v %d\n", u[0], v[0]);
|
||||
|
||||
if (pucch_pdu->freq_hop_flag == 1) {
|
||||
nr_group_sequence_hopping(pucch_GroupHopping,
|
||||
pucch_pdu->hopping_id,
|
||||
1,
|
||||
slot,
|
||||
&u[1],
|
||||
&v[1]); // calculating u and v value second hop
|
||||
LOG_D(PHY, "pucch0 second hop: u %d, v %d\n", u[1], v[1]);
|
||||
prb_offset[1] = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb;
|
||||
}
|
||||
|
||||
AssertFatal(pucch_pdu->nr_of_symbols < 3, "nr_of_symbols %d not allowed\n", pucch_pdu->nr_of_symbols);
|
||||
uint32_t re_offset[2] = {0};
|
||||
|
||||
const int16_t *x_re[2], *x_im[2];
|
||||
x_re[0] = table_5_2_2_2_2_Re[u[0]];
|
||||
x_im[0] = table_5_2_2_2_2_Im[u[0]];
|
||||
x_re[1] = table_5_2_2_2_2_Re[u[1]];
|
||||
x_im[1] = table_5_2_2_2_2_Im[u[1]];
|
||||
|
||||
c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32)));
|
||||
int64_t xrtmag = 0, xrtmag_next = 0;
|
||||
uint8_t maxpos = 0;
|
||||
uint8_t index = 0;
|
||||
LOG_D(NR_PHY, "prb_size %d\n", pucch_pdu->prb_size);
|
||||
int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1
|
||||
int32_t rp[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][nb_re_pucch];
|
||||
memset(rp, 0, sizeof(rp));
|
||||
int32_t *tmp_rp = NULL;
|
||||
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
uint8_t l2 = l + pucch_pdu->start_symbol_index;
|
||||
|
||||
re_offset[l] = (12 * prb_offset[l]) + frame_parms->first_carrier_offset;
|
||||
if (re_offset[l] >= frame_parms->ofdm_symbol_size)
|
||||
re_offset[l] -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
|
||||
LOG_D(NR_PHY, "soffset %i, soffset + l2*frame_parms->ofdm_symbol_size %i %i re_offset[%d] %i\n",
|
||||
soffset, soffset + l2*frame_parms->ofdm_symbol_size,
|
||||
(soffset + l2*frame_parms->ofdm_symbol_size + nb_re_pucch), l, re_offset[l]);
|
||||
for (int z = soffset + l2*frame_parms->ofdm_symbol_size + re_offset[l]; z < (soffset + l2*frame_parms->ofdm_symbol_size + re_offset[l] + nb_re_pucch); z++)
|
||||
LOG_D(NR_PHY, "%4d.%2d z %d rxdataF (%d,%d)\n", frame, slot, z, rxdataF[aa][z].r, rxdataF[aa][z].i);
|
||||
tmp_rp = (int32_t *)&rxdataF[aa][soffset + l2 * frame_parms->ofdm_symbol_size];
|
||||
if(re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) {
|
||||
int neg_length = frame_parms->ofdm_symbol_size - re_offset[l];
|
||||
int pos_length = nb_re_pucch - neg_length;
|
||||
memcpy1((void*)rp[aa][l], (void*)&tmp_rp[re_offset[l]], neg_length*sizeof(int32_t));
|
||||
memcpy1((void*)&rp[aa][l][neg_length], (void*)tmp_rp, pos_length*sizeof(int32_t));
|
||||
}
|
||||
else
|
||||
memcpy1((void*)rp[aa][l], (void*)&tmp_rp[re_offset[l]], nb_re_pucch*sizeof(int32_t));
|
||||
|
||||
c16_t *r = (c16_t*)&rp[aa][l];
|
||||
|
||||
for (n=0; n<nb_re_pucch; n++) {
|
||||
xr[aa][l][n].r = (int32_t)x_re[l][n] * r[n].r + (int32_t)x_im[l][n] * r[n].i;
|
||||
xr[aa][l][n].i = (int32_t)x_re[l][n] * r[n].i - (int32_t)x_im[l][n] * r[n].r;
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "x (%d,%d), r%d.%d (%d,%d), xr (%lld,%lld)\n",
|
||||
x_re[l][n], x_im[l][n], l2, re_offset[l], r[n].r, r[n].i, xr[aa][l][n].r, xr[aa][l][n].i);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int seq_index = 0;
|
||||
int64_t temp;
|
||||
|
||||
for(i=0; i<nr_sequences; i++) {
|
||||
c64_t corr[frame_parms->nb_antennas_rx][2];
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
seq_index = (pucch_pdu->initial_cyclic_shift+
|
||||
mcs[i]+
|
||||
ue->pucch0_lut.lut[cs_ind][slot][l+pucch_pdu->start_symbol_index])%12;
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_I(NR_PHY, "PUCCH symbol %d seq %d, seq_index %d, mcs %d , slot %d, cs_ind %d\n",
|
||||
l, i, seq_index, mcs[i], slot, cs_ind);
|
||||
#endif
|
||||
corr[aa][l] = (c64_t){0};
|
||||
for (n = 0; n < 12; n++) {
|
||||
corr[aa][l].r += xr[aa][l][n].r * idft12_re[seq_index][n] + xr[aa][l][n].i * idft12_im[seq_index][n];
|
||||
corr[aa][l].i += xr[aa][l][n].r * idft12_im[seq_index][n] - xr[aa][l][n].i * idft12_re[seq_index][n];
|
||||
}
|
||||
corr[aa][l].r >>= 31;
|
||||
corr[aa][l].i >>= 31;
|
||||
}
|
||||
}
|
||||
LOG_D(PHY,"PUCCH IDFT[%d/%d] = (%ld,%ld)=>%f\n",
|
||||
mcs[i], seq_index, corr[0][0].r, corr[0][0].i,
|
||||
10*log10((double)squaredMod(corr[0][0])));
|
||||
if (pucch_pdu->nr_of_symbols == 2)
|
||||
LOG_D(PHY,"PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n",
|
||||
mcs[i], seq_index, corr[0][1].r, corr[0][1].i,
|
||||
10*log10((double)squaredMod(corr[0][1])));
|
||||
if (pucch_pdu->freq_hop_flag == 0) {
|
||||
if (pucch_pdu->nr_of_symbols == 1) {// non-coherent correlation
|
||||
temp = 0;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++)
|
||||
temp += squaredMod(corr[aa][0]);
|
||||
} else {
|
||||
temp = 0;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
c64_t corr2;
|
||||
csum(corr2, corr[aa][0], corr[aa][1]);
|
||||
// coherent combining of 2 symbols and then complex modulus for single-frequency case
|
||||
temp += corr2.r*corr2.r + corr2.i*corr2.i;
|
||||
}
|
||||
}
|
||||
} else if (pucch_pdu->freq_hop_flag == 1) {
|
||||
// full non-coherent combining of 2 symbols for frequency-hopping case
|
||||
temp = 0;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++)
|
||||
temp += squaredMod(corr[aa][0]) + squaredMod(corr[aa][1]);
|
||||
}
|
||||
else AssertFatal(1==0,"shouldn't happen\n");
|
||||
LOG_D(PHY, "Sequence %d temp %ld vs. xrtmag %ld xrtmag_next %ld, slot %d rx atnennas %u\n",
|
||||
i, temp, xrtmag, xrtmag_next, slot, frame_parms->nb_antennas_rx);
|
||||
if (temp > xrtmag) {
|
||||
xrtmag_next = xrtmag;
|
||||
xrtmag = temp;
|
||||
LOG_D(PHY,"Sequence %d xrtmag %ld xrtmag_next %ld, slot %d\n", i, xrtmag, xrtmag_next, slot);
|
||||
maxpos = i;
|
||||
int64_t temp2 = 0,temp3 = 0;;
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
temp2 += squaredMod(corr[aa][0]);
|
||||
if (pucch_pdu->nr_of_symbols == 2)
|
||||
temp3 += squaredMod(corr[aa][1]);
|
||||
}
|
||||
}
|
||||
else if (temp > xrtmag_next)
|
||||
xrtmag_next = temp;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
LOG_D(NR_PHY, "PUCCH 0 : maxpos %d\n", maxpos);
|
||||
#endif
|
||||
index = maxpos;
|
||||
uint8_t ack_nack = !(index&0x01);
|
||||
LOG_D(PHY,
|
||||
"[PSFCH RX] %d.%d HARQ %s\n",
|
||||
frame,
|
||||
slot,
|
||||
ack_nack == 0 ? "ACK" : "NACK");
|
||||
return ack_nack;
|
||||
}
|
||||
@@ -47,7 +47,7 @@
|
||||
#include <execinfo.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -93,6 +93,8 @@
|
||||
|
||||
#include "impl_defs_top.h"
|
||||
#include "impl_defs_nr.h"
|
||||
// This is for ULSCH RX structures used for Sidelink
|
||||
#include "defs_gNB.h"
|
||||
#include "time_meas.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
@@ -279,7 +281,7 @@ typedef struct {
|
||||
#define NR_PSBCH_MAX_NB_MOD_SYMBOLS 99
|
||||
#define NR_PSBCH_DMRS_LENGTH 297 // in mod symbols
|
||||
#define NR_PSBCH_DMRS_LENGTH_DWORD 20 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
|
||||
|
||||
#define NR_SLSCH_RX_MAX 2
|
||||
/* NR Sidelink PSBCH payload fields
|
||||
TODO: This will be removed in the future and
|
||||
filled in by the upper layers once developed. */
|
||||
@@ -406,6 +408,7 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
uint8_t prs_active_gNBs;
|
||||
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
|
||||
NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES];
|
||||
NR_UL_UE_HARQ_t sl_harq_processes[NR_MAX_SLSCH_HARQ_PROCESSES];
|
||||
//Paging parameters
|
||||
uint32_t IMSImod1024;
|
||||
uint32_t PF;
|
||||
@@ -457,6 +460,7 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
/// temporary offset during cell search prior to MIB decoding
|
||||
int ssb_offset;
|
||||
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
|
||||
int rx_offset; /// Timing offset
|
||||
int64_t max_pos_iir; /// Timing offset IIR filter
|
||||
int max_pos_acc; /// Timing offset accumuluated error for PI filter
|
||||
|
||||
@@ -521,6 +525,20 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
// Sidelink parameters
|
||||
sl_nr_sidelink_mode_t sl_mode;
|
||||
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
|
||||
struct PHY_MEASUREMENTS_gNB_s *sl_measurements;
|
||||
int max_nb_slsch;
|
||||
// we use the gNB ULSCH context for SLSCH reception
|
||||
struct NR_gNB_ULSCH_t *slsch;
|
||||
struct NR_gNB_PUSCH *pssch_vars;
|
||||
bool phy_config_request_sent;
|
||||
int pscch_dmrs_gold_init;
|
||||
/// PDCCH DMRS for TX
|
||||
uint32_t ***nr_gold_pscch_dmrs;
|
||||
/// PSCCH DMRS for RX
|
||||
uint32_t ***nr_gold_pscch;
|
||||
/// PSSCH signal detection threshold
|
||||
int pssch_thres;
|
||||
|
||||
Actor_t sync_actor;
|
||||
Actor_t *dl_actors;
|
||||
Actor_t *ul_actors;
|
||||
@@ -581,6 +599,8 @@ typedef struct nr_phy_data_tx_s {
|
||||
// Sidelink Rx action decided by MAC
|
||||
sl_nr_tx_config_type_enum_t sl_tx_action;
|
||||
sl_nr_tx_config_psbch_pdu_t psbch_vars;
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t nr_sl_pssch_pscch_pdu;
|
||||
uint32_t pscch_Nid;
|
||||
} nr_phy_data_tx_t;
|
||||
|
||||
typedef struct nr_phy_data_s {
|
||||
@@ -589,6 +609,12 @@ typedef struct nr_phy_data_s {
|
||||
|
||||
// Sidelink Rx action decided by MAC
|
||||
sl_nr_rx_config_type_enum_t sl_rx_action;
|
||||
sl_nr_rx_config_pscch_pdu_t nr_sl_pscch_pdu;
|
||||
sl_nr_rx_config_pssch_sci_pdu_t nr_sl_pssch_sci_pdu;
|
||||
sl_nr_rx_config_pssch_pdu_t nr_sl_pssch_pdu;
|
||||
sl_nr_tti_csi_rs_pdu_t nr_sl_csi_rs_pdu;
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
|
||||
uint8_t num_psfch_pdus;
|
||||
NR_UE_CSI_RS csirs_vars;
|
||||
NR_UE_CSI_IM csiim_vars;
|
||||
} nr_phy_data_t;
|
||||
|
||||
@@ -336,4 +336,34 @@ typedef struct {
|
||||
#define KHz (1000UL)
|
||||
#define MHz (1000*KHz)
|
||||
|
||||
static const int16_t idft12_re[12][12] = {
|
||||
{23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170},
|
||||
{23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066},
|
||||
{23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585},
|
||||
{23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0},
|
||||
{23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585},
|
||||
{23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}
|
||||
};
|
||||
|
||||
static const int16_t idft12_im[12][12] = {
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585},
|
||||
{0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066},
|
||||
{0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170},
|
||||
{0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066},
|
||||
{0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585},
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585},
|
||||
{0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066},
|
||||
{0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170},
|
||||
{0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066},
|
||||
{0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -113,6 +113,47 @@ typedef struct SL_NR_SYNC_PARAMS {
|
||||
|
||||
} SL_NR_SYNC_PARAMS_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSSCH {
|
||||
|
||||
// AVG POWER OF PSSCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
// AVG POWER OF PSSCH DMRS in dBm/RE
|
||||
int16_t rsrp_dBm_per_RE;
|
||||
|
||||
// STATS - CRC Errors observed during PSSCH reception (per HARQ round)
|
||||
uint32_t rx_errors[8];
|
||||
|
||||
// STATS - CRC Errors observed during PSSCH SCI2 reception
|
||||
uint32_t rx_sci2_errors;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_ok;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_sci2_ok;
|
||||
|
||||
// STATS - transmissions of PSSCH by the UE
|
||||
uint32_t num_pssch_tx;
|
||||
|
||||
// STATS - transmissions of PSSCH by the UE
|
||||
uint32_t num_pssch_sci2_tx;
|
||||
} SL_NR_UE_PSSCH_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSCCH {
|
||||
|
||||
// AVG POWER OF PSCCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
// AVG POWER OF PSCCH DMRS in dBm/RE
|
||||
int16_t rsrp_dBm_per_RE;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint32_t rx_ok;
|
||||
|
||||
// STATS - transmissions of PSBCH by the UE
|
||||
uint32_t num_pscch_tx;
|
||||
|
||||
} SL_NR_UE_PSCCH_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSBCH {
|
||||
// AVG POWER OF PSBCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
@@ -130,6 +171,12 @@ typedef struct SL_NR_UE_PSBCH {
|
||||
|
||||
} SL_NR_UE_PSBCH_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSFCH {
|
||||
// STATS - transmissions of PSFCH by the UE
|
||||
uint32_t num_psfch_tx;
|
||||
uint32_t num_psfch_rx;
|
||||
} SL_NR_UE_PSFCH_t;
|
||||
|
||||
typedef struct sl_nr_ue_phy_params {
|
||||
SL_NR_UE_INIT_PARAMS_t init_params;
|
||||
|
||||
@@ -138,7 +185,16 @@ typedef struct sl_nr_ue_phy_params {
|
||||
// Sidelink PHY PARAMETERS USED FOR PSBCH reception/Txn
|
||||
SL_NR_UE_PSBCH_t psbch;
|
||||
|
||||
// Configuration parameters from MAC
|
||||
// sidelink phy parameters used for pscch reception/txn
|
||||
SL_NR_UE_PSCCH_t pscch;
|
||||
|
||||
// sidelink phy parameters used for pssch reception/txn
|
||||
SL_NR_UE_PSSCH_t pssch;
|
||||
|
||||
// sidelink phy parameters used for psfch reception/txn
|
||||
SL_NR_UE_PSFCH_t psfch;
|
||||
|
||||
//Configuration parameters from MAC
|
||||
sl_nr_phy_config_request_t sl_config;
|
||||
|
||||
NR_DL_FRAME_PARMS sl_frame_params;
|
||||
@@ -150,4 +206,4 @@ typedef struct sl_nr_ue_phy_params {
|
||||
|
||||
} sl_nr_ue_phy_params_t;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -277,6 +277,7 @@
|
||||
|
||||
#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 */
|
||||
#define NR_MAX_SLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES)
|
||||
#endif
|
||||
|
||||
/// Data structure for transmission.
|
||||
|
||||
@@ -183,5 +183,15 @@ void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
|
||||
void *typeSpecific,
|
||||
uint16_t rx_slss_id);
|
||||
|
||||
void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data,
|
||||
int8_t *ack_nack_rcvd,
|
||||
uint8_t num_acks);
|
||||
|
||||
typedef struct {
|
||||
ldpcDecode_t *rdata;
|
||||
bool rxok;
|
||||
} slsch_status_t;
|
||||
#endif
|
||||
/** @}*/
|
||||
|
||||
@@ -451,12 +451,17 @@ void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config)
|
||||
void sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response)
|
||||
{
|
||||
module_id_t module_id = scheduled_response->module_id;
|
||||
const char *sl_rx_action[] = {"NONE", "RX_PSBCH", "RX_PSCCH", "RX_SCI2_ON_PSSCH", "RX_SLSCH_ON_PSSCH"};
|
||||
const char *sl_tx_action[] = {"TX_PSBCH", "TX_PSCCH_PSSCH", "TX_PSFCH"};
|
||||
|
||||
const char *sl_rx_action[] = {"NONE", "RX_PSBCH", "RX_PSCCH", "RX_SCI2_ON_PSSCH", "RX_SLSCH_ON_PSSCH", "RX_PSFCH", "RX_SLSCH_ON_PSSCH_CSI_RS"};
|
||||
const char *sl_tx_action[] = {"TX_PSBCH", "TX_PSCCH_PSSCH", "TX_PSCCH_PSSCH_PSFCH", "TX_PSCCH_PSSCH_CSI_RS"};
|
||||
//NR_UE_CSI_RS *csirs_vars = PHY_vars_UE_g[module_id][cc_id]->csirs_vars[0];
|
||||
|
||||
if (scheduled_response->sl_rx_config != NULL) {
|
||||
sl_nr_rx_config_request_t *sl_rx_config = scheduled_response->sl_rx_config;
|
||||
nr_phy_data_t *phy_data = (nr_phy_data_t *)scheduled_response->phy_data;
|
||||
sl_nr_tti_csi_rs_pdu_t *csirs_config_pdu;
|
||||
AssertFatal(sl_rx_config->number_pdus == SL_NR_RX_CONFIG_LIST_NUM,
|
||||
"sl_rx_config->number_pdus incorrect\n");
|
||||
|
||||
AssertFatal(sl_rx_config->number_pdus == SL_NR_RX_CONFIG_LIST_NUM, "sl_rx_config->number_pdus incorrect\n");
|
||||
|
||||
@@ -465,6 +470,34 @@ void sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response)
|
||||
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
|
||||
LOG_D(PHY, "Recvd CONFIG_TYPE_RX_PSBCH\n");
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_RX_PSCCH:
|
||||
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSCCH;
|
||||
phy_data->nr_sl_pscch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pscch_config_pdu;
|
||||
LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSCCH\n");
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SCI:
|
||||
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SCI;
|
||||
phy_data->nr_sl_pssch_sci_pdu = sl_rx_config->sl_rx_config_list[0].rx_sci2_config_pdu;
|
||||
LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH_SCI\n");
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH:
|
||||
case SL_NR_CONFIG_TYPE_RX_PSFCH:
|
||||
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS:
|
||||
phy_data->sl_rx_action = sl_rx_config->sl_rx_config_list[0].pdu_type;
|
||||
phy_data->nr_sl_pssch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pssch_config_pdu;
|
||||
LOG_D(NR_PHY, "%4d.%2d Recvd %s\n", sl_rx_config->sfn, sl_rx_config->slot, sl_rx_action[phy_data->sl_rx_action]);
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS) {
|
||||
csirs_config_pdu = &sl_rx_config->sl_rx_config_list[0].rx_csi_rs_config_pdu;
|
||||
memcpy((void*)&(phy_data->csirs_vars.csirs_config_pdu), (void*)csirs_config_pdu, sizeof(sl_nr_tti_csi_rs_pdu_t));
|
||||
phy_data->csirs_vars.active = true;
|
||||
}
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSFCH) {
|
||||
phy_data->psfch_pdu_list = calloc(sl_rx_config->sl_rx_config_list[0].num_psfch_pdus, sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
|
||||
memcpy((void*)phy_data->psfch_pdu_list, (void*)sl_rx_config->sl_rx_config_list[0].rx_psfch_pdu_list,
|
||||
sl_rx_config->sl_rx_config_list[0].num_psfch_pdus * sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
|
||||
phy_data->num_psfch_pdus = sl_rx_config->sl_rx_config_list[0].num_psfch_pdus;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Incorrect sl_rx config req pdutype \n");
|
||||
break;
|
||||
@@ -492,6 +525,32 @@ void sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response)
|
||||
phy_data_tx->psbch_vars.psbch_tx_power = sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.psbch_tx_power;
|
||||
phy_data_tx->psbch_vars.tx_slss_id = sl_tx_config->tx_config_list[0].tx_psbch_config_pdu.tx_slss_id;
|
||||
break;
|
||||
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH:
|
||||
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS:
|
||||
case SL_NR_CONFIG_TYPE_TX_PSFCH: {
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *tx_config_pdu = &sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu;
|
||||
phy_data_tx->sl_tx_action = sl_tx_config->tx_config_list[0].pdu_type;
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu = *tx_config_pdu;
|
||||
LOG_D(PHY, "Recvd CONFIG_TYPE_%s in (%d.%d) PSCCH startRB %hhu, PSCCH numRB %hhu\n",
|
||||
sl_tx_action[phy_data_tx->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH],
|
||||
sl_tx_config->sfn, sl_tx_config->slot,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.startrb,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_numrbs);
|
||||
LOG_D(NR_PHY, "format 1A length %hu :%llx, format 2x length %hu : %llx, PSSCH mcs %hu, PSSCH tbslrm %u\n",
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload_len,
|
||||
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload_len,
|
||||
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.mcs,
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.tbslbrm);
|
||||
if (phy_data_tx->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
phy_data_tx->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu = tx_config_pdu->nr_sl_csi_rs_pdu;
|
||||
}
|
||||
//uint8_t current_harq_pid = tx_config_pdu->harq_pid;
|
||||
//NR_UL_UE_HARQ_t *harq_process = &PHY_vars_UE_g[module_id][cc_id]->sl_harq_processes[current_harq_pid];
|
||||
phy_data_tx->ulsch.status = ACTIVE; //harq_process->status = ACTIVE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Incorrect sl_tx config req pdutype \n");
|
||||
break;
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "UTIL/OPT/opt.h"
|
||||
#include "intertask_interface.h"
|
||||
@@ -31,6 +34,8 @@
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "common/utils/colors.h"
|
||||
|
||||
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
@@ -77,6 +82,18 @@ void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
|
||||
|
||||
switch (pdu_type) {
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH:
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH_PSFCH: {
|
||||
sl_nr_slsch_pdu_t *rx_slsch_pdu = &rx_ind->rx_indication_body[n_pdus - 1].rx_slsch_pdu;
|
||||
slsch_status_t *slsch_status = (slsch_status_t *)typeSpecific;
|
||||
rx_slsch_pdu->pdu = slsch_status->rdata->ulsch_harq->b;
|
||||
rx_slsch_pdu->pdu_length = slsch_status->rdata->ulsch_harq->TBS;
|
||||
rx_slsch_pdu->harq_pid = slsch_status->rdata->harq_pid;
|
||||
rx_slsch_pdu->ack_nack = (slsch_status->rxok==true) ? 1 : 0;
|
||||
|
||||
LOG_D(NR_MAC, "%4d.%2d Received %s SLSCH\n", rx_ind->sfn, rx_ind->slot, rx_slsch_pdu->ack_nack ? "Correct" : "Incorrect");
|
||||
if (slsch_status->rxok==true) ue->SL_UE_PHY_PARAMS.pssch.rx_ok++;
|
||||
else ue->SL_UE_PHY_PARAMS.pssch.rx_errors[0]++;
|
||||
}
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SSB: {
|
||||
sl_nr_ssb_pdu_t *ssb_pdu = &rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu;
|
||||
@@ -102,6 +119,246 @@ void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
|
||||
rx_ind->number_pdus = n_pdus;
|
||||
}
|
||||
|
||||
extern int dmrs_pscch_mask[2];
|
||||
#if 0
|
||||
int nr_slsch_procedures(PHY_VARS_NR_UE *ue, int frame_rx, int slot_rx, int SLSCH_id, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data, bool is_csi_rs_slot, int8_t *ack_nack_rcvd, int num_acks) {
|
||||
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
sl_nr_rx_config_pssch_pdu_t *slsch_pdu = &phy_data->nr_sl_pssch_pdu; //ue->slsch[SLSCH_id].harq_process->slsch_pdu;
|
||||
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu; //ue->slsch[SLSCH_id].harq_process->pssch_pdu;
|
||||
|
||||
uint8_t freq_density = 0;
|
||||
uint8_t nr_of_rbs = 0;
|
||||
if (is_csi_rs_slot) {
|
||||
freq_density = phy_data->csirs_vars.csirs_config_pdu.freq_density; //ue->csirs_vars[0]->csirs_config_pdu.freq_density;
|
||||
nr_of_rbs = phy_data->csirs_vars.csirs_config_pdu.nr_of_rbs; //ue->csirs_vars[0]->csirs_config_pdu.nr_of_rbs;
|
||||
AssertFatal((freq_density == 1) || (nr_of_rbs > 0), "CSI-RS parameters are not properly configured\n");
|
||||
}
|
||||
int harq_pid = slsch_pdu->harq_pid;
|
||||
uint16_t nb_re_dmrs;
|
||||
uint16_t start_symbol = 1;
|
||||
uint16_t number_symbols = pssch_pdu->pssch_numsym;
|
||||
ue->slsch[SLSCH_id].harq_process->harq_to_be_cleared=true;
|
||||
uint8_t number_dmrs_symbols = 0;
|
||||
for (int l = start_symbol; l < start_symbol + number_symbols; l++)
|
||||
number_dmrs_symbols += ((pssch_pdu->dmrs_symbol_position)>>l)&0x01;
|
||||
|
||||
nb_re_dmrs = 6;
|
||||
|
||||
uint32_t rb_size = pssch_pdu->num_subch*pssch_pdu->subchannel_size;
|
||||
int sci1_dmrs_overlap = pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pssch_pdu->pscch_numsym-2];
|
||||
int sci2_re = get_NREsci2_2(pssch_pdu->sci2_alpha_times_100,
|
||||
pssch_pdu->sci2_len,
|
||||
pssch_pdu->sci2_beta_offset,
|
||||
pssch_pdu->pssch_numsym,
|
||||
pssch_pdu->pscch_numsym,
|
||||
pssch_pdu->pscch_numrbs,
|
||||
pssch_pdu->l_subch,
|
||||
pssch_pdu->subchannel_size,
|
||||
pssch_pdu->targetCodeRate,
|
||||
0);
|
||||
|
||||
uint8_t nr_rbs_w_csi_rs = nr_of_rbs / freq_density;
|
||||
uint8_t subcarriers_used = get_nrUE_params()->nb_antennas_tx > 2 ? 2 : get_nrUE_params()->nb_antennas_tx;
|
||||
int num_CSI_REs = is_csi_rs_slot ? nr_rbs_w_csi_rs * subcarriers_used : 0;
|
||||
uint16_t sci1_re = pssch_pdu->pscch_numsym * pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
|
||||
uint32_t G = nr_get_G_SL(rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
sci1_dmrs_overlap,
|
||||
sci1_re,
|
||||
pssch_pdu->pscch_numrbs,
|
||||
sci2_re,
|
||||
num_CSI_REs,
|
||||
pssch_pdu->mod_order,
|
||||
pssch_pdu->num_layers);
|
||||
|
||||
AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
|
||||
rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pssch_pdu->mod_order,
|
||||
pssch_pdu->num_layers);
|
||||
LOG_D(NR_PHY,"slot %d rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
|
||||
slot_rx,
|
||||
rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
pssch_pdu->dmrs_symbol_position,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pssch_pdu->mod_order,
|
||||
pssch_pdu->num_layers);
|
||||
|
||||
nr_ulsch_layer_demapping(ue->pssch_vars[SLSCH_id].llr,
|
||||
pssch_pdu->num_layers,
|
||||
pssch_pdu->mod_order,
|
||||
G,
|
||||
ue->pssch_vars[SLSCH_id].llr_layers);
|
||||
|
||||
//for (int g=0;g<G;g++) LOG_I(NR_PHY,"prescrambling_llr[%d] %d\n",g,ue->pssch_vars[SLSCH_id].llr[g]);
|
||||
//----------------------------------------------------------
|
||||
//------------------- ULSCH unscrambling -------------------
|
||||
//----------------------------------------------------------
|
||||
//LOG_I(NR_PHY,"SLSCH, unscrambling with Nid %x\n",pssch_pdu->Nid);
|
||||
nr_ulsch_unscrambling(ue->pssch_vars[SLSCH_id].llr, G, pssch_pdu->Nid, 1010);
|
||||
// for (int g=0;g<32;g++) LOG_I(NR_PHY,"unscrambling_llr[%d] %d\n",g,ue->pssch_vars[SLSCH_id].llr[g]);
|
||||
//----------------------------------------------------------
|
||||
//--------------------- ULSCH decoding ---------------------
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
nfapi_nr_pusch_pdu_t pusch_pdu;
|
||||
|
||||
pusch_pdu.rb_size = rb_size;
|
||||
pusch_pdu.qam_mod_order = pssch_pdu->mod_order;
|
||||
pusch_pdu.mcs_index = slsch_pdu->mcs;
|
||||
pusch_pdu.nrOfLayers = pssch_pdu->num_layers;
|
||||
pusch_pdu.pusch_data.tb_size=slsch_pdu->tb_size;
|
||||
uint32_t A = slsch_pdu->tb_size<<3;
|
||||
pusch_pdu.target_code_rate=slsch_pdu->target_coderate;
|
||||
float Coderate = (float) (slsch_pdu->target_coderate) / 10240.0f;
|
||||
pusch_pdu.pusch_data.rv_index=slsch_pdu->rv_index;
|
||||
|
||||
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){
|
||||
pusch_pdu.maintenance_parms_v3.ldpcBaseGraph=2;
|
||||
}
|
||||
else{
|
||||
pusch_pdu.maintenance_parms_v3.ldpcBaseGraph=1;
|
||||
}
|
||||
pusch_pdu.maintenance_parms_v3.tbSizeLbrmBytes=slsch_pdu->tbslbrm>>3;
|
||||
|
||||
LOG_D(NR_PHY, "%4d.%2d Calling nr_ulsch_decoding\n", frame_rx, slot_rx);
|
||||
int nbDecode =
|
||||
nr_ulsch_decoding(NULL, ue, SLSCH_id, ue->pssch_vars[SLSCH_id].llr, fp, &pusch_pdu, frame_rx, slot_rx, harq_pid, G, proc, phy_data, ack_nack_rcvd, num_acks);
|
||||
return nbDecode;
|
||||
}
|
||||
|
||||
void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_proc_t *proc,nr_phy_data_t *phy_data, int8_t *ack_nack_rcvd, uint8_t num_acks)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
|
||||
NR_UL_gNB_HARQ_t *slsch_harq = rdata->ulsch_harq;
|
||||
NR_gNB_ULSCH_t *slsch = rdata->ulsch;
|
||||
int r = rdata->segment_r;
|
||||
sl_nr_rx_config_pssch_pdu_t *slsch_pdu = &phy_data->nr_sl_pssch_pdu;//UE->slsch[rdata->ulsch_id].harq_process->slsch_pdu;
|
||||
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
|
||||
slsch_harq->processedSegments++;
|
||||
LOG_D(NR_PHY,
|
||||
"processing result of segment: %d, processed %d/%d\n",
|
||||
rdata->segment_r,
|
||||
slsch_harq->processedSegments,
|
||||
rdata->nbSegments);
|
||||
if (decodeSuccess) {
|
||||
memcpy(slsch_harq->b + rdata->offset, slsch_harq->c[r], rdata->Kr_bytes - (slsch_harq->F >> 3) - ((slsch_harq->C > 1) ? 3 : 0));
|
||||
|
||||
} else {
|
||||
LOG_D(NR_PHY, "ULSCH %d in error\n", rdata->ulsch_id);
|
||||
}
|
||||
|
||||
//int dumpsig=0;
|
||||
// if all segments are done
|
||||
if (rdata->nbSegments == slsch_harq->processedSegments) {
|
||||
sl_nr_rx_indication_t sl_rx_indication;
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
slsch_status_t slsch_status;
|
||||
if (!check_abort(&slsch_harq->abort_decode) && !UE->pssch_vars[rdata->ulsch_id].DTX) {
|
||||
LOG_D(NR_PHY,
|
||||
"[UE] SLSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
"(all seg) %d)\n",
|
||||
slsch->frame,
|
||||
slsch->slot,
|
||||
rdata->harq_pid,
|
||||
slsch_pdu->ndi,
|
||||
slsch->active,
|
||||
slsch_harq->round,
|
||||
slsch_harq->TBS,
|
||||
rdata->decodeIterations);
|
||||
slsch->active = false;
|
||||
slsch_harq->round = 0;
|
||||
LOG_D(NR_PHY, "%4d.%2d SLSCH received ok \n", proc->frame_rx, proc->nr_slot_rx);
|
||||
slsch_status.rdata = rdata;
|
||||
slsch_status.rxok = true;
|
||||
//dumpsig=1;
|
||||
} else {
|
||||
LOG_E(NR_PHY,
|
||||
"[UE] SLSCH %d in error: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
|
||||
"TBS %d) r %d\n",
|
||||
rdata->ulsch_id,
|
||||
slsch->frame,
|
||||
slsch->slot,
|
||||
rdata->harq_pid,
|
||||
slsch_pdu->ndi,
|
||||
slsch->active,
|
||||
slsch_harq->round,
|
||||
slsch_harq->ulsch_pdu.pusch_data.rv_index,
|
||||
slsch_harq->ulsch_pdu.rb_start,
|
||||
slsch_harq->ulsch_pdu.rb_size,
|
||||
slsch_harq->TBS,
|
||||
r);
|
||||
slsch->handled = 1;
|
||||
LOG_D(NR_PHY, "%4d.%2d SLSCH %d in error\n", proc->frame_rx, proc->nr_slot_rx, rdata->ulsch_id);
|
||||
slsch_status.rdata = rdata;
|
||||
slsch_status.rxok = false;
|
||||
// dumpsig=1;
|
||||
}
|
||||
slsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
sl_rx_indication.sfn = proc->frame_rx;
|
||||
sl_rx_indication.slot = proc->nr_slot_rx;
|
||||
sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.ack_nack_rcvd = calloc(num_acks, sizeof(uint8_t));
|
||||
memcpy((void*)sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.ack_nack_rcvd, (void*)ack_nack_rcvd,
|
||||
num_acks * sizeof(uint8_t));
|
||||
sl_rx_indication.rx_indication_body[0].rx_slsch_pdu.num_acks_rcvd = num_acks;
|
||||
uint8_t pdu_type = phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH ? SL_NR_RX_PDU_TYPE_SLSCH_PSFCH : SL_NR_RX_PDU_TYPE_SLSCH;
|
||||
nr_fill_sl_rx_indication(&sl_rx_indication, pdu_type, UE, 1, proc, (void*)&slsch_status, 0);
|
||||
nr_fill_sl_indication(&sl_indication,&sl_rx_indication,NULL,proc,UE,phy_data);
|
||||
if (UE->if_inst && UE->if_inst->sl_indication)
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
/*
|
||||
if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) {
|
||||
int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0;
|
||||
|
||||
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M("rxsigF0_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
|
||||
LOG_M("chestF0_ext.m","chF0_ext",
|
||||
&gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp",
|
||||
&gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr",
|
||||
&gNB->pusch_vars[0].llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size *
|
||||
ulsch_harq->ulsch_pdu.qam_mod_order,1,0); if (gNB->frame_parms.nb_antennas_rx > 1) {
|
||||
|
||||
LOG_M("rxsigF1_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
|
||||
LOG_M("chestF1_ext.m","chF1_ext",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF1_comp.m","rxsF1_comp",
|
||||
&gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1);
|
||||
}
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
*/
|
||||
slsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nr_ue_psbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
@@ -174,6 +431,10 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
int sampleShift = INT_MAX;
|
||||
#if 0
|
||||
bool is_csi_rs_slot = false;
|
||||
int8_t *ack_nack_rcvd = NULL;
|
||||
#endif
|
||||
|
||||
// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX_SL, VCD_FUNCTION_IN);
|
||||
start_meas(&sl_phy_params->phy_proc_sl_rx);
|
||||
@@ -183,6 +444,41 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
|
||||
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
|
||||
__attribute__((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz];
|
||||
|
||||
if ((frame_rx & 127) == 0)
|
||||
{
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSBCH Stats: TX %u, RX ok %u, RX not ok %u\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->psbch.num_psbch_tx,
|
||||
sl_phy_params->psbch.rx_ok,
|
||||
sl_phy_params->psbch.rx_errors);
|
||||
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSCCH Stats: TX %u, RX ok %u\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->pscch.num_pscch_tx,
|
||||
sl_phy_params->pscch.rx_ok);
|
||||
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH/SCI2 Stats: TX %u, RX ok %u, RX not ok %u\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->pssch.num_pssch_sci2_tx,
|
||||
sl_phy_params->pssch.rx_sci2_ok,
|
||||
sl_phy_params->pssch.rx_sci2_errors);
|
||||
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH Stats: TX %u, RX ok %u, RX not ok (%u/%u/%u/%u)\n",KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->pssch.num_pssch_tx,
|
||||
sl_phy_params->pssch.rx_ok,
|
||||
sl_phy_params->pssch.rx_errors[0],
|
||||
sl_phy_params->pssch.rx_errors[1],
|
||||
sl_phy_params->pssch.rx_errors[2],
|
||||
sl_phy_params->pssch.rx_errors[3]);
|
||||
LOG_I(NR_PHY, "%s[UE%d] %d:%d PSFCH Stats: TX %u\n", KGRN,
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->psfch.num_psfch_tx
|
||||
);
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
}
|
||||
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH) {
|
||||
const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
|
||||
@@ -258,6 +554,200 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
|
||||
LOG_I(NR_PHY, "============================================\n");
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSCCH)
|
||||
{
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_data->phy_pdcch_config.pdcch_config[0];
|
||||
LOG_D(NR_PHY,"pscch_numsym = %d\n",phy_data->nr_sl_pscch_pdu.pscch_numsym);
|
||||
LOG_D(NR_PHY,"pscch_startrb = %d\n",phy_data->nr_sl_pscch_pdu.pscch_startrb);
|
||||
LOG_D(NR_PHY,"pscch_numrbs = %d\n",phy_data->nr_sl_pscch_pdu.pscch_numrbs);
|
||||
LOG_D(NR_PHY,"pscch_dmrs_scrambling_id = %d\n",phy_data->nr_sl_pscch_pdu.pscch_dmrs_scrambling_id);
|
||||
|
||||
LOG_D(NR_PHY,"pscch_num_subch= %d\n",phy_data->nr_sl_pscch_pdu.num_subch);
|
||||
LOG_D(NR_PHY,"pscch_subchannel_size = %d\n",phy_data->nr_sl_pscch_pdu.subchannel_size);
|
||||
LOG_D(NR_PHY,"pscch_l_subch = %d\n",phy_data->nr_sl_pscch_pdu.l_subch);
|
||||
LOG_D(NR_PHY,"pscch_pssch_numsym = %d\n",phy_data->nr_sl_pscch_pdu.pssch_numsym);
|
||||
LOG_D(NR_PHY,"sense_pscch = %d\n",phy_data->nr_sl_pscch_pdu.sense_pscch);
|
||||
|
||||
rel15->rnti = 0;
|
||||
rel15->BWPSize = phy_data->nr_sl_pscch_pdu.num_subch * phy_data->nr_sl_pscch_pdu.subchannel_size;
|
||||
rel15->BWPStart = phy_data->nr_sl_pscch_pdu.pscch_startrb;
|
||||
rel15->SubcarrierSpacing = fp->subcarrier_spacing;
|
||||
rel15->coreset.frequency_domain_resource[0] = phy_data->nr_sl_pscch_pdu.pscch_startrb;
|
||||
rel15->coreset.frequency_domain_resource[1] = phy_data->nr_sl_pscch_pdu.pscch_numrbs;
|
||||
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
|
||||
rel15->coreset.StartSymbolIndex = 1;
|
||||
rel15->coreset.RegBundleSize = 0;
|
||||
rel15->coreset.duration = phy_data->nr_sl_pscch_pdu.pscch_numsym;
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id = phy_data->nr_sl_pscch_pdu.pscch_dmrs_scrambling_id;
|
||||
rel15->coreset.scrambling_rnti = 1010;
|
||||
rel15->coreset.tci_present_in_dci = 0;
|
||||
|
||||
rel15->number_of_candidates = phy_data->nr_sl_pscch_pdu.l_subch;
|
||||
rel15->num_dci_options = 1;
|
||||
rel15->dci_length_options[0] = phy_data->nr_sl_pscch_pdu.sci_1a_length;
|
||||
// L now provides the number of PRBs used by PSCCH instead of the number of CCEs
|
||||
rel15->L[0] = phy_data->nr_sl_pscch_pdu.pscch_numrbs * phy_data->nr_sl_pscch_pdu.pscch_numsym;
|
||||
// This provides the offset of the candidate of PSCCH in RBs instead of CCEs
|
||||
rel15->CCE[0] = 0;
|
||||
|
||||
// Hold the channel estimates in frequency domain.
|
||||
int32_t pscch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16);
|
||||
__attribute__ ((aligned(16))) int32_t pscch_dl_ch_estimates[4*fp->nb_antennas_rx][pscch_est_size];
|
||||
//
|
||||
int16_t rsrp_dBm = 0;
|
||||
for (int sym=0; sym<rel15->coreset.duration;sym++) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc->nr_slot_rx,
|
||||
1+sym,
|
||||
rxdataF,
|
||||
link_type_sl,
|
||||
0,
|
||||
ue->common_vars.rxdata);
|
||||
|
||||
nr_pdcch_channel_estimation(ue,
|
||||
proc,
|
||||
1,
|
||||
1+sym,
|
||||
&rel15->coreset,
|
||||
fp->first_carrier_offset,
|
||||
rel15->BWPStart,
|
||||
pscch_est_size,
|
||||
pscch_dl_ch_estimates,
|
||||
rxdataF,
|
||||
&rsrp_dBm);
|
||||
}
|
||||
|
||||
nr_ue_pdcch_procedures(ue, proc, 1, pscch_est_size, pscch_dl_ch_estimates, phy_data, 0, rxdataF, &rsrp_dBm);
|
||||
LOG_D(NR_PHY,"returned from nr_ue_pdcch_procedures\n");
|
||||
}
|
||||
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SCI)
|
||||
{
|
||||
LOG_D(NR_PHY,"sci2_len = %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_len);
|
||||
LOG_D(NR_PHY,"sci2_beta_offset = %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_beta_offset);
|
||||
LOG_D(NR_PHY,"sci2_alpha_times_100= %d\n",phy_data->nr_sl_pssch_sci_pdu.sci2_alpha_times_100);
|
||||
LOG_D(NR_PHY,"pssch_targetCodeRate = %d\n",phy_data->nr_sl_pssch_sci_pdu.targetCodeRate);
|
||||
LOG_D(NR_PHY,"pssch_num_layers = %d\n",phy_data->nr_sl_pssch_sci_pdu.num_layers);
|
||||
LOG_D(NR_PHY,"dmrs_symbol_position = %d\n",phy_data->nr_sl_pssch_sci_pdu.dmrs_symbol_position);
|
||||
int num_dmrs = 0;
|
||||
for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++)
|
||||
num_dmrs += (phy_data->nr_sl_pssch_sci_pdu.dmrs_symbol_position >> s) & 1;
|
||||
LOG_D(NR_PHY,"num_dmrs = %d\n",num_dmrs);
|
||||
LOG_D(NR_PHY,"Nid = %x\n",phy_data->nr_sl_pssch_sci_pdu.Nid);
|
||||
|
||||
LOG_D(NR_PHY,"startrb = %d\n",phy_data->nr_sl_pssch_sci_pdu.startrb);
|
||||
LOG_D(NR_PHY,"pscch_numsym = %d\n",phy_data->nr_sl_pssch_sci_pdu.pscch_numsym);
|
||||
LOG_D(NR_PHY,"pscch_numrbs = %d\n",phy_data->nr_sl_pssch_sci_pdu.pscch_numrbs);
|
||||
LOG_D(NR_PHY,"num_subch= %d\n",phy_data->nr_sl_pssch_sci_pdu.num_subch);
|
||||
LOG_D(NR_PHY,"subchannel_size = %d\n",phy_data->nr_sl_pssch_sci_pdu.subchannel_size);
|
||||
LOG_D(NR_PHY,"l_subch = %d\n",phy_data->nr_sl_pssch_sci_pdu.l_subch);
|
||||
LOG_D(NR_PHY,"pssch_numsym = %d\n",phy_data->nr_sl_pssch_sci_pdu.pssch_numsym);
|
||||
LOG_D(NR_PHY,"sense_pssch = %d\n",phy_data->nr_sl_pssch_sci_pdu.sense_pssch);
|
||||
ue->slsch->harq_process->pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu;
|
||||
// compute number of REs containing SCI2
|
||||
int sci2_re = get_NREsci2_2(phy_data->nr_sl_pssch_sci_pdu.sci2_alpha_times_100,
|
||||
phy_data->nr_sl_pssch_sci_pdu.sci2_len,
|
||||
phy_data->nr_sl_pssch_sci_pdu.sci2_beta_offset,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pssch_numsym,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pscch_numsym,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pscch_numrbs,
|
||||
phy_data->nr_sl_pssch_sci_pdu.l_subch,
|
||||
phy_data->nr_sl_pssch_sci_pdu.subchannel_size,
|
||||
phy_data->nr_sl_pssch_sci_pdu.targetCodeRate,
|
||||
0);
|
||||
LOG_D(NR_PHY,"Starting slot FEP for SLSCH (symbol %d to %d) pscch_numsym %d pssch_numsym %d REs with SCI2 %d\n",
|
||||
1 + phy_data->nr_sl_pssch_sci_pdu.pscch_numsym, phy_data->nr_sl_pssch_sci_pdu.pssch_numsym,
|
||||
phy_data->nr_sl_pssch_sci_pdu.pscch_numsym, phy_data->nr_sl_pssch_sci_pdu.pssch_numsym, sci2_re);
|
||||
for (int sym=1+phy_data->nr_sl_pssch_sci_pdu.pscch_numsym; sym<=phy_data->nr_sl_pssch_sci_pdu.pssch_numsym;sym++) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
sym,
|
||||
rxdataF,
|
||||
link_type_sl);
|
||||
|
||||
}
|
||||
|
||||
nr_rx_pusch(NULL,
|
||||
ue,
|
||||
proc,
|
||||
phy_data,
|
||||
rxdataF_sz,
|
||||
rxdataF,
|
||||
0,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
0,
|
||||
&is_csi_rs_slot);
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH) {
|
||||
ack_nack_rcvd = calloc(phy_data->num_psfch_pdus, sizeof(ack_nack_rcvd));
|
||||
LOG_D(NR_PHY, "num_psfch_pdus: %d\n", phy_data->num_psfch_pdus);
|
||||
for (int k = 0; k < phy_data->num_psfch_pdus; k++) {
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu = &phy_data->psfch_pdu_list[k];
|
||||
LOG_D(NR_PHY, "%s start_symbol_index %d, sl_bwp_start %d, sequence_hop_flag %d, \
|
||||
second_hop_prb %d, prb %d, nr_of_symbols %d, initial_cyclic_shift %d, hopping_id %d, \
|
||||
group_hop_flag %d, freq_hop_flag %d, bit_len_harq %d\n",
|
||||
__FUNCTION__,
|
||||
psfch_pdu->start_symbol_index, psfch_pdu->sl_bwp_start,
|
||||
psfch_pdu->sequence_hop_flag, psfch_pdu->second_hop_prb, psfch_pdu->prb,
|
||||
psfch_pdu->nr_of_symbols, psfch_pdu->initial_cyclic_shift, psfch_pdu->hopping_id,
|
||||
psfch_pdu->group_hop_flag, psfch_pdu->freq_hop_flag, psfch_pdu->bit_len_harq);
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
psfch_pdu->start_symbol_index,
|
||||
rxdataF,
|
||||
link_type_sl);
|
||||
ack_nack_rcvd[k] = nr_ue_decode_psfch0(ue,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
rxdataF,
|
||||
psfch_pdu);
|
||||
}
|
||||
free(phy_data->psfch_pdu_list);
|
||||
phy_data->psfch_pdu_list = NULL;
|
||||
}
|
||||
NR_gNB_PUSCH *pssch_vars = &ue->pssch_vars[0];
|
||||
pssch_vars->ulsch_power_tot = 0;
|
||||
pssch_vars->ulsch_noise_power_tot = 0;
|
||||
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
|
||||
pssch_vars->ulsch_power[aarx] /= num_dmrs;
|
||||
pssch_vars->ulsch_power_tot += pssch_vars->ulsch_power[aarx];
|
||||
pssch_vars->ulsch_noise_power[aarx] /= num_dmrs;
|
||||
pssch_vars->ulsch_noise_power_tot += pssch_vars->ulsch_noise_power[aarx];
|
||||
}
|
||||
if (dB_fixed_x10(pssch_vars->ulsch_power_tot) < dB_fixed_x10(pssch_vars->ulsch_noise_power_tot) + ue->pssch_thres) {
|
||||
|
||||
LOG_D(NR_PHY,
|
||||
"PSSCH not detected in %d.%d (%d,%d,%d)\n",
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
dB_fixed_x10(pssch_vars->ulsch_power_tot),
|
||||
dB_fixed_x10(pssch_vars->ulsch_noise_power_tot),
|
||||
ue->pssch_thres);
|
||||
pssch_vars->ulsch_power_tot = pssch_vars->ulsch_noise_power_tot;
|
||||
pssch_vars->DTX = 1;
|
||||
//if (stats)
|
||||
// stats->ulsch_stats.DTX++;
|
||||
// nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1);
|
||||
//pssch_DTX++;
|
||||
// continue;
|
||||
} else {
|
||||
pssch_vars->DTX = 0;
|
||||
int totalDecode = nr_slsch_procedures(ue, frame_rx, nr_slot_rx, 0, proc, phy_data, is_csi_rs_slot, ack_nack_rcvd, phy_data->num_psfch_pdus);
|
||||
LOG_D(NR_PHY,
|
||||
"Total %d decoded PSSCH detected in %d.%d (%d,%d,%d)\n",
|
||||
totalDecode,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
dB_fixed_x10(pssch_vars->ulsch_power_tot),
|
||||
dB_fixed_x10(pssch_vars->ulsch_noise_power_tot),
|
||||
ue->pssch_thres);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UEscopeCopy(ue, commonRxdataF, rxdataF, sizeof(int32_t), fp->nb_antennas_rx, rxdataF_sz, 0);
|
||||
|
||||
@@ -270,6 +760,10 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc
|
||||
int frame_tx = proc->frame_tx;
|
||||
int tx_action = 0;
|
||||
|
||||
const char *sl_tx_actions[] = {"PSBCH", "PSCCH_PSSCH", "PSCCH_PSSCH_PSFCH", "PSCCH_PSSCH_CSI_RS"};
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
LOG_D(NR_PHY, "Generating %s (%d.%d)\n", sl_tx_actions[phy_data->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH], frame_tx, slot_tx);
|
||||
}
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
|
||||
|
||||
@@ -927,7 +927,7 @@ int main(int argc, char **argv)
|
||||
|
||||
init_nr_ue_transport(UE);
|
||||
|
||||
UE_mac = nr_l2_init_ue(0);
|
||||
UE_mac = nr_l2_init_ue(0, NULL);
|
||||
ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu));
|
||||
|
||||
UE->if_inst = nr_ue_if_module_init(0);
|
||||
|
||||
@@ -86,6 +86,27 @@ void deref_sched_response(int _)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req, int *nb_ok)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||
int r = rdata->segment_r;
|
||||
|
||||
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
|
||||
ulsch_harq->processedSegments++;
|
||||
|
||||
if (decodeSuccess) {
|
||||
memcpy(ulsch_harq->b+rdata->offset,
|
||||
ulsch_harq->c[r],
|
||||
rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
|
||||
}
|
||||
|
||||
// if all segments are done
|
||||
if (rdata->nbSegments == ulsch_harq->processedSegments)
|
||||
return *nb_ok == rdata->nbSegments;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nrUE_params_t nrUE_params;
|
||||
|
||||
nrUE_params_t *get_nrUE_params(void) {
|
||||
|
||||
@@ -885,7 +885,7 @@ int main(int argc, char *argv[])
|
||||
init_nr_ue_transport(UE);
|
||||
|
||||
//Configure UE
|
||||
NR_UE_MAC_INST_t* UE_mac = nr_l2_init_ue(0);
|
||||
NR_UE_MAC_INST_t* UE_mac = nr_l2_init_ue(0, NULL);
|
||||
|
||||
ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu));
|
||||
|
||||
|
||||
@@ -103,6 +103,54 @@ uint32_t nr_compute_tbs(uint16_t Qm,
|
||||
LOG_D(NR_MAC, "Ninfo %u nbp_re %d nb_re %d Qm %d, R %d, tbs %d bits\n", Ninfo, nbp_re, nb_re, Qm, R, nr_tbs);
|
||||
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, "In %s: Ninfo %u nb_re %d Qm %d, R %d, tbs %d bits\n", __FUNCTION__, 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, uint8_t Nl)
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <stdbool.h>
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/collection/linear_alloc.h"
|
||||
|
||||
#include "NR_CellGroupConfig.h"
|
||||
|
||||
#define MAX_FRAME_NUMBER 0x400
|
||||
@@ -109,6 +111,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))
|
||||
@@ -132,6 +142,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
|
||||
@@ -432,6 +453,22 @@ typedef struct {
|
||||
#define UL_SCH_LCID_PADDING 0x3F
|
||||
|
||||
#define NR_MAX_NUM_LCGID 8
|
||||
|
||||
#define SL_SCH_LCID_SCCH_PC5_NOT_PROT 0 // SCCH carrying PC5-S messages that are not protected
|
||||
#define SL_SCH_LCID_SCCH_PC5_DSMC 1 // SCCH carrying PC5-S messages "Direct Security Mode Command" and "Direct Security Mode Complete"
|
||||
#define SL_SCH_LCID_SCCH_PC5_PROT 2 // SCCH carrying other PC5-S messages that are protected
|
||||
#define SL_SCH_LCID_SCCH_PC5_RRC 3 // SCCH carrying PC5-RRC messages
|
||||
#define SL_SCH_LCID_4_19 4 // 4–19 Identity of the logical channel
|
||||
#define SL_SCH_LCID_20_55 20 // 20–55 Reserved
|
||||
#define SL_SCH_LCID_SCCH_RRC_SL_RLC0 56 // SCCH carrying RRC messages delivered via SL-RLC0 as specified in TS 38.331 [5]
|
||||
#define SL_SCH_LCID_SCCH_RRC_SL_RLC1 57 // SCCH carrying RRC message delivered via SL-RLC1 as specified in TS 38.331 [5]
|
||||
#define SL_SCH_LCID_SCCH_SL_DISCOVERY 58 // SCCH for Sidelink Discovery Messages
|
||||
#define SL_SCH_LCID_SL_INTER_UE_COORD_REQ 59 // Sidelink Inter-UE Coordination Request
|
||||
#define SL_SCH_LCID_SL_INTER_UE_COORD_INFO 60 // Sidelink Inter-UE Coordination Information
|
||||
#define SL_SCH_LCID_SL_DRX_CMD 61 // Sidelink DRX Command
|
||||
#define SL_SCH_LCID_SL_CSI_REPORT 62 // Sidelink CSI Reporting
|
||||
#define SL_SCH_LCID_SL_PADDING 63 // Padding
|
||||
|
||||
#define MAX_RLC_SDU_SUBHEADER_SIZE 3
|
||||
|
||||
//=========
|
||||
@@ -522,6 +559,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,
|
||||
@@ -641,5 +697,21 @@ typedef enum {
|
||||
RA_2_STEP = 1,
|
||||
} nr_ra_type_t;
|
||||
|
||||
typedef struct NR_bler_stats {
|
||||
frame_t last_frame;
|
||||
float bler;
|
||||
uint8_t mcs;
|
||||
uint64_t rounds[8];
|
||||
} NR_bler_stats_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__ */
|
||||
|
||||
|
||||
@@ -39,6 +39,18 @@
|
||||
|
||||
#define reserved 0xffff
|
||||
|
||||
|
||||
void reverse_n_bits(uint8_t *value, uint16_t bitlen) {
|
||||
uint16_t j;
|
||||
uint8_t i;
|
||||
for(j = bitlen - 1,i = 0; j > i; j--, i++) {
|
||||
if(((*value>>j)&1) != ((*value>>i)&1)) {
|
||||
*value ^= (1<<j);
|
||||
*value ^= (1<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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,
|
||||
@@ -79,6 +91,62 @@ uint32_t get_long_bsr_value(int idx)
|
||||
return NR_LONG_BSR_TABLE[idx];
|
||||
}
|
||||
|
||||
// #define DEBUG_DCI
|
||||
// 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}};
|
||||
|
||||
// start symbols for SSB types A,B,C,D,E
|
||||
static const uint16_t symbol_ssb_AC[8] = {2, 8, 16, 22, 30, 36, 44, 50};
|
||||
static const uint16_t symbol_ssb_BD[64] = {4, 8, 16, 20, 32, 36, 44, 48, 60, 64, 72, 76, 88, 92, 100, 104,
|
||||
@@ -90,6 +158,8 @@ static const uint16_t symbol_ssb_E[64] = {8, 12, 16, 20, 32, 36, 40, 44,
|
||||
288, 292, 296, 300, 312, 316, 320, 324, 344, 348, 352, 356, 368, 372, 376, 380,
|
||||
400, 404, 408, 412, 424, 428, 432, 436, 456, 460, 464, 468, 480, 484, 488, 492};
|
||||
|
||||
const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
|
||||
|
||||
// Table 6.3.3.1-5 (38.211) NCS for preamble formats with delta_f_RA = 1.25 KHz
|
||||
static const uint16_t NCS_unrestricted_delta_f_RA_125[16] = {0, 13, 15, 18, 22, 26, 32, 38, 46, 59, 76, 93, 119, 167, 279, 419};
|
||||
static const uint16_t NCS_restricted_TypeA_delta_f_RA_125[15] =
|
||||
@@ -3260,6 +3330,45 @@ 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)
|
||||
{
|
||||
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 || num_dl_sched <= 3) // above threshold or no activity
|
||||
new_mcs -= 1;
|
||||
// else we are within threshold boundaries
|
||||
|
||||
new_mcs = max(new_mcs, bler_options->min_mcs);
|
||||
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;
|
||||
}
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type)
|
||||
{
|
||||
|
||||
@@ -4959,3 +5068,228 @@ int get_j_for_k2(int mu)
|
||||
AssertFatal(mu >= 0 && mu < sizeofArray(j_table), "Invalid numerology %d\n", mu);
|
||||
return j_table[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;
|
||||
}
|
||||
|
||||
#define MAX_EL_213_9_3_2 19
|
||||
const float tab38_213_9_3_2[MAX_EL_213_9_3_2] = {1.125,1.250,1.375,1.625,1.750,2.000,2.250,2.500,2.875,3.125,3.500,4.000,5.000,6.250,8.000,10.000,12.625,15.875,20.000};
|
||||
|
||||
int get_NREsci2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int mcs,
|
||||
const int mcs_tb_ind) {
|
||||
|
||||
float Osci2 = (float)sci2_payload_len;
|
||||
AssertFatal(sci2_beta_offset < MAX_EL_213_9_3_2, "illegal sci2_beta_offset %d\n",sci2_beta_offset);
|
||||
float beta_offset_sci2 = tab38_213_9_3_2[sci2_beta_offset];
|
||||
|
||||
|
||||
uint32_t R10240 = nr_get_code_rate_ul(mcs,mcs_tb_ind);
|
||||
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/((float)R10240/5120));
|
||||
float tmp2 = 12.0*pssch_numsym;
|
||||
int N_REsci1 = 12*pscch_numrbs*pscch_numsym;
|
||||
tmp2 *= l_subch*subchannel_size;
|
||||
tmp2 -= N_REsci1;
|
||||
tmp2 *= ((float)sci2_alpha/100.0);
|
||||
int min_val = min(tmp,(int)ceil(tmp2));
|
||||
uint8_t gamma = 12 - (min_val % 12);
|
||||
return min_val + (gamma % 12);
|
||||
|
||||
}
|
||||
int get_NREsci2_2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int target_coderate,
|
||||
const int mcs_table_index) {
|
||||
|
||||
float Osci2 = (float)sci2_payload_len;
|
||||
AssertFatal(sci2_beta_offset < MAX_EL_213_9_3_2, "illegal sci2_beta_offset %d\n",sci2_beta_offset);
|
||||
float beta_offset_sci2 = tab38_213_9_3_2[sci2_beta_offset];
|
||||
|
||||
uint32_t R10240 = get_softmodem_params()->sl_mode ? nr_get_code_rate_ul(1, mcs_table_index) : target_coderate;
|
||||
uint32_t tmp = (uint32_t)ceil((Osci2 + 24)*beta_offset_sci2/((float)R10240/5120));
|
||||
float tmp2 = 12.0*pssch_numsym;
|
||||
int N_REsci1 = 12*pscch_numrbs*pscch_numsym;
|
||||
tmp2 *= l_subch*subchannel_size;
|
||||
tmp2 -= N_REsci1;
|
||||
tmp2 *= ((float)sci2_alpha/100.0);
|
||||
int min_val = min(tmp,(int)ceil(tmp2));
|
||||
uint8_t gamma = 12 - (min_val % 12);
|
||||
return min_val + (gamma % 12);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,36 @@ typedef enum {
|
||||
pusch_len2 = 2
|
||||
} pusch_maxLength_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 min_mcs;
|
||||
uint8_t max_mcs;
|
||||
uint8_t harq_round_max;
|
||||
} NR_bler_options_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t bwpStart;
|
||||
uint16_t bwpSize;
|
||||
@@ -123,6 +153,7 @@ void config_frame_structure(int mu,
|
||||
uint8_t tdd_period,
|
||||
uint8_t frame_type,
|
||||
frame_structure_t *fs);
|
||||
int get_first_ul_slot(const frame_structure_t *fs, bool mixed);
|
||||
|
||||
NR_PDSCH_TimeDomainResourceAllocationList_t *get_dl_tdalist(const NR_UE_DL_BWP_t *DL_BWP,
|
||||
int controlResourceSetId,
|
||||
@@ -198,6 +229,14 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
|
||||
uint8_t unpaired,
|
||||
frequency_range_t);
|
||||
|
||||
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx);
|
||||
|
||||
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_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrecoder);
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type);
|
||||
@@ -219,6 +258,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);
|
||||
@@ -334,4 +378,37 @@ int get_delta_for_k2(int mu);
|
||||
|
||||
int get_j_for_k2(int mu);
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
int get_NREsci2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int mcs,
|
||||
const int mcs_tb_ind);
|
||||
|
||||
int get_NREsci2_2(const int sci2_alpha,
|
||||
const int sci2_payload_len,
|
||||
const int sci2_beta_offset,
|
||||
const int pssch_numsym,
|
||||
const int pscch_numsym,
|
||||
const int pscch_numrbs,
|
||||
const int l_subch,
|
||||
const int subchannel_size,
|
||||
const int target_coderate,
|
||||
const int mcs_table_index);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -259,3 +259,25 @@ bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs)
|
||||
const tdd_period_config_t *pc = &fs->period_cfg;
|
||||
return pc->tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the first UL slot index in period
|
||||
* @param fs frame structure
|
||||
* @param mixed indicates whether to include in the count also mixed slot with UL symbols or only full UL slot
|
||||
* @return slot index
|
||||
*/
|
||||
int get_first_ul_slot(const frame_structure_t *fs, bool mixed)
|
||||
{
|
||||
DevAssert(fs);
|
||||
|
||||
if (fs->frame_type == TDD) {
|
||||
for (int i = 0; i < fs->numb_slots_period; i++) {
|
||||
if ((mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // FDD
|
||||
}
|
||||
|
||||
|
||||
118
openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h
Normal file
118
openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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_mac_extern.h
|
||||
* \brief NR mac externs
|
||||
* \author Navid Nikaein, Raymond Knopp, Guido Casati
|
||||
* \date 2019
|
||||
* \version 1.0
|
||||
* \email navid.nikaein@eurecom.fr, guido.casati@iis.fraunhofer.de
|
||||
* @ingroup _mac
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __NR_MAC_EXTERN_H__
|
||||
#define __NR_MAC_EXTERN_H__
|
||||
|
||||
#include "common/ran_context.h"
|
||||
#include "nr_mac.h"
|
||||
|
||||
/*#include "PHY/defs_common.h"*/
|
||||
|
||||
extern const uint8_t nr_slots_per_frame[5];
|
||||
|
||||
extern dci_pdu_rel15_t *def_dci_pdu_rel15;
|
||||
|
||||
/* Scheduler */
|
||||
extern RAN_CONTEXT_t RC;
|
||||
extern uint8_t nfapi_mode;
|
||||
|
||||
extern const uint32_t NR_SHORT_BSR_TABLE[NR_SHORT_BSR_TABLE_SIZE];
|
||||
extern const uint32_t NR_LONG_BSR_TABLE[NR_LONG_BSR_TABLE_SIZE];
|
||||
|
||||
// Type0-PDCCH search space
|
||||
extern const int32_t table_38213_13_1_c1[16];
|
||||
extern const int32_t table_38213_13_1_c2[16];
|
||||
extern const int32_t table_38213_13_1_c3[16];
|
||||
extern const int32_t table_38213_13_1_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_2_c1[16];
|
||||
extern const int32_t table_38213_13_2_c2[16];
|
||||
extern const int32_t table_38213_13_2_c3[16];
|
||||
extern const int32_t table_38213_13_2_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_3_c1[16];
|
||||
extern const int32_t table_38213_13_3_c2[16];
|
||||
extern const int32_t table_38213_13_3_c3[16];
|
||||
extern const int32_t table_38213_13_3_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_4_c1[16];
|
||||
extern const int32_t table_38213_13_4_c2[16];
|
||||
extern const int32_t table_38213_13_4_c3[16];
|
||||
extern const int32_t table_38213_13_4_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_5_c1[16];
|
||||
extern const int32_t table_38213_13_5_c2[16];
|
||||
extern const int32_t table_38213_13_5_c3[16];
|
||||
extern const int32_t table_38213_13_5_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_6_c1[16];
|
||||
extern const int32_t table_38213_13_6_c2[16];
|
||||
extern const int32_t table_38213_13_6_c3[16];
|
||||
extern const int32_t table_38213_13_6_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_7_c1[16];
|
||||
extern const int32_t table_38213_13_7_c2[16];
|
||||
extern const int32_t table_38213_13_7_c3[16];
|
||||
extern const int32_t table_38213_13_7_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_8_c1[16];
|
||||
extern const int32_t table_38213_13_8_c2[16];
|
||||
extern const int32_t table_38213_13_8_c3[16];
|
||||
extern const int32_t table_38213_13_8_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_9_c1[16];
|
||||
extern const int32_t table_38213_13_9_c2[16];
|
||||
extern const int32_t table_38213_13_9_c3[16];
|
||||
extern const int32_t table_38213_13_9_c4[16];
|
||||
|
||||
extern const int32_t table_38213_13_10_c1[16];
|
||||
extern const int32_t table_38213_13_10_c2[16];
|
||||
extern const int32_t table_38213_13_10_c3[16];
|
||||
extern const int32_t table_38213_13_10_c4[16];
|
||||
|
||||
extern const float table_38213_13_11_c1[16];
|
||||
extern const int32_t table_38213_13_11_c2[16];
|
||||
extern const float table_38213_13_11_c3[16];
|
||||
extern const int32_t table_38213_13_11_c4[16];
|
||||
|
||||
extern const float table_38213_13_12_c1[16];
|
||||
extern const int32_t table_38213_13_12_c2[16];
|
||||
extern const float table_38213_13_12_c3[16];
|
||||
|
||||
extern const int32_t table_38213_10_1_1_c2[5];
|
||||
|
||||
extern const char table_38211_6_3_1_5_1[6][2][1];
|
||||
extern const char table_38211_6_3_1_5_2[28][4][1];
|
||||
extern const char table_38211_6_3_1_5_3[28][4][1];
|
||||
extern const char table_38211_6_3_1_5_4[3][2][2];
|
||||
extern const char table_38211_6_3_1_5_5[22][4][2];
|
||||
#endif //DEF_H
|
||||
@@ -1794,7 +1794,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
|
||||
@@ -2800,3 +2800,4 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
AssertFatal(!ret, "mutex failed %d\n", ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,66 @@
|
||||
*/
|
||||
|
||||
#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}}
|
||||
|
||||
/*Sidelink HARQ configuration parameters */
|
||||
#define SL_CONFIG_STRING_SL_CONFIGUREDGRANT_LIST "sl_ConfiguredGrantConfig"
|
||||
#define SL_CONFIG_STRING_SL_CONFIGUREDGRANT_NROFHARQ_PROCESSES "sl_NrOfHARQ_Processes"
|
||||
#define SL_CONFIG_STRING_SL_CONFIGUREDGRANT_HARQ_PROCID_OFFSET "sl_HARQ_ProcID_offset"
|
||||
#define SL_CONFIG_STRING_SL_CONFIGUREDGRANT_HARQ_PERIODIC_RRI "sl_periodic_rsc_rsr_interval"
|
||||
#define SL_CONFIGUREDGRANT_DESC(sl_harq_info) { \
|
||||
{SL_CONFIG_STRING_SL_CONFIGUREDGRANT_NROFHARQ_PROCESSES, NULL, 0, .u16ptr=&sl_harq_info->sl_Num_HARQ_Processes, .defuintval=0, TYPE_UINT16, 0}, \
|
||||
{SL_CONFIG_STRING_SL_CONFIGUREDGRANT_HARQ_PROCID_OFFSET, NULL, 0, .u16ptr=&sl_harq_info->sl_HARQ_ProcID_offset, .defuintval=0, TYPE_UINT16, 0}, \
|
||||
{SL_CONFIG_STRING_SL_CONFIGUREDGRANT_HARQ_PERIODIC_RRI, NULL, 0, .u16ptr=&sl_harq_info->sl_Periodic_RRI, .defuintval=0, TYPE_UINT16, 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;
|
||||
|
||||
typedef struct sl_harq_info {
|
||||
uint16_t sl_Num_HARQ_Processes;
|
||||
uint16_t sl_HARQ_ProcID_offset;
|
||||
uint16_t sl_Periodic_RRI;
|
||||
} sl_harq_info_t;
|
||||
|
||||
void sl_ue_mac_free(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
@@ -33,8 +91,10 @@ void sl_ue_mac_free(NR_UE_MAC_INST_t *mac)
|
||||
|
||||
//Allocated by MAC only in case of SYNC_REF_UE
|
||||
//else it is freed as part of RRC pre-config structure
|
||||
if (syncsource == SL_SYNC_SOURCE_SYNC_REF_UE) {
|
||||
if (syncsource == SL_SYNC_SOURCE_SYNC_REF_UE &&
|
||||
mac->SL_MAC_PARAMS->sl_TDD_config) {
|
||||
ASN_STRUCT_FREE (asn_DEF_NR_TDD_UL_DL_Pattern, mac->SL_MAC_PARAMS->sl_TDD_config);
|
||||
mac->SL_MAC_PARAMS->sl_TDD_config = NULL;
|
||||
}
|
||||
|
||||
fapi_nr_max_tdd_periodicity_t *tdd_list =
|
||||
@@ -132,6 +192,8 @@ static void sl_prepare_phy_config(int module_id,
|
||||
//FREQSHIFT_7P5KHZ is DISABLED
|
||||
phycfg->sl_carrier_config.sl_frequency_shift_7p5khz = 0;
|
||||
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];
|
||||
@@ -235,10 +297,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,
|
||||
@@ -305,6 +369,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 +380,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 +405,44 @@ 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);
|
||||
sl_mac->mac_tx_params.sl_thresh_rsrp = (-128 + (*sl_ue_selected_config->sl_Thres_RSRP_List_r16->list.array[0] - 1) * 2);
|
||||
long sl_TxPercentage = txpool->sl_TxPercentageList_r16->list.array[0]->sl_TxPercentage_r16;
|
||||
switch (sl_TxPercentage)
|
||||
{
|
||||
case NR_SL_TxPercentageConfig_r16__sl_TxPercentage_r16_p20:
|
||||
sl_mac->mac_tx_params.sl_res_ratio = 20.0 / 100;
|
||||
break;
|
||||
case NR_SL_TxPercentageConfig_r16__sl_TxPercentage_r16_p35:
|
||||
sl_mac->mac_tx_params.sl_res_ratio = 35.0 / 100;
|
||||
break;
|
||||
case NR_SL_TxPercentageConfig_r16__sl_TxPercentage_r16_p50:
|
||||
sl_mac->mac_tx_params.sl_res_ratio = 50.0 / 100;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC, "Incorrect sl_TxPercentage provided, !!!");
|
||||
break;
|
||||
}
|
||||
LOG_D(NR_MAC, "sl_thresh_rsrp %d rri %i sl_ResourceReservePeriod1 %ld, i %d, sensing_window_ms %d, selection_window %d\n",
|
||||
sl_mac->mac_tx_params.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,
|
||||
@@ -372,8 +472,19 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
|
||||
sl_mac->sl_TDD_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
|
||||
|
||||
config_frame_structure(get_softmodem_params()->numerology,
|
||||
sl_mac->sl_TDD_config,
|
||||
get_tdd_period_idx(sl_mac->sl_TDD_config),
|
||||
TDD,
|
||||
&mac->frame_structure);
|
||||
|
||||
sl_set_tdd_config_nr_ue(&sl_mac->sl_phy_config.sl_config_req.tdd_table,
|
||||
get_softmodem_params()->numerology,
|
||||
&sl_mac->sl_TDD_config->pattern1);
|
||||
|
||||
// Sync source is identified, timing needs to be adjusted.
|
||||
sl_mac->timing_acquired = true;
|
||||
mac->is_synced = true;
|
||||
}
|
||||
|
||||
//Do not copy TDD config yet as SYNC source is not yet found
|
||||
@@ -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 = get_first_ul_slot(&mac->frame_structure, false);
|
||||
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
}
|
||||
|
||||
memset(mac->ulsch_slot_bitmap, 0, sizeof(mac->ulsch_slot_bitmap));
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -483,6 +655,7 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
sl_config->sl_sync_source.rx_slss_id = rx_slss_id;
|
||||
|
||||
sl_mac->timing_acquired = true;
|
||||
mac->is_synced = true;
|
||||
|
||||
sl_mac->rx_sl_bch.status = 1;
|
||||
sl_mac->rx_sl_bch.slss_id = rx_slss_id;
|
||||
@@ -519,16 +692,152 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
NR_NUMBER_OF_SUBFRAMES_PER_FRAME*(1<<cfg->sl_bwp_config.sl_scs);
|
||||
}
|
||||
|
||||
config_frame_structure(get_softmodem_params()->numerology,
|
||||
sl_mac->sl_TDD_config,
|
||||
get_tdd_period_idx(sl_mac->sl_TDD_config),
|
||||
TDD,
|
||||
&mac->frame_structure);
|
||||
|
||||
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 = get_first_ul_slot(&mac->frame_structure, false);
|
||||
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
}
|
||||
|
||||
memset(mac->ulsch_slot_bitmap, 0, sizeof(mac->ulsch_slot_bitmap));
|
||||
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, sizeof(SL_CRI_RS_INFO)/sizeof(paramdef_t), aprefix);
|
||||
|
||||
char aprefix1[MAX_OPTNAME_SIZE*2 + 8];
|
||||
sl_harq_info_t *sl_harq_info = (sl_harq_info_t*)malloc16_clear(sizeof(sl_harq_info_t));
|
||||
paramdef_t SL_HARQ_INFO[] = SL_CONFIGUREDGRANT_DESC(sl_harq_info);
|
||||
sprintf(aprefix1, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0, SL_CONFIG_STRING_SL_CONFIGUREDGRANT_LIST, 0);
|
||||
config_get(config_get_if(), SL_HARQ_INFO, sizeof(SL_HARQ_INFO)/sizeof(paramdef_t), aprefix1);
|
||||
sl_mac->sl_Num_HARQ_Processes = sl_harq_info->sl_Num_HARQ_Processes;
|
||||
sl_mac->sl_HARQ_ProcID_offset = sl_harq_info->sl_HARQ_ProcID_offset;
|
||||
sl_mac->sl_Periodic_RRI = sl_harq_info->sl_Periodic_RRI;
|
||||
|
||||
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, sizeof(SL_CONFIG_RSR_INFO) / sizeof(paramdef_t), 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
/* MAC */
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "mac_defs_sl.h"
|
||||
|
||||
/* RRC */
|
||||
@@ -61,6 +62,7 @@
|
||||
#include "NR_ServingCellConfig.h"
|
||||
#include "NR_MeasConfig.h"
|
||||
#include "NR_ServingCellConfigCommonSIB.h"
|
||||
#include "NR_SL-BWP-ConfigCommon-r16.h"
|
||||
|
||||
|
||||
// ==========
|
||||
@@ -459,6 +461,264 @@ typedef struct ssb_list_info {
|
||||
int nb_ssb_per_index[MAX_NB_SSB];
|
||||
} ssb_list_info_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;
|
||||
|
||||
typedef enum {
|
||||
NR_SL_V2X_LBT_DISABLED = 0,
|
||||
NR_SL_V2X_LBT_TYPE2,
|
||||
NR_SL_V2X_LBT_TYPE1,
|
||||
} nr_sl_v2x_lbt_mode_t;
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
nr_sl_v2x_lbt_mode_t mode;
|
||||
int16_t energy_detection_threshold_dbm;
|
||||
uint8_t max_consecutive_failures;
|
||||
uint8_t consecutive_failures;
|
||||
uint32_t attempts;
|
||||
uint32_t failures;
|
||||
uint32_t successes;
|
||||
frameslot_t last_failure;
|
||||
} nr_sl_v2x_lbt_state_t;
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
uint16_t pool_id;
|
||||
uint16_t c_resel;
|
||||
uint16_t c_resel_initial;
|
||||
uint16_t p_rsvp_slots;
|
||||
int64_t next_abs_slot;
|
||||
sl_resource_info_t resource;
|
||||
sl_resource_info_t current_resource;
|
||||
uint32_t reselections;
|
||||
uint32_t kept;
|
||||
uint32_t released;
|
||||
} nr_sl_v2x_sps_state_t;
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
nr_sl_v2x_lbt_state_t lbt;
|
||||
nr_sl_v2x_sps_state_t sps;
|
||||
} nr_sl_v2x_scheduler_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;
|
||||
|
||||
|
||||
typedef struct nr_lcordered_info_s {
|
||||
// logical channels ids ordered as per priority
|
||||
NR_LogicalChannelIdentity_t lcid;
|
||||
@@ -597,6 +857,12 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon;
|
||||
frame_structure_t frame_structure;
|
||||
|
||||
// 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;
|
||||
|
||||
/* Random Access */
|
||||
/// CRNTI
|
||||
uint16_t crnti;
|
||||
@@ -656,6 +922,35 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
|
||||
//SIDELINK MAC PARAMETERS
|
||||
sl_nr_ue_mac_params_t *SL_MAC_PARAMS;
|
||||
|
||||
// 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;
|
||||
bool is_synced;
|
||||
|
||||
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
|
||||
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
|
||||
nr_sl_v2x_scheduler_t sl_v2x_scheduler;
|
||||
|
||||
/// 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;
|
||||
|
||||
// PUCCH closed loop power control state
|
||||
int G_b_f_c;
|
||||
bool pucch_power_control_initialized;
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
#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_ue_sci.h"
|
||||
#include <pthread.h>
|
||||
#include "mac_defs.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 +48,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
|
||||
@@ -96,6 +118,7 @@ typedef struct SL_ResourcePool_params {
|
||||
//This holds the structure from RRC
|
||||
NR_SL_ResourcePool_r16_t *respool;
|
||||
|
||||
BIT_STRING_t phy_sl_bitmap;
|
||||
//NUM Subchannels in this resource pool
|
||||
uint16_t num_subch;
|
||||
|
||||
@@ -105,6 +128,13 @@ typedef struct SL_ResourcePool_params {
|
||||
//SCI-1A configuration according to RESPOOL configured.
|
||||
sidelink_sci_format_1a_fields_t sci_1a;
|
||||
|
||||
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 +161,23 @@ 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
|
||||
int sl_thresh_rsrp; // A threshold in dBm used for sensing based UE autonomous resource selection
|
||||
float sl_res_ratio; /* The percentage threshold to indicate the
|
||||
minimum number of candidate single-slot
|
||||
resources to be selected using sensing procedure.
|
||||
*/
|
||||
} nr_sl_transmission_params_t;
|
||||
|
||||
typedef struct sl_stored_tti_req {
|
||||
uint32_t sl_action;
|
||||
int frame;
|
||||
@@ -148,6 +195,29 @@ 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 grant harq parameters
|
||||
uint8_t sl_Num_HARQ_Processes;
|
||||
uint8_t sl_HARQ_ProcID_offset;
|
||||
uint16_t sl_Periodic_RRI;
|
||||
|
||||
//Configured from RRC
|
||||
uint32_t sl_MaxNumConsecutiveDTX;
|
||||
@@ -177,6 +247,7 @@ typedef struct sl_nr_ue_mac_params {
|
||||
|
||||
uint16_t decoded_DFN;
|
||||
uint16_t decoded_slot;
|
||||
NR_bler_options_t sl_bler;
|
||||
|
||||
uint32_t N_SL_SLOTS;
|
||||
uint16_t N_SSB_16frames;
|
||||
|
||||
@@ -37,13 +37,34 @@
|
||||
#include "oai_asn1.h"
|
||||
#include "RRC/NR_UE/rrc_defs.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
#include "executables/nr-uesoftmodem.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 */
|
||||
|
||||
// 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;
|
||||
|
||||
/**\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 nr_ue_init_mac_sl(NR_UE_MAC_INST_t *mac, ueinfo_t *ueinfo);
|
||||
|
||||
NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup);
|
||||
NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup);
|
||||
@@ -95,7 +116,7 @@ void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id);
|
||||
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)*/
|
||||
@@ -150,6 +171,21 @@ typedef struct {
|
||||
enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr;
|
||||
} type_bsr_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t phr_len;
|
||||
uint sdu_length_total;
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE phr;
|
||||
type_bsr_t bsr;
|
||||
uint8_t *pdu_end;
|
||||
uint8_t *end_for_tailer;
|
||||
uint8_t *cur_ptr;
|
||||
uint num_sdus;
|
||||
// int highest_priority = 16;
|
||||
// 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;
|
||||
|
||||
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom,
|
||||
@@ -329,6 +365,8 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfiguration,
|
||||
uint8_t sync_source);
|
||||
|
||||
uint8_t count_on_bits(uint8_t* buf, size_t size);
|
||||
|
||||
void nr_rrc_mac_transmit_slss_req(module_id_t module_id,
|
||||
uint8_t *sl_mib_payload,
|
||||
uint16_t tx_slss_id,
|
||||
@@ -338,6 +376,8 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
uint16_t rx_slss_id,
|
||||
uint8_t *sl_mib);
|
||||
|
||||
void nr_sl_params_read_conf(module_id_t module_id);
|
||||
|
||||
void sl_prepare_psbch_payload(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t *bits_0_to_7, uint8_t *bits_8_to_11,
|
||||
uint8_t mu, uint8_t L, uint8_t Y);
|
||||
@@ -357,8 +397,332 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
|
||||
@returns int : 0 or Sidelink slot type */
|
||||
int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int nr_slot, uint8_t frame_duplex_type);
|
||||
|
||||
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,int cc_id,frame_t frame, int slot, sl_nr_sci_indication_pdu_t *sci,void *phy_data);
|
||||
|
||||
void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac);
|
||||
|
||||
void nr_ue_sl_v2x_init_scheduler(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
sl_resource_info_t *nr_ue_sl_v2x_select_resource(NR_UE_MAC_INST_t *mac,
|
||||
const frameslot_t *frame_slot,
|
||||
sl_sidelink_slot_type_t slot_type);
|
||||
|
||||
bool nr_ue_sl_v2x_lbt_allows_tx(NR_UE_MAC_INST_t *mac,
|
||||
const sl_resource_info_t *resource,
|
||||
const frameslot_t *frame_slot);
|
||||
|
||||
void nr_ue_sl_v2x_notify_tx_result(NR_UE_MAC_INST_t *mac,
|
||||
const sl_resource_info_t *resource,
|
||||
const frameslot_t *frame_slot,
|
||||
bool transmitted);
|
||||
|
||||
NR_SearchSpace_t *get_common_search_space(const NR_UE_MAC_INST_t *mac, const NR_SearchSpaceId_t ss_id);
|
||||
|
||||
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);
|
||||
|
||||
size_t dump_mac_stats_sl(NR_UE_MAC_INST_t *mac, char *output, size_t strlen, bool reset_rsrp);
|
||||
|
||||
void handle_nr_ue_sl_harq(module_id_t mod_id, frame_t frame, sub_frame_t slot, sl_nr_slsch_pdu_t *rx_slsch_pdu, uint16_t src_id);
|
||||
|
||||
void abort_nr_ue_sl_harq(NR_UE_MAC_INST_t *mac, int8_t harq_pid, NR_SL_UE_info_t *UE_info);
|
||||
|
||||
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(const frame_structure_t *fs, 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);
|
||||
|
||||
bool is_sl_slot(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint16_t phy_map_sz, uint64_t abs_slot);
|
||||
|
||||
void validate_selected_sl_slot(NR_UE_MAC_INST_t *mac, 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 nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes);
|
||||
|
||||
void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
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);
|
||||
|
||||
#endif
|
||||
/** @}*/
|
||||
|
||||
@@ -51,7 +51,43 @@ 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_sl(NR_UE_MAC_INST_t *mac, ueinfo_t* ueinfo)
|
||||
{
|
||||
int k = 0;
|
||||
|
||||
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);
|
||||
nr_ue_sl_v2x_init_scheduler(mac);
|
||||
|
||||
if (ueinfo != NULL) {
|
||||
mac->src_id = ueinfo->srcid;
|
||||
LOG_D(NR_MAC, "srcid %d\n", ueinfo->srcid);
|
||||
}
|
||||
|
||||
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_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);
|
||||
@@ -72,6 +108,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
mac->ntn_ta.ntn_params_changed = false;
|
||||
initNotifiedFIFO(&mac->input_nf);
|
||||
reset_mac_inst(mac);
|
||||
nr_ue_init_mac_sl(mac, ueinfo);
|
||||
|
||||
// need to inizialize because might not been setup (optional timer)
|
||||
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
|
||||
@@ -130,7 +167,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 instance_id)
|
||||
NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id, ueinfo_t *ueinfo)
|
||||
{
|
||||
AssertFatal(instance_id < MAX_NUM_NR_UE_INST, "instance_id %d is out of range\n", instance_id);
|
||||
AssertFatal(nr_ue_mac_inst[instance_id] == NULL, "MAC instance %d already initialized\n", instance_id);
|
||||
@@ -138,7 +175,7 @@ NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id)
|
||||
|
||||
NR_UE_MAC_INST_t *mac = nr_ue_mac_inst[instance_id];
|
||||
mac->ue_id = instance_id;
|
||||
nr_ue_init_mac(mac);
|
||||
nr_ue_init_mac(mac, ueinfo);
|
||||
int ret = pthread_mutex_init(&mac->if_mutex, NULL);
|
||||
AssertFatal(ret == 0, "Mutex init failed\n");
|
||||
nr_ue_mac_default_configs(mac);
|
||||
|
||||
468
openair2/LAYER2/NR_MAC_UE/nr_slsch_scheduler.c
Normal file
468
openair2/LAYER2/NR_MAC_UE/nr_slsch_scheduler.c
Normal file
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* 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 "NR_MAC_UE/mac_proto.h"
|
||||
#include "NR_MAC_UE/nr_ue_sci.h"
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
#include "NR_MAC_UE/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
|
||||
|
||||
const uint8_t nr_rv_round_map[4] = {0, 2, 3, 1};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void abort_nr_ue_sl_harq(NR_UE_MAC_INST_t *mac, int8_t harq_pid, NR_SL_UE_info_t *UE_info)
|
||||
{
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl;
|
||||
NR_UE_sl_harq_t *harq = &sched_ctrl->sl_harq_processes[harq_pid];
|
||||
|
||||
harq->round = 0;
|
||||
UE_info->mac_sl_stats.sl.errors++;
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq_pid);
|
||||
/* the transmission failed: the UE won't send the data we expected initially,
|
||||
* so retrieve to correctly schedule after next BSR */
|
||||
sched_ctrl->sched_sl_bytes -= harq->sched_pssch.tb_size;
|
||||
if (sched_ctrl->sched_sl_bytes < 0)
|
||||
sched_ctrl->sched_sl_bytes = 0;
|
||||
}
|
||||
|
||||
void handle_nr_ue_sl_harq(module_id_t mod_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
sl_nr_slsch_pdu_t *rx_slsch_pdu,
|
||||
uint16_t src_id)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
NR_UE_SL_SCHED_LOCK(&mac->sl_sched_lock);
|
||||
NR_SL_UE_info_t **UE_SL_temp = (NR_SL_UE_info_t **)&mac->sl_info.list, *UE;
|
||||
// TODO: update for multiple UEs
|
||||
UE=*(UE_SL_temp);
|
||||
uint8_t num_ack_rcvd = rx_slsch_pdu->num_acks_rcvd;
|
||||
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_sl_harq_t **matched_harqs = (NR_UE_sl_harq_t **) calloc(sched_ctrl->feedback_sl_harq.len, sizeof(NR_UE_sl_harq_t *));
|
||||
int k = find_current_slot_harqs(frame, slot, sched_ctrl, matched_harqs);
|
||||
LOG_D(NR_MAC, "Found %d matching HARQ processes vs. num. of received acks %d\n", k, num_ack_rcvd);
|
||||
for (int i = 0; i < num_ack_rcvd; i++) {
|
||||
uint8_t ack_nack = rx_slsch_pdu->ack_nack_rcvd[i];
|
||||
uint8_t rx_harq_id = matched_harqs[i]->sl_harq_pid;
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
int8_t harq_pid = sched_ctrl->feedback_sl_harq.head;
|
||||
LOG_D(NR_MAC, "Comparing %4u.%2u rx_harq_id vs feedback harq_pid = %d %d\n", frame, slot, rx_harq_id, harq_pid);
|
||||
while (rx_harq_id != harq_pid || harq_pid < 0) {
|
||||
LOG_W(NR_MAC,
|
||||
"Unexpected SLSCH HARQ PID %d (have %d) for src id %4d\n",
|
||||
rx_harq_id,
|
||||
harq_pid,
|
||||
src_id);
|
||||
if (harq_pid < 0) {
|
||||
NR_UE_SL_SCHED_UNLOCK(&mac->sl_sched_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
remove_front_nr_list(&sched_ctrl->feedback_sl_harq);
|
||||
sched_ctrl->sl_harq_processes[harq_pid].is_waiting = false;
|
||||
|
||||
if(sched_ctrl->sl_harq_processes[harq_pid].round >= (HARQ_ROUND_MAX - 1)) {
|
||||
abort_nr_ue_sl_harq(mac, harq_pid, UE);
|
||||
} else {
|
||||
sched_ctrl->sl_harq_processes[harq_pid].round++;
|
||||
add_tail_nr_list(&sched_ctrl->retrans_sl_harq, harq_pid);
|
||||
}
|
||||
harq_pid = sched_ctrl->feedback_sl_harq.head;
|
||||
}
|
||||
remove_front_nr_list(&sched_ctrl->feedback_sl_harq);
|
||||
NR_UE_sl_harq_t *harq = &sched_ctrl->sl_harq_processes[harq_pid];
|
||||
DevAssert(harq->is_waiting);
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
if (!ack_nack) {
|
||||
UE->mac_sl_stats.cumul_round[harq->round]++;
|
||||
harq->round = 0;
|
||||
LOG_D(NR_MAC,
|
||||
"%4u.%2u Slharq id %d crc passed for src id %4d\n",
|
||||
frame,
|
||||
slot,
|
||||
harq_pid,
|
||||
src_id);
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq_pid);
|
||||
} else if (harq->round >= (HARQ_ROUND_MAX - 1)) {
|
||||
UE->mac_sl_stats.cumul_round[HARQ_ROUND_MAX]++;
|
||||
LOG_D(NR_MAC,
|
||||
"src id %4d, Slharq id %d crc failed in all rounds\n",
|
||||
src_id,
|
||||
harq_pid);
|
||||
abort_nr_ue_sl_harq(mac, harq_pid, UE);
|
||||
} else {
|
||||
harq->round++;
|
||||
LOG_D(NR_MAC,
|
||||
"%4u.%2u Slharq id %d crc failed for src id %4d\n",
|
||||
frame,
|
||||
slot,
|
||||
harq_pid,
|
||||
src_id);
|
||||
add_tail_nr_list(&sched_ctrl->retrans_sl_harq, harq_pid);
|
||||
}
|
||||
}
|
||||
free(matched_harqs);
|
||||
matched_harqs = NULL;
|
||||
NR_UE_SL_SCHED_UNLOCK(&mac->sl_sched_lock);
|
||||
}
|
||||
|
||||
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);
|
||||
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 ? resource->sl_subchan_len : 1;
|
||||
uint8_t n_start_subch1 = resource ? resource->sl_subchan_start : 0;
|
||||
uint8_t n_start_subch2 = 0;
|
||||
// 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(mac, 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 = 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 ? get_first_ul_slot(&mac->frame_structure, false) : 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");
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,25 @@
|
||||
|
||||
#include "mac_defs.h"
|
||||
#include "mac_proto.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
|
||||
#define SL_DEBUG
|
||||
|
||||
static const int sequence_cyclic_shift_harq_ack_or_ack_or_only_nack[2]
|
||||
/* Sequence cyclic shift */ = { 0, 6 };
|
||||
|
||||
void print_prb_set_allocation(psfch_params_t *psfch_params, uint8_t psfch_period, uint8_t num_subchannels) {
|
||||
LOG_D(NR_PHY, "PSSCH Slot mod PSFCH period | Subchannel | Start PRB | End PRB\n");
|
||||
for (int i = 0; i < psfch_period; i++) {
|
||||
for (int j = 0; j < num_subchannels; j++) {
|
||||
LOG_D(NR_PHY, "\t\t %d \t\t|\t%d\t|\t%d\t| \t %d\n", i, j, psfch_params->prbs_sets->start_prb[i][j], psfch_params->prbs_sets->end_prb[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sl_process_TDD_UL_DL_config_patterns(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t mu,
|
||||
double *slot_period_P,
|
||||
@@ -308,6 +324,12 @@ uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
//a5,a6..a11 bits from the 7th to 1st LSB of num SL slots
|
||||
num_SL_slots = ((bits_0_to_7 & 0x07) << 4 ) | ((bits_8_to_11 & 0xF0) >> 4);
|
||||
|
||||
const int nr_slots_period = nr_slots_per_frame[mu] / get_nb_periods_per_frame(TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity);
|
||||
AssertFatal(num_SL_slots <= nr_slots_period,
|
||||
"Decoded sidelink slots %d exceed TDD period slots %d\n",
|
||||
num_SL_slots,
|
||||
nr_slots_period);
|
||||
TDD_UL_DL_Config->pattern1.nrofDownlinkSlots = nr_slots_period - num_SL_slots;
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSlots = num_SL_slots;
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSymbols = mixed_slot_numsym;
|
||||
|
||||
@@ -528,3 +550,904 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
|
||||
|
||||
return sci_1a_len;
|
||||
}
|
||||
|
||||
uint8_t count_on_bits(uint8_t* buf, size_t size) {
|
||||
uint8_t count = 0;
|
||||
uint8_t byte;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
byte = buf[i];
|
||||
while(byte) {
|
||||
count += byte & 1;
|
||||
byte >>= 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void compute_params(int module_idP, psfch_params_t* psfch_params) {
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
if (!mac->sl_tx_res_pool->sl_PSFCH_Config_r16 &&
|
||||
mac->sl_tx_res_pool->sl_PSFCH_Config_r16->present != NR_SetupRelease_SL_PSFCH_Config_r16_PR_setup)
|
||||
return;
|
||||
|
||||
psfch_params->prbs_sets = calloc(1, sizeof(prbs_set_t));
|
||||
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup;
|
||||
const int sl_num_muxcs_pair[4] = {1, 2, 3, 6};
|
||||
uint8_t sci2_src_id = mac->sci_pdu_rx.source_id;
|
||||
uint8_t *rb_buf = sl_psfch_config->sl_PSFCH_RB_Set_r16->buf;
|
||||
size_t size = sl_psfch_config->sl_PSFCH_RB_Set_r16->size / sizeof(rb_buf[0]);
|
||||
uint8_t m_psfch_prb_set = count_on_bits(rb_buf, size);
|
||||
long sl_numsubchannel = *mac->sl_tx_res_pool->sl_NumSubchannel_r16;
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
long n_psfch_pssch = (sl_psfch_config->sl_PSFCH_Period_r16)
|
||||
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
|
||||
long n_psfch_cs = *sl_psfch_config->sl_NumMuxCS_Pair_r16;
|
||||
|
||||
double m_psfch_subch_slot = m_psfch_prb_set / (sl_numsubchannel * n_psfch_pssch);
|
||||
// FIXME: Add second condition from spec. 38213 16.3, current implementation assuming single subchannel
|
||||
long n_psfch_type = *sl_psfch_config->sl_PSFCH_CandidateResourceType_r16 ? sl_numsubchannel : 1;
|
||||
uint16_t r_psfch_prb_cs = n_psfch_type * m_psfch_subch_slot * sl_num_muxcs_pair[n_psfch_cs];
|
||||
uint8_t psfch_rsc_idx = (sci2_src_id + mac->src_id) / r_psfch_prb_cs;
|
||||
LOG_D(NR_MAC, "sci2_src_id %d, UE id %d\n", sci2_src_id, mac->src_id);
|
||||
LOG_D(NR_MAC, "size %lu, m_psfch_prb_set %d, sl_numsubchannel %ld, n_psfch_pssch %ld, n_psfch_cs %d\n", size, m_psfch_prb_set, sl_numsubchannel, n_psfch_pssch, sl_num_muxcs_pair[n_psfch_cs]);
|
||||
LOG_D(NR_MAC, "m_psfch_subch_slot %f, n_psfch_type %ld, r_psfch_prb_cs %d, psfch_rsc_idx %d\n", m_psfch_subch_slot, n_psfch_type, r_psfch_prb_cs, psfch_rsc_idx);
|
||||
psfch_params->m0 = table_16_3_1[n_psfch_cs][psfch_rsc_idx];
|
||||
|
||||
// 38213 16.3 Compute PRB allocation
|
||||
psfch_params->prbs_sets->start_prb = (uint16_t**)calloc(n_psfch_pssch, sizeof(uint16_t*));
|
||||
psfch_params->prbs_sets->end_prb = (uint16_t**)calloc(n_psfch_pssch, sizeof(uint16_t*));
|
||||
for (int k=0; k<n_psfch_pssch; k++) {
|
||||
psfch_params->prbs_sets->start_prb[k] = (uint16_t*)calloc(sl_numsubchannel, sizeof(uint16_t));
|
||||
psfch_params->prbs_sets->end_prb[k] = (uint16_t*)calloc(sl_numsubchannel, sizeof(uint16_t));
|
||||
}
|
||||
for (int i = 0; i < n_psfch_pssch; i++) {
|
||||
for (int j = 0; j < sl_numsubchannel; j++) {
|
||||
psfch_params->prbs_sets->start_prb[i][j] = (i + j * n_psfch_pssch) * m_psfch_subch_slot;
|
||||
psfch_params->prbs_sets->end_prb[i][j] = (i + 1 + j * n_psfch_pssch) * m_psfch_subch_slot - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void configure_psfch_params_tx(int module_idP,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
int pdu_id)
|
||||
{
|
||||
// TODO: May need to update in case of multiple UEs
|
||||
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 scs = get_softmodem_params()->numerology;
|
||||
uint16_t tx_slot = (rx_ind->slot + GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs)) % nr_slots_per_frame[scs];
|
||||
uint16_t tx_frame = (rx_ind->sfn + (rx_ind->slot + GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs)) / nr_slots_per_frame[scs]) % 1024;
|
||||
|
||||
uint8_t ack_nack = (rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu.ack_nack;
|
||||
LOG_D(NR_MAC, "tx_frame %4u.%2u, ack_nack %d rx: %4u.%2u\n", tx_frame, tx_slot, ack_nack, rx_ind->sfn, rx_ind->slot);
|
||||
psfch_params_t *psfch_params = calloc(1, sizeof(psfch_params_t));
|
||||
compute_params(module_idP, psfch_params);
|
||||
const int nr_slots_frame = nr_slots_per_frame[scs];
|
||||
int psfch_index = nr_ue_sl_acknack_scheduling(mac, rx_ind, psfch_period, tx_frame, tx_slot, nr_slots_frame);
|
||||
if (psfch_index != -1)
|
||||
fill_psfch_params_tx(mac, rx_ind, psfch_period, tx_frame, tx_slot, ack_nack, psfch_params, nr_slots_frame, psfch_index);
|
||||
free(psfch_params);
|
||||
psfch_params = NULL;
|
||||
}
|
||||
|
||||
int get_psfch_index(const frame_structure_t *fs, int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_psfch_max_size)
|
||||
{
|
||||
// PUCCH structures are indexed by slot in the PUCCH period determined by sched_psfch_max_size number of UL slots
|
||||
// this functions return the index to the structure for slot passed to the function
|
||||
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(fs, false) : 0;
|
||||
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 n_ul_slots_frame = n_slots_frame / nr_slots_period * n_ul_slots_period;
|
||||
// (frame * n_ul_slots_frame) adds up the number of UL slots in the previous frames
|
||||
const int frame_start = frame * n_ul_slots_frame;
|
||||
// ((slot / nr_slots_period) * n_ul_slots_period) adds up the number of UL slots in the previous TDD periods of this frame
|
||||
const int ul_period_start = (slot / nr_slots_period) * n_ul_slots_period;
|
||||
// ((slot % nr_slots_period) - first_ul_slot_period) gives the progressive number of the slot in this TDD period
|
||||
const int ul_period_slot = (slot % nr_slots_period) - first_ul_slot_period;
|
||||
// the sum gives the index of current UL slot in the frame which is normalized wrt sched_psfch_max_size
|
||||
return (frame_start + ul_period_start + ul_period_slot) % sched_psfch_max_size;
|
||||
|
||||
}
|
||||
|
||||
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 n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : nr_slots_frame;
|
||||
for (int i = 0; i < n_ul_slots_period; i++) {
|
||||
pssch_to_harq_feedback[i] = psfch_min_time_gap + i + 1;
|
||||
}
|
||||
return n_ul_slots_period;
|
||||
}
|
||||
|
||||
void get_csirs_to_csi_report(uint8_t *csirs_to_csi_report, uint8_t sl_latencyboundcsi_report, const int nr_slots_frame) {
|
||||
for (int i = 0; i < sl_latencyboundcsi_report; i++)
|
||||
csirs_to_csi_report[i] = i + 1;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
AssertFatal(tdd != NULL, "Expecting valid tdd configurations");
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(&mac->frame_structure, false) : 0;
|
||||
const int nr_slots_period = tdd ? nr_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : nr_slots_frame;
|
||||
// can't schedule ACKNACK before minimum feedback time
|
||||
if(feedback_offset < psfch_min_time_gap)
|
||||
return -1;
|
||||
|
||||
*psfch_slot = (slot + feedback_offset) % nr_slots_frame;
|
||||
// check if the slot is UL
|
||||
if(*psfch_slot % nr_slots_period < first_ul_slot_period)
|
||||
return -1;
|
||||
|
||||
if (*psfch_slot % psfch_period > 0)
|
||||
return -1;
|
||||
|
||||
*psfch_frame = (frame + ((slot + feedback_offset) / nr_slots_frame)) & 1023;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t get_feedback_slot(long psfch_period, uint16_t slot) {
|
||||
int16_t feedback_slot = -1;
|
||||
if (psfch_period == 1) {
|
||||
switch(slot) {
|
||||
case 0:
|
||||
feedback_slot = 6;
|
||||
break;
|
||||
case 1:
|
||||
feedback_slot = 7;
|
||||
break;
|
||||
case 2:
|
||||
feedback_slot = 8;
|
||||
break;
|
||||
case 3:
|
||||
feedback_slot = 9;
|
||||
break;
|
||||
case 10:
|
||||
feedback_slot = 16;
|
||||
break;
|
||||
case 11:
|
||||
feedback_slot = 17;
|
||||
break;
|
||||
case 12:
|
||||
feedback_slot = 18;
|
||||
break;
|
||||
case 13:
|
||||
feedback_slot = 19;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid slot %d\n", slot);
|
||||
}
|
||||
} else if (psfch_period == 2) {
|
||||
switch(slot) {
|
||||
case 0:
|
||||
case 1:
|
||||
feedback_slot = 7;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
feedback_slot = 9;
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
feedback_slot = 17;
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
feedback_slot = 19;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid slot %d\n", slot);
|
||||
}
|
||||
} else if (psfch_period == 4) {
|
||||
switch(slot) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
feedback_slot = 9;
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
feedback_slot = 19;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid slot %d\n", slot);
|
||||
}
|
||||
}
|
||||
return feedback_slot;
|
||||
}
|
||||
|
||||
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) {
|
||||
// TODO: needs to be updated for multi-subchannels
|
||||
int psfch_frame, psfch_slot;
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
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);
|
||||
int n_ul_buf_max_size = n_ul_slots_period * num_subch;
|
||||
|
||||
psfch_slot = get_feedback_slot(psfch_period, slot);
|
||||
const int psfch_index = get_psfch_index(&mac->frame_structure, rx_ind->sfn, rx_ind->slot, nr_slots_frame, tdd, n_ul_buf_max_size);
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &mac->sl_info.list[0]->UE_sched_ctrl;
|
||||
SL_sched_feedback_t *curr_psfch = &sched_ctrl->sched_psfch[psfch_index];
|
||||
psfch_frame = frame;
|
||||
frameslot_t fs;
|
||||
fs.frame = psfch_frame;
|
||||
fs.slot = psfch_slot;
|
||||
uint8_t pool_id = 0;
|
||||
uint64_t tx_abs_slot = normalize(&fs, get_softmodem_params()->numerology);
|
||||
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);
|
||||
LOG_D(NR_MAC, "%s %4d.%2d sl_has_psfch %d\n", __FUNCTION__, psfch_frame, psfch_slot, sl_has_psfch);
|
||||
curr_psfch->feedback_frame = psfch_frame;
|
||||
curr_psfch->feedback_slot = psfch_slot;
|
||||
curr_psfch->dai_c = psfch_index;
|
||||
LOG_D(NR_MAC, "Rx SLSCH %4d.%2d, SL_ACK %4d.%2d in current PSFCH: psfch_index %d, n_ul_slots_period %d dai_c %u curr_psfch %p\n",
|
||||
rx_ind->sfn,
|
||||
rx_ind->slot,
|
||||
psfch_frame,
|
||||
psfch_slot,
|
||||
psfch_index,
|
||||
n_ul_slots_period,
|
||||
curr_psfch->dai_c,
|
||||
curr_psfch);
|
||||
LOG_D(NR_MAC, "SL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", rx_ind->sfn, rx_ind->slot);
|
||||
return psfch_index;
|
||||
}
|
||||
|
||||
void fill_psfch_params_tx(NR_UE_MAC_INST_t *mac, sl_nr_rx_indication_t *rx_ind,
|
||||
long psfch_period, uint16_t frame, uint16_t slot,
|
||||
uint8_t ack_nack, psfch_params_t *psfch_params,
|
||||
const int nr_slots_frame, int psfch_index) {
|
||||
|
||||
NR_SL_BWP_Generic_r16_t *sl_bwp = mac->sl_bwp->sl_BWP_Generic_r16;
|
||||
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[psfch_index];
|
||||
LOG_D(NR_MAC, "psfch_period %ld, feedback frame:slot %d:%d, frame:slot %d:%d, harq feedback %d psfch_index %d\n",
|
||||
psfch_period,
|
||||
sched_psfch->feedback_frame,
|
||||
sched_psfch->feedback_slot,
|
||||
rx_ind->sfn,
|
||||
rx_ind->slot,
|
||||
mac->sci_pdu_rx.harq_feedback,
|
||||
psfch_index);
|
||||
sched_psfch->initial_cyclic_shift = psfch_params->m0;
|
||||
if ((mac->sci1_pdu.second_stage_sci_format == 0 && (mac->sci_pdu_rx.cast_type == 1 ||
|
||||
mac->sci_pdu_rx.cast_type == 2)) || mac->sci1_pdu.second_stage_sci_format == 2) {
|
||||
sched_psfch->mcs = sequence_cyclic_shift_harq_ack_or_ack_or_only_nack[ack_nack];
|
||||
sched_psfch->bit_len_harq = 1;
|
||||
LOG_D(NR_MAC, "mcs %i, ack_nack: %i, sched_psfch->initial_cyclic_shift %i\n",
|
||||
sched_psfch->mcs, ack_nack, sched_psfch->initial_cyclic_shift);
|
||||
} else if (mac->sci1_pdu.second_stage_sci_format == 1 ||
|
||||
(mac->sci1_pdu.second_stage_sci_format == 0 && mac->sci_pdu_rx.cast_type == 3)) {
|
||||
sched_psfch->mcs = sequence_cyclic_shift_harq_ack_or_ack_or_only_nack[0];
|
||||
sched_psfch->bit_len_harq = 0;
|
||||
}
|
||||
const uint8_t values[] = {7, 8, 9, 10, 11, 12, 13, 14};
|
||||
uint8_t sl_num_symbols = *sl_bwp->sl_LengthSymbols_r16 ? values[*sl_bwp->sl_LengthSymbols_r16] : 0;
|
||||
// start_symbol_index has been used as lprime check 38.213 16.3
|
||||
sched_psfch->start_symbol_index = *sl_bwp->sl_StartSymbol_r16 + sl_num_symbols - 2;
|
||||
LOG_D(NR_PHY, "sl_StartSymbol_r16 %ld, sl_num_symbols: %d, start sym index %d, mcs %d\n",
|
||||
*sl_bwp->sl_StartSymbol_r16, sl_num_symbols, sched_psfch->start_symbol_index, sched_psfch->mcs);
|
||||
sched_psfch->hopping_id = *mac->sl_bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.array[0]->sl_ResourcePool_r16->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_HopID_r16;
|
||||
sched_psfch->prb = psfch_params->prbs_sets->start_prb[rx_ind->slot % psfch_period][0]; // FIXME [0] is based on assumption of number of subchannels = 1; 0 is channel id
|
||||
print_prb_set_allocation(psfch_params, psfch_period, 1);
|
||||
LOG_D(NR_PHY, "slot %d, slot mode psfch_period %ld, sched_psfch->prb %d, start_prb %d\n",
|
||||
rx_ind->slot, rx_ind->slot%psfch_period, sched_psfch->prb,
|
||||
psfch_params->prbs_sets->start_prb[rx_ind->slot%psfch_period][0]);
|
||||
int locbw = sl_bwp->sl_BWP_r16->locationAndBandwidth;
|
||||
sched_psfch->sl_bwp_start = NRRIV2PRBOFFSET(locbw, MAX_BWP_SIZE);
|
||||
sched_psfch->freq_hop_flag = 0;
|
||||
sched_psfch->group_hop_flag = 0;
|
||||
sched_psfch->second_hop_prb = 0;
|
||||
sched_psfch->sequence_hop_flag = 0;
|
||||
sched_psfch->harq_feedback = mac->sci_pdu_rx.harq_feedback;
|
||||
LOG_D(NR_MAC, "Filled psfch pdu\n");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int cur = sched_ctrl->feedback_sl_harq.head;
|
||||
int k = 0;
|
||||
while (cur != -1) {
|
||||
NR_UE_sl_harq_t *harq = &sched_ctrl->sl_harq_processes[cur];
|
||||
LOG_D(NR_MAC, "%s %4d.%2d feedback %4d.%2d\n", __FUNCTION__, frame, slot, harq->feedback_frame, harq->feedback_slot);
|
||||
if (harq->feedback_frame == frame && harq->feedback_slot == slot) {
|
||||
if (matched_harqs) {
|
||||
matched_harqs[k] = harq;
|
||||
LOG_D(NR_MAC, "%s matched_harqs[%d] %4d.%2d %d slot %d\n",
|
||||
__FUNCTION__,
|
||||
k,
|
||||
matched_harqs[k]->feedback_frame,
|
||||
matched_harqs[k]->feedback_slot,
|
||||
matched_harqs[k]->sl_harq_pid,
|
||||
matched_harqs[k]->sched_pssch.slot);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
cur = sched_ctrl->feedback_sl_harq.next[cur];
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
/*
|
||||
Following function is used to remove the harq_pids from the feedback list;
|
||||
Adds back to available list or retransmission list based on round value.
|
||||
*/
|
||||
|
||||
void update_harq_lists(NR_UE_MAC_INST_t *mac, frame_t frame, sub_frame_t slot, NR_SL_UE_info_t* UE)
|
||||
{
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
int cur = sched_ctrl->feedback_sl_harq.head;
|
||||
while (cur != -1) {
|
||||
NR_UE_sl_harq_t *harq = &sched_ctrl->sl_harq_processes[cur];
|
||||
if ((harq->feedback_frame < frame
|
||||
|| (harq->feedback_frame == frame && harq->feedback_slot < slot))) {
|
||||
remove_nr_list(&sched_ctrl->feedback_sl_harq, cur);
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
if (harq->round >= HARQ_ROUND_MAX - 1) {
|
||||
abort_nr_ue_sl_harq(mac, cur, UE);
|
||||
} else {
|
||||
add_tail_nr_list(&sched_ctrl->retrans_sl_harq, cur);
|
||||
harq->round++;
|
||||
}
|
||||
}
|
||||
cur = sched_ctrl->feedback_sl_harq.next[cur];
|
||||
}
|
||||
}
|
||||
|
||||
void configure_psfch_params_rx(int module_idP,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
sl_nr_rx_config_request_t *rx_config)
|
||||
{
|
||||
const uint16_t slot = rx_config->slot;
|
||||
frame_t frame = rx_config->sfn;
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_rx_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;
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_rx_res_pool);
|
||||
rx_config->sl_rx_config_list[0].rx_psfch_pdu_list = calloc(psfch_period*num_subch, sizeof(sl_nr_tx_rx_config_psfch_pdu_t));
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
|
||||
if (*(UE_info->list) == NULL) {
|
||||
LOG_D(NR_MAC, "UE list is empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
psfch_params_t *psfch_params = calloc(1, sizeof(psfch_params_t));
|
||||
compute_params(module_idP, psfch_params);
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_sl_harq_t **matched_harqs = (NR_UE_sl_harq_t **) calloc(sched_ctrl->feedback_sl_harq.len, sizeof(NR_UE_sl_harq_t *));
|
||||
int matched_sz = find_current_slot_harqs(frame, slot, sched_ctrl, matched_harqs);
|
||||
LOG_D(NR_MAC, "%s matched_sz %d\n", __FUNCTION__, matched_sz);
|
||||
rx_config->sl_rx_config_list[0].num_psfch_pdus = 0;
|
||||
for (int i = 0; i < matched_sz; i++) {
|
||||
AssertFatal(i < UE->UE_sched_ctrl.feedback_sl_harq.len, "k MUST be smaller than feedback_sl_harq length\n");
|
||||
AssertFatal(i < (psfch_period * num_subch), "k MUST be smaller than %ld\n", (psfch_period * num_subch));
|
||||
NR_UE_sl_harq_t *cur_harq = matched_harqs[i];
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu = &rx_config->sl_rx_config_list[0].rx_psfch_pdu_list[i];
|
||||
fill_psfch_params_rx(rx_config, psfch_pdu, psfch_params, cur_harq, mac, psfch_period, slot);
|
||||
}
|
||||
free(matched_harqs);
|
||||
matched_harqs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
rx_config->sl_rx_config_list[0].num_psfch_pdus++;
|
||||
psfch_pdu->initial_cyclic_shift = psfch_params->m0;
|
||||
LOG_D(NR_MAC, "psfch_pdu->initial_cyclic_shift %i\n", psfch_pdu->initial_cyclic_shift);
|
||||
const uint8_t values[] = {7, 8, 9, 10, 11, 12, 13, 14};
|
||||
NR_SL_BWP_Generic_r16_t *sl_bwp = mac->sl_bwp->sl_BWP_Generic_r16;
|
||||
uint8_t sl_num_symbols = *sl_bwp->sl_LengthSymbols_r16 ? values[*sl_bwp->sl_LengthSymbols_r16] : 0;
|
||||
// start_symbol_index has been used as lprime check 38.213 16.3
|
||||
psfch_pdu->start_symbol_index = *sl_bwp->sl_StartSymbol_r16 + sl_num_symbols - 2;
|
||||
LOG_D(NR_PHY, "Rx sl_StartSymbol_r16 %ld, sl_num_symbols: %d, start sym index %d, mcs %d\n", *sl_bwp->sl_StartSymbol_r16, sl_num_symbols, psfch_pdu->start_symbol_index, psfch_pdu->mcs);
|
||||
psfch_pdu->hopping_id = *mac->sl_bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.array[0]->sl_ResourcePool_r16->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_HopID_r16;
|
||||
uint8_t index = cur_harq->sched_pssch.slot%psfch_period;
|
||||
psfch_pdu->prb = psfch_params->prbs_sets->start_prb[index][0]; // FIXME [0] is based on assumption of number of subchannels = 1; 0 is channel id
|
||||
print_prb_set_allocation(psfch_params, psfch_period, 1);
|
||||
LOG_D(NR_PHY, "Rx slot %d, slsch tx slot %d, tx slot mode psfch_period %d, start_prb %d\n", slot, cur_harq->sched_pssch.slot, index, psfch_params->prbs_sets->start_prb[index][0]);
|
||||
int locbw = sl_bwp->sl_BWP_r16->locationAndBandwidth;
|
||||
psfch_pdu->sl_bwp_start = NRRIV2PRBOFFSET(locbw, MAX_BWP_SIZE);
|
||||
psfch_pdu->freq_hop_flag = 0;
|
||||
psfch_pdu->group_hop_flag = 0;
|
||||
psfch_pdu->second_hop_prb = 0;
|
||||
psfch_pdu->sequence_hop_flag = 0;
|
||||
psfch_pdu->bit_len_harq = 1;
|
||||
int num_psfch_symbols = 0;
|
||||
if (psfch_period == 1) num_psfch_symbols = 3;
|
||||
else if (psfch_period == 2 || psfch_period == 4) {
|
||||
num_psfch_symbols = mac->SL_MAC_PARAMS->sl_RxPool[0]->sci_1a.psfch_overhead_indication.nbits ? 3 : 0;
|
||||
}
|
||||
psfch_pdu->nr_of_symbols = num_psfch_symbols ? num_psfch_symbols - 2 : 0; // (num_psfch_symbols - 2) excludes PSFCH AGC and Guard
|
||||
rx_config->sl_rx_config_list[0].pdu_type = SL_NR_CONFIG_TYPE_RX_PSFCH;
|
||||
LOG_D(NR_PHY, "%s start_symbol_index %d, sl_bwp_start %d, sequence_hop_flag %d, \
|
||||
second_hop_prb %d, prb %d, nr_of_symbols %d, initial_cyclic_shift %d, hopping_id %d, \
|
||||
group_hop_flag %d, freq_hop_flag %d, bit_len_harq %d----> Setting pdu type SL_NR_CONFIG_TYPE_RX_PSFCH \n",
|
||||
__FUNCTION__,
|
||||
psfch_pdu->start_symbol_index, psfch_pdu->sl_bwp_start,
|
||||
psfch_pdu->sequence_hop_flag, psfch_pdu->second_hop_prb, psfch_pdu->prb,
|
||||
psfch_pdu->nr_of_symbols, psfch_pdu->initial_cyclic_shift, psfch_pdu->hopping_id,
|
||||
psfch_pdu->group_hop_flag, psfch_pdu->freq_hop_flag, psfch_pdu->bit_len_harq);
|
||||
}
|
||||
|
||||
void set_csi_report_params(NR_UE_MAC_INST_t* mac, NR_SL_UE_sched_ctrl_t *sched_ctrl) {
|
||||
SL_CSI_Report_t *csi_report = &sched_ctrl->sched_csi_report;
|
||||
csi_report->cqi = mac->csirs_measurements.cqi;
|
||||
csi_report->ri = mac->csirs_measurements.ri;
|
||||
}
|
||||
|
||||
uint8_t sl_num_slsch_feedbacks(NR_UE_MAC_INST_t *mac) {
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
uint8_t 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);
|
||||
return n_ul_slots_period * num_subch;
|
||||
}
|
||||
|
||||
bool is_feedback_scheduled(NR_UE_MAC_INST_t *mac, int frameP,int slotP) {
|
||||
for (int i = 0; i < sl_num_slsch_feedbacks(mac); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
LOG_D(NR_MAC, "frame.slot %4d.%2d, harq_feedback %d\n", frameP, slotP, sched_psfch->harq_feedback);
|
||||
if (frameP == sched_psfch->feedback_frame && slotP == sched_psfch->feedback_slot && sched_psfch->harq_feedback) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reset_sched_psfch(NR_UE_MAC_INST_t *mac, int frameP,int slotP) {
|
||||
|
||||
for (int i = 0; i < sl_num_slsch_feedbacks(mac); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
if (frameP == sched_psfch->feedback_frame && slotP == sched_psfch->feedback_slot) {
|
||||
sched_psfch->feedback_frame = -1;
|
||||
sched_psfch->feedback_slot = -1;
|
||||
sched_psfch->harq_feedback = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_process_mac_sl_pdu(int module_idP,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
int pdu_id)
|
||||
{
|
||||
int8_t pdu_type = (rx_ind->rx_indication_body + pdu_id)->pdu_type;
|
||||
sl_nr_slsch_pdu_t *rx_slsch_pdu = &(rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu;
|
||||
uint8_t *pduP = rx_slsch_pdu->pdu;
|
||||
int32_t pdu_len = (int32_t)rx_slsch_pdu->pdu_length;
|
||||
uint8_t done = 0;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
int frame = rx_ind->sfn;
|
||||
int slot = rx_ind->slot;
|
||||
if (!pduP){
|
||||
return;
|
||||
}
|
||||
|
||||
NR_SLSCH_MAC_SUBHEADER_FIXED *sl_sch_subheader = (NR_SLSCH_MAC_SUBHEADER_FIXED *) pduP;
|
||||
uint8_t psfch_period = 0;
|
||||
if (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_period = *mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup->sl_PSFCH_Period_r16;
|
||||
if (psfch_period && mac->sci_pdu_rx.harq_feedback) {
|
||||
configure_psfch_params_tx(module_idP, mac, rx_ind, pdu_id);
|
||||
}
|
||||
|
||||
NR_SL_UE_info_t *UE = find_UE(mac, sl_sch_subheader->SRC);
|
||||
|
||||
if (UE == NULL)
|
||||
return;
|
||||
|
||||
if (pdu_type == SL_NR_RX_PDU_TYPE_SLSCH_PSFCH) {
|
||||
handle_nr_ue_sl_harq(module_idP, frame, slot, rx_slsch_pdu, sl_sch_subheader->SRC);
|
||||
int r0 = UE->mac_sl_stats.cumul_round[0];
|
||||
int r1 = UE->mac_sl_stats.cumul_round[1];
|
||||
int r2 = UE->mac_sl_stats.cumul_round[2];
|
||||
int r3 = UE->mac_sl_stats.cumul_round[3];
|
||||
int r4 = UE->mac_sl_stats.cumul_round[4];
|
||||
int round_sum = r1 + 2 * r2 + 3 * r3 + 4 * r4;
|
||||
int total_tx = r0 + round_sum;
|
||||
if (total_tx % 20 == 0 || (total_tx > 299 && total_tx < 305)) {
|
||||
LOG_I(NR_PHY, "[UE] %d:%d PSFCH Stats: RX round (%u %u %u %u %u), SumRetx %u TotalTx %u\n",
|
||||
frame, slot,
|
||||
UE->mac_sl_stats.cumul_round[0],
|
||||
UE->mac_sl_stats.cumul_round[1],
|
||||
UE->mac_sl_stats.cumul_round[2],
|
||||
UE->mac_sl_stats.cumul_round[3],
|
||||
UE->mac_sl_stats.cumul_round[4],
|
||||
round_sum, total_tx
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "%4d.%2d ack_nack %d pdu_type %d mac->sci_pdu_rx.csi_req %d\n",
|
||||
frame, slot, rx_slsch_pdu->ack_nack, pdu_type, mac->sci_pdu_rx.csi_req);
|
||||
if (rx_slsch_pdu->ack_nack == 0)
|
||||
return;
|
||||
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
if (mac->sci_pdu_rx.csi_req) {
|
||||
LOG_D(NR_MAC, "%4d.%2d Configuring sl_csi_report parameters\n", frame, slot);
|
||||
int scs = get_softmodem_params()->numerology;
|
||||
uint16_t tx_slot = (rx_ind->slot + GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs)) % nr_slots_per_frame[scs];
|
||||
uint16_t tx_frame = (rx_ind->sfn + (rx_ind->slot + GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs)) / nr_slots_per_frame[scs]) % 1024;
|
||||
set_csi_report_params(mac, sched_ctrl);
|
||||
nr_ue_sl_csi_report_scheduling(module_idP,
|
||||
sched_ctrl,
|
||||
tx_frame,
|
||||
tx_slot);
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "In %s : processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, pdu_id, pdu_len, rx_ind->number_pdus);
|
||||
LOG_D(NR_PHY, "%4d.%2d Rx 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);
|
||||
pduP += sizeof(*sl_sch_subheader);
|
||||
pdu_len -= sizeof(*sl_sch_subheader);
|
||||
if (frame % 20 == 0)
|
||||
LOG_D(NR_PHY, "%4d.%2d Rx 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);
|
||||
while (!done && pdu_len > 0) {
|
||||
uint16_t mac_len = 0x0000;
|
||||
uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct
|
||||
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)(pduP))->LCID;
|
||||
LOG_D(NR_MAC, "[UE %x] LCID %d, remaining pdu length %d byte(s)\n", mac->src_id, rx_lcid, pdu_len);
|
||||
switch (rx_lcid) {
|
||||
// MAC CE
|
||||
case SL_SCH_LCID_4_19:
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return;
|
||||
LOG_D(NR_MAC, "%4d.%2d : SLSCH -> LCID %d %d bytes with subheader %d\n", frame, slot, rx_lcid, mac_len, mac_subheader_len);
|
||||
|
||||
#if 0
|
||||
mac_rlc_data_ind(module_idP,
|
||||
mac->src_id,
|
||||
0,
|
||||
frame,
|
||||
ENB_FLAG_NO,
|
||||
MBMS_FLAG_NO,
|
||||
rx_lcid,
|
||||
(char *)(pduP + mac_subheader_len),
|
||||
mac_len,
|
||||
1,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
nr_mac_rlc_data_ind(mac->ue_id, mac->src_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len);
|
||||
|
||||
break;
|
||||
case SL_SCH_LCID_SL_CSI_REPORT:
|
||||
{
|
||||
NR_MAC_SUBHEADER_FIXED* sub_pdu_header = (NR_MAC_SUBHEADER_FIXED*) pduP;
|
||||
if (frame % 20 == 0)
|
||||
LOG_D(NR_MAC, "\tLCID: %i, R: %i\n", sub_pdu_header->LCID, sub_pdu_header->R);
|
||||
mac_subheader_len = sizeof(*sub_pdu_header);
|
||||
nr_sl_csi_report_t* nr_sl_csi_report = (nr_sl_csi_report_t *) (pduP + mac_len);
|
||||
mac_len = sizeof(*nr_sl_csi_report);
|
||||
if (frame % 20 == 0)
|
||||
LOG_D(NR_MAC, "\tCQI: %i RI: %i\n", nr_sl_csi_report->CQI, nr_sl_csi_report->RI);
|
||||
sched_ctrl->rx_csi_report.CQI = nr_sl_csi_report->CQI;
|
||||
sched_ctrl->rx_csi_report.RI = nr_sl_csi_report->RI;
|
||||
LOG_D(NR_MAC, "Setting to CQI %i\n", sched_ctrl->rx_csi_report.CQI);
|
||||
break;
|
||||
}
|
||||
case SL_SCH_LCID_SL_PADDING:
|
||||
{
|
||||
NR_MAC_SUBHEADER_FIXED* sub_pdu_header = (NR_MAC_SUBHEADER_FIXED*) pduP;
|
||||
mac_subheader_len = sizeof(*sub_pdu_header);
|
||||
mac_len = pdu_len - mac_subheader_len;
|
||||
LOG_D(NR_MAC, "%4d.%2d Received padding %d\n", frame, slot, pdu_len);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
case SL_SCH_LCID_SCCH_PC5_NOT_PROT:
|
||||
case SL_SCH_LCID_SCCH_PC5_DSMC:
|
||||
case SL_SCH_LCID_SCCH_PC5_PROT:
|
||||
case SL_SCH_LCID_SCCH_PC5_RRC:
|
||||
case SL_SCH_LCID_20_55:
|
||||
case SL_SCH_LCID_SCCH_RRC_SL_RLC0:
|
||||
case SL_SCH_LCID_SCCH_RRC_SL_RLC1:
|
||||
case SL_SCH_LCID_SCCH_SL_DISCOVERY:
|
||||
case SL_SCH_LCID_SL_INTER_UE_COORD_REQ:
|
||||
case SL_SCH_LCID_SL_INTER_UE_COORD_INFO:
|
||||
case SL_SCH_LCID_SL_DRX_CMD:
|
||||
LOG_W(NR_MAC,"Received unsupported SL LCID %d\n",rx_lcid);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
pduP += ( mac_subheader_len + mac_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_len );
|
||||
LOG_D(NR_MAC, "mac_subhead_len + mac_len = %d\n", mac_subheader_len + mac_len);
|
||||
LOG_D(NR_MAC, "%4d.%2d : SLSCH -> LCID %d remaining pdu length %d byte(s)\n", frame, slot, rx_lcid, pdu_len);
|
||||
if (pdu_len < 0)
|
||||
LOG_E(NR_MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu_sl, residual mac pdu length %d < 0!\n", module_idP, frame, slot, pdu_len);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_sl_csi_report_scheduling(int mod_id,
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl,
|
||||
uint32_t frame,
|
||||
uint32_t slot) {
|
||||
uint32_t sched_slot, sched_frame;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
if (sched_ctrl->sched_csi_report.active == false) {
|
||||
uint8_t scs = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
const int nr_slots_frame = nr_slots_per_frame[scs];
|
||||
uint8_t csirs_to_csi_report[sl_mac->sl_LatencyBoundCSI_Report];
|
||||
|
||||
get_csirs_to_csi_report(csirs_to_csi_report, sl_mac->sl_LatencyBoundCSI_Report, nr_slots_frame);
|
||||
int continue_flag = 0;
|
||||
for (int f = 0; f < sl_mac->sl_LatencyBoundCSI_Report; f++) {
|
||||
continue_flag = get_csi_reporting_frame_slot(mac,
|
||||
tdd,
|
||||
csirs_to_csi_report[f],
|
||||
nr_slots_frame,
|
||||
frame,
|
||||
slot,
|
||||
&sched_frame,
|
||||
&sched_slot);
|
||||
if (continue_flag == -1)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
LOG_D(NR_MAC, "%4d.%2d Scheduling csi_report\n", sched_frame, sched_slot);
|
||||
SL_CSI_Report_t *csi_report = &sched_ctrl->sched_csi_report;
|
||||
csi_report->frame = sched_frame;
|
||||
csi_report->slot = sched_slot;
|
||||
csi_report->active = true;
|
||||
}
|
||||
}
|
||||
|
||||
NR_SL_UE_info_t* find_UE(NR_UE_MAC_INST_t *mac,
|
||||
uint16_t nearby_ue_id) {
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
|
||||
if (*(UE_info->list) == NULL) {
|
||||
LOG_D(NR_MAC, "UE list is empty\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
LOG_D(NR_MAC, "%s: dest_id %d nearby id %d\n", __FUNCTION__, UE->uid, nearby_ue_id);
|
||||
if((UE->uid == nearby_ue_id)) {
|
||||
return UE;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
AssertFatal(tdd != NULL, "Expecting valid tdd configurations");
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(&mac->frame_structure, false) : 0;
|
||||
const int nr_slots_period = tdd ? nr_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : nr_slots_frame;
|
||||
|
||||
*csi_report_slot = (slot + csi_offset) % nr_slots_frame;
|
||||
|
||||
// check if the slot is UL
|
||||
if(*csi_report_slot % nr_slots_period < first_ul_slot_period)
|
||||
return -1;
|
||||
|
||||
*csi_report_frame = (frame + ((slot + csi_offset) / nr_slots_frame)) & 1023;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_list(List_t* list, size_t element_size, size_t initial_capacity) {
|
||||
list->data = calloc(1, element_size * initial_capacity);
|
||||
list->element_size = element_size;
|
||||
list->size = 0;
|
||||
list->capacity = initial_capacity;
|
||||
}
|
||||
|
||||
void push_back(List_t* list, void *element) {
|
||||
if (list->size == list->capacity) {
|
||||
list->capacity *= 2;
|
||||
list->data = realloc(list->data, list->element_size * list->capacity);
|
||||
}
|
||||
void *target = (char*)list->data + (list->size * list->element_size);
|
||||
memcpy(target, element, list->element_size);
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void* get_front(const List_t* list) {
|
||||
if (list->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return list->data; // pointer to first element
|
||||
}
|
||||
|
||||
void* get_back(const List_t* list) {
|
||||
if (list->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return (char*)list->data + (list->size - 1) * list->element_size; // pointer to last element
|
||||
}
|
||||
|
||||
void delete_at(List_t* list, size_t index) {
|
||||
|
||||
if (index >= list->size) {
|
||||
LOG_E(NR_MAC, "Index of bound\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char* element_ptr = (char*)list->data + index * list->element_size;
|
||||
|
||||
memmove(element_ptr, element_ptr + list->element_size, (list->size - index - 1) * list->element_size);
|
||||
|
||||
list->size--;
|
||||
}
|
||||
|
||||
int64_t normalize(frameslot_t *frame_slot, uint8_t mu) {
|
||||
int64_t num_slots = 0;
|
||||
uint8_t slots_per_frame = nr_slots_per_frame[mu];
|
||||
num_slots = frame_slot->slot;
|
||||
num_slots += frame_slot->frame * slots_per_frame;
|
||||
return num_slots;
|
||||
}
|
||||
|
||||
void de_normalize(int64_t abs_slot_idx, uint8_t mu, frameslot_t *frame_slot) {
|
||||
uint8_t slots_per_frame = nr_slots_per_frame[mu];
|
||||
frame_slot->frame = (abs_slot_idx / slots_per_frame) & 1023;
|
||||
frame_slot->slot = (abs_slot_idx % slots_per_frame);
|
||||
}
|
||||
|
||||
frameslot_t add_to_sfn(frameslot_t* sfn, uint16_t slot_n, uint8_t mu) {
|
||||
frameslot_t temp_sfn;
|
||||
temp_sfn.frame = (sfn->frame + ((sfn->slot + slot_n) / nr_slots_per_frame[mu])) % 1024;
|
||||
temp_sfn.slot = (sfn->slot + slot_n) % nr_slots_per_frame[mu];
|
||||
return temp_sfn;
|
||||
}
|
||||
|
||||
|
||||
void update_sensing_data(List_t* sensing_data, frameslot_t *frame_slot, sl_nr_ue_mac_params_t *sl_mac, uint16_t pool_id) {
|
||||
uint8_t mu = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
int64_t num_max_slots = nr_slots_per_frame[mu] * 1024;
|
||||
while(sensing_data->size > 0) {
|
||||
sensing_data_t* last_elem = (sensing_data_t*)((char*)sensing_data->data + (sensing_data->size - 1) * sensing_data->element_size);
|
||||
int64_t diff = (normalize(frame_slot, mu) - normalize(&last_elem->frame_slot, mu) + num_max_slots) % num_max_slots;
|
||||
if (diff <= get_tproc0(sl_mac, pool_id)) {
|
||||
pop_back(sensing_data);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_transmit_history(List_t* transmit_history, frameslot_t *frame_slot, sl_nr_ue_mac_params_t *sl_mac, uint16_t pool_id) {
|
||||
uint8_t mu = sl_mac->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
int64_t num_max_slots = nr_slots_per_frame[mu] * 1024;
|
||||
while(transmit_history->size > 0) {
|
||||
frameslot_t* last_frame_slot = (frameslot_t*)((uint8_t*)transmit_history->data + (transmit_history->size - 1) * transmit_history->element_size);
|
||||
int64_t diff = (normalize(frame_slot, mu) - normalize(last_frame_slot, mu) + num_max_slots) % num_max_slots;
|
||||
|
||||
if (diff <= get_tproc0(sl_mac, pool_id)) {
|
||||
pop_back(transmit_history);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pop_back(List_t* sensing_data) {
|
||||
if(sensing_data->size > 0) {
|
||||
sensing_data->size--;
|
||||
}
|
||||
}
|
||||
|
||||
void free_list_mem(List_t* list) {
|
||||
free(list->data);
|
||||
list->data = NULL;
|
||||
list->size = 0;
|
||||
list->capacity = 0;
|
||||
}
|
||||
|
||||
uint16_t get_T2_min(uint16_t pool_id, sl_nr_ue_mac_params_t *sl_mac, uint8_t mu) {
|
||||
uint16_t t2min = sl_mac->sl_TxPool[pool_id]->t2min * pow(2, mu);
|
||||
return t2min;
|
||||
}
|
||||
|
||||
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 t2;
|
||||
if (!(sl_tx_params->packet_delay_budget_ms == 0)) {
|
||||
// Packet delay budget is known, so use it
|
||||
uint16_t pdb_slots = time_to_slots(mu, sl_tx_params->packet_delay_budget_ms);
|
||||
t2 = min(pdb_slots, sl_mac->sl_TxPool[pool_id]->t2);
|
||||
} else {
|
||||
// Packet delay budget is not known, so use max(NrSlUeMac::T2, T2min)
|
||||
uint16_t t2min = get_T2_min(pool_id, sl_mac, mu);
|
||||
t2 = max(t2min, sl_mac->sl_TxPool[pool_id]->t2);
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
uint16_t time_to_slots(uint8_t mu, uint16_t time) {
|
||||
uint8_t slots_per_ms = (uint8_t)pow(2, mu); // subframe is of 1 ms
|
||||
uint16_t time_in_slots = time * slots_per_ms;
|
||||
return time_in_slots;
|
||||
}
|
||||
|
||||
uint8_t get_tproc0(sl_nr_ue_mac_params_t *sl_mac, uint16_t pool_id) {
|
||||
return sl_mac->sl_TxPool[pool_id]->tproc0;
|
||||
}
|
||||
|
||||
void init_vector(vec_of_list_t* vec, size_t initial_capacity) {
|
||||
vec->size = 0;
|
||||
vec->capacity = initial_capacity;
|
||||
vec->lists = (List_t*)malloc16_clear(initial_capacity * sizeof(List_t));
|
||||
|
||||
if (!vec->lists) {
|
||||
LOG_E(NR_MAC, "Memory allocation failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void add_list(vec_of_list_t* vec, size_t element_size, size_t initial_list_capacity) {
|
||||
if (vec->size == vec->capacity) {
|
||||
vec->capacity *= 2;
|
||||
vec->lists = realloc(vec->lists, vec->capacity * sizeof(List_t));
|
||||
if (!vec->lists) {
|
||||
LOG_E(NR_MAC, "Memory allocation failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
init_list(&vec->lists[vec->size], element_size, initial_list_capacity);
|
||||
vec->size++;
|
||||
}
|
||||
|
||||
void push_back_list(vec_of_list_t* vec, List_t* new_list) {
|
||||
if (vec->size == vec->capacity) {
|
||||
vec->capacity *= 2;
|
||||
vec->lists = realloc(vec->lists, vec->capacity * sizeof(List_t));
|
||||
if (!vec->lists) {
|
||||
LOG_E(NR_MAC, "Memory allocation failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
vec->lists[vec->size] = *new_list;
|
||||
vec->size++;
|
||||
}
|
||||
|
||||
List_t* get_list(vec_of_list_t *vec, size_t index) {
|
||||
if (index >= vec->size) {
|
||||
LOG_E(NR_MAC, "Index out of bounds\n");
|
||||
return NULL;
|
||||
}
|
||||
return &vec->lists[index];
|
||||
}
|
||||
|
||||
void free_vector(vec_of_list_t* vec) {
|
||||
for (size_t i = 0; i < vec->size; i++) {
|
||||
free_list_mem(&vec->lists[i]);
|
||||
}
|
||||
free(vec->lists);
|
||||
vec->lists = NULL;
|
||||
vec->size = 0;
|
||||
vec->capacity = 0;
|
||||
}
|
||||
|
||||
@@ -163,6 +163,51 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity
|
||||
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
|
||||
}
|
||||
|
||||
/*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];
|
||||
if (lc_info->rb_suspended)
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// flush all HARQ buffers for all Serving Cells
|
||||
@@ -1303,51 +1348,6 @@ static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP,
|
||||
}
|
||||
}
|
||||
|
||||
/*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'.
|
||||
|
||||
*/
|
||||
|
||||
static 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];
|
||||
if (lc_info->rb_suspended)
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
|
||||
{
|
||||
int cc_id = ul_info->cc_id;
|
||||
@@ -2258,22 +2258,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
|
||||
} // if is_nr_UL_slot
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t phr_len;
|
||||
uint sdu_length_total;
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE phr;
|
||||
type_bsr_t bsr;
|
||||
uint8_t *pdu_end;
|
||||
uint8_t *end_for_tailer;
|
||||
uint8_t *cur_ptr;
|
||||
uint num_sdus;
|
||||
// int highest_priority = 16;
|
||||
// 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;
|
||||
|
||||
static void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
|
||||
void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
@@ -2303,7 +2288,7 @@ static void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
|
||||
// A Regular or Periodic BSR can only be sent if TBS is sufficient
|
||||
// as transmitting only a BSR is not allowed if UE has data to transmit
|
||||
int size_for_long = num_lcg_id_with_data + sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT);
|
||||
int size_for_short = sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
int size_for_short = (get_softmodem_params()->sl_mode ? sizeof(NR_SL_BSR_SHORT) : sizeof(NR_BSR_SHORT)) + sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
if (num_lcg_id_with_data > 1 && buflen >= size_for_long)
|
||||
bsr_len = size_for_long;
|
||||
else if ((num_lcg_id_with_data > 0 && buflen >= size_for_short)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
349
openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl_v2x.c
Normal file
349
openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl_v2x.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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_scheduler_sl_v2x.c
|
||||
* \brief Rel-16 NR sidelink V2X semi-persistent resource selection and LBT gate
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
|
||||
#define NR_SL_V2X_DEFAULT_PROB_RESOURCE_KEEP 0.8
|
||||
#define NR_SL_V2X_DEFAULT_LBT_ED_THRESHOLD_DBM -72
|
||||
#define NR_SL_V2X_DEFAULT_MAX_LBT_FAILURES 4
|
||||
#define NR_SL_V2X_SLSCH_LCID 4
|
||||
|
||||
static bool nr_sl_v2x_is_configured(const NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
return mac != NULL && mac->SL_MAC_PARAMS != NULL && mac->sl_tx_res_pool != NULL && mac->SL_MAC_PARAMS->sl_TxPool[0] != NULL;
|
||||
}
|
||||
|
||||
static double nr_sl_v2x_random_unit(void)
|
||||
{
|
||||
return (double)(lrand48() & 0x7fffffff) / (double)0x7fffffff;
|
||||
}
|
||||
|
||||
static void nr_sl_v2x_reset_selected_list(NR_UE_MAC_INST_t *mac, const sl_resource_info_t *resource)
|
||||
{
|
||||
if (mac->sl_candidate_resources == NULL) {
|
||||
mac->sl_candidate_resources = calloc(1, sizeof(*mac->sl_candidate_resources));
|
||||
init_list(mac->sl_candidate_resources, sizeof(*resource), 1);
|
||||
} else if (mac->sl_candidate_resources->data == NULL || mac->sl_candidate_resources->element_size != sizeof(*resource)) {
|
||||
init_list(mac->sl_candidate_resources, sizeof(*resource), 1);
|
||||
} else {
|
||||
mac->sl_candidate_resources->size = 0;
|
||||
}
|
||||
|
||||
if (resource != NULL)
|
||||
push_back(mac->sl_candidate_resources, (void *)resource);
|
||||
}
|
||||
|
||||
static uint16_t nr_sl_v2x_next_reselection_counter(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
uint16_t rri = sl_mac->mac_tx_params.rri;
|
||||
uint16_t counter = get_random_reselection_counter(rri);
|
||||
|
||||
if (counter == 0)
|
||||
counter = 1;
|
||||
|
||||
sl_mac->mac_tx_params.resel_counter = counter;
|
||||
mac->sl_resel_counter = counter;
|
||||
mac->sl_c_resel = counter;
|
||||
return counter;
|
||||
}
|
||||
|
||||
static void nr_sl_v2x_release_sps_resource(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
nr_sl_v2x_sps_state_t *sps = &mac->sl_v2x_scheduler.sps;
|
||||
sps->active = false;
|
||||
sps->next_abs_slot = -1;
|
||||
sps->released++;
|
||||
nr_sl_v2x_reset_selected_list(mac, NULL);
|
||||
}
|
||||
|
||||
static bool nr_sl_v2x_pick_candidate(const List_t *candidates, sl_resource_info_t *selected)
|
||||
{
|
||||
if (candidates == NULL || candidates->size == 0)
|
||||
return false;
|
||||
|
||||
size_t idle_count = 0;
|
||||
for (size_t i = 0; i < candidates->size; i++) {
|
||||
const sl_resource_info_t *candidate = (const sl_resource_info_t *)((const char *)candidates->data + i * candidates->element_size);
|
||||
if (!candidate->slot_busy)
|
||||
idle_count++;
|
||||
}
|
||||
|
||||
size_t target = 0;
|
||||
if (idle_count > 0) {
|
||||
target = lrand48() % idle_count;
|
||||
for (size_t i = 0; i < candidates->size; i++) {
|
||||
const sl_resource_info_t *candidate = (const sl_resource_info_t *)((const char *)candidates->data + i * candidates->element_size);
|
||||
if (!candidate->slot_busy && target-- == 0) {
|
||||
*selected = *candidate;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*selected = *(const sl_resource_info_t *)((const char *)candidates->data + (lrand48() % candidates->size) * candidates->element_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool nr_sl_v2x_activate_sps_resource(NR_UE_MAC_INST_t *mac, const frameslot_t *frame_slot)
|
||||
{
|
||||
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;
|
||||
List_t *candidates = get_candidate_resources((frameslot_t *)frame_slot, mac, &mac->sl_sensing_data, &mac->sl_transmit_history);
|
||||
|
||||
sl_resource_info_t selected = {0};
|
||||
bool selected_ok = nr_sl_v2x_pick_candidate(candidates, &selected);
|
||||
if (candidates != NULL) {
|
||||
free_list_mem(candidates);
|
||||
free(candidates);
|
||||
}
|
||||
|
||||
if (!selected_ok)
|
||||
return false;
|
||||
|
||||
nr_sl_v2x_sps_state_t *sps = &mac->sl_v2x_scheduler.sps;
|
||||
sps->active = true;
|
||||
sps->pool_id = 0;
|
||||
sps->p_rsvp_slots = time_to_slots(mu, sl_mac->mac_tx_params.rri);
|
||||
if (sps->p_rsvp_slots == 0)
|
||||
sps->p_rsvp_slots = 1;
|
||||
sps->c_resel = nr_sl_v2x_next_reselection_counter(mac);
|
||||
sps->c_resel_initial = sps->c_resel;
|
||||
sps->resource = selected;
|
||||
sps->current_resource = selected;
|
||||
sps->next_abs_slot = normalize(&selected.sfn, mu);
|
||||
sps->reselections++;
|
||||
nr_sl_v2x_reset_selected_list(mac, &selected);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"SL-V2X SPS selected %4d.%2d subch %d len %d C_resel %d RRI-slots %d\n",
|
||||
selected.sfn.frame,
|
||||
selected.sfn.slot,
|
||||
selected.sl_subchan_start,
|
||||
selected.sl_subchan_len,
|
||||
sps->c_resel,
|
||||
sps->p_rsvp_slots);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nr_sl_v2x_refresh_config(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
nr_sl_v2x_scheduler_t *scheduler = &mac->sl_v2x_scheduler;
|
||||
scheduler->enabled = true;
|
||||
|
||||
if (mac->m_slProbResourceKeep <= 0.0 || mac->m_slProbResourceKeep > 1.0)
|
||||
mac->m_slProbResourceKeep = NR_SL_V2X_DEFAULT_PROB_RESOURCE_KEEP;
|
||||
|
||||
scheduler->lbt.enabled = true;
|
||||
if (scheduler->lbt.mode == NR_SL_V2X_LBT_DISABLED)
|
||||
scheduler->lbt.mode = NR_SL_V2X_LBT_TYPE2;
|
||||
if (scheduler->lbt.energy_detection_threshold_dbm == 0)
|
||||
scheduler->lbt.energy_detection_threshold_dbm = NR_SL_V2X_DEFAULT_LBT_ED_THRESHOLD_DBM;
|
||||
if (mac->SL_MAC_PARAMS->mac_tx_params.sl_thresh_rsrp != 0)
|
||||
scheduler->lbt.energy_detection_threshold_dbm = mac->SL_MAC_PARAMS->mac_tx_params.sl_thresh_rsrp;
|
||||
if (scheduler->lbt.max_consecutive_failures == 0)
|
||||
scheduler->lbt.max_consecutive_failures = NR_SL_V2X_DEFAULT_MAX_LBT_FAILURES;
|
||||
}
|
||||
|
||||
void nr_ue_sl_v2x_init_scheduler(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
AssertFatal(mac != NULL, "mac cannot be NULL\n");
|
||||
nr_sl_v2x_scheduler_t *scheduler = &mac->sl_v2x_scheduler;
|
||||
memset(scheduler, 0, sizeof(*scheduler));
|
||||
scheduler->enabled = true;
|
||||
scheduler->lbt.enabled = true;
|
||||
scheduler->lbt.mode = NR_SL_V2X_LBT_TYPE2;
|
||||
scheduler->lbt.energy_detection_threshold_dbm = NR_SL_V2X_DEFAULT_LBT_ED_THRESHOLD_DBM;
|
||||
scheduler->lbt.max_consecutive_failures = NR_SL_V2X_DEFAULT_MAX_LBT_FAILURES;
|
||||
scheduler->lbt.last_failure.frame = -1;
|
||||
scheduler->lbt.last_failure.slot = -1;
|
||||
scheduler->sps.next_abs_slot = -1;
|
||||
mac->m_slProbResourceKeep = NR_SL_V2X_DEFAULT_PROB_RESOURCE_KEEP;
|
||||
}
|
||||
|
||||
sl_resource_info_t *nr_ue_sl_v2x_select_resource(NR_UE_MAC_INST_t *mac,
|
||||
const frameslot_t *frame_slot,
|
||||
sl_sidelink_slot_type_t slot_type)
|
||||
{
|
||||
if (!nr_sl_v2x_is_configured(mac) || slot_type != SIDELINK_SLOT_TYPE_TX)
|
||||
return NULL;
|
||||
|
||||
nr_sl_v2x_refresh_config(mac);
|
||||
if (!mac->sl_v2x_scheduler.enabled)
|
||||
return mac->sl_candidate_resources ? get_resource_element(mac->sl_candidate_resources, *frame_slot) : NULL;
|
||||
|
||||
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;
|
||||
nr_sl_v2x_sps_state_t *sps = &mac->sl_v2x_scheduler.sps;
|
||||
int64_t current_abs_slot = normalize((frameslot_t *)frame_slot, mu);
|
||||
|
||||
if (!sps->active && !nr_sl_v2x_activate_sps_resource(mac, frame_slot))
|
||||
return NULL;
|
||||
|
||||
if (current_abs_slot > sps->next_abs_slot) {
|
||||
int64_t missed = ((current_abs_slot - sps->next_abs_slot) / sps->p_rsvp_slots) + 1;
|
||||
sps->next_abs_slot += missed * sps->p_rsvp_slots;
|
||||
}
|
||||
|
||||
if (current_abs_slot != sps->next_abs_slot)
|
||||
return NULL;
|
||||
|
||||
sps->current_resource = sps->resource;
|
||||
sps->current_resource.sfn = *frame_slot;
|
||||
return &sps->current_resource;
|
||||
}
|
||||
|
||||
static bool nr_sl_v2x_has_pending_tx(NR_UE_MAC_INST_t *mac, const frameslot_t *frame_slot)
|
||||
{
|
||||
if (mac->sl_tx_res_pool != NULL && mac->sl_tx_res_pool->sl_PSFCH_Config_r16 && is_feedback_scheduled(mac, frame_slot->frame, frame_slot->slot))
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < MAX_SL_UE_CONNECTIONS && mac->sl_info.list[i] != NULL; i++) {
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &mac->sl_info.list[i]->UE_sched_ctrl;
|
||||
if (sched_ctrl->retrans_sl_harq.head >= 0)
|
||||
return true;
|
||||
if (sched_ctrl->sched_csi_report.active &&
|
||||
sched_ctrl->sched_csi_report.frame == frame_slot->frame &&
|
||||
sched_ctrl->sched_csi_report.slot == frame_slot->slot)
|
||||
return true;
|
||||
}
|
||||
|
||||
mac_rlc_status_resp_t rlc_status = nr_mac_rlc_status_ind(mac->ue_id, frame_slot->frame, NR_SL_V2X_SLSCH_LCID);
|
||||
return rlc_status.bytes_in_buffer > 0;
|
||||
}
|
||||
|
||||
static bool nr_sl_v2x_sensed_resource_busy(NR_UE_MAC_INST_t *mac, const sl_resource_info_t *resource, const frameslot_t *frame_slot)
|
||||
{
|
||||
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;
|
||||
int64_t cycle_slots = nr_slots_per_frame[mu] * 1024;
|
||||
int64_t target_abs = normalize((frameslot_t *)frame_slot, mu);
|
||||
int16_t threshold = mac->sl_v2x_scheduler.lbt.energy_detection_threshold_dbm;
|
||||
|
||||
for (size_t i = 0; i < mac->sl_sensing_data.size; i++) {
|
||||
const sensing_data_t *sensed = (const sensing_data_t *)((const char *)mac->sl_sensing_data.data + i * mac->sl_sensing_data.element_size);
|
||||
if (sensed->sl_rsrp <= threshold)
|
||||
continue;
|
||||
if (!overlapped_resource(sensed->subch_start, sensed->subch_len, resource->sl_subchan_start, resource->sl_subchan_len))
|
||||
continue;
|
||||
|
||||
int64_t sensed_abs = normalize((frameslot_t *)&sensed->frame_slot, mu);
|
||||
int64_t diff = (target_abs - sensed_abs + cycle_slots) % cycle_slots;
|
||||
if (diff == 0)
|
||||
return true;
|
||||
|
||||
uint16_t p_rsvp_slots = sensed->rsvp ? time_to_slots(mu, sensed->rsvp) : 0;
|
||||
if (p_rsvp_slots > 0 && diff > 0 && (diff % p_rsvp_slots) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nr_ue_sl_v2x_lbt_allows_tx(NR_UE_MAC_INST_t *mac,
|
||||
const sl_resource_info_t *resource,
|
||||
const frameslot_t *frame_slot)
|
||||
{
|
||||
if (!nr_sl_v2x_is_configured(mac) || resource == NULL || !mac->sl_v2x_scheduler.lbt.enabled)
|
||||
return true;
|
||||
if (!nr_sl_v2x_has_pending_tx(mac, frame_slot))
|
||||
return true;
|
||||
|
||||
nr_sl_v2x_lbt_state_t *lbt = &mac->sl_v2x_scheduler.lbt;
|
||||
lbt->attempts++;
|
||||
|
||||
if (!nr_sl_v2x_sensed_resource_busy(mac, resource, frame_slot))
|
||||
return true;
|
||||
|
||||
lbt->failures++;
|
||||
lbt->consecutive_failures++;
|
||||
lbt->last_failure = *frame_slot;
|
||||
LOG_D(NR_MAC,
|
||||
"SL-V2X LBT busy at %4d.%2d subch %d len %d RSRP threshold %d failures %d/%d\n",
|
||||
frame_slot->frame,
|
||||
frame_slot->slot,
|
||||
resource->sl_subchan_start,
|
||||
resource->sl_subchan_len,
|
||||
lbt->energy_detection_threshold_dbm,
|
||||
lbt->consecutive_failures,
|
||||
lbt->max_consecutive_failures);
|
||||
|
||||
if (lbt->consecutive_failures >= lbt->max_consecutive_failures) {
|
||||
LOG_D(NR_MAC, "SL-V2X LBT releasing SPS resource after consecutive failures\n");
|
||||
nr_sl_v2x_release_sps_resource(mac);
|
||||
lbt->consecutive_failures = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void nr_ue_sl_v2x_notify_tx_result(NR_UE_MAC_INST_t *mac,
|
||||
const sl_resource_info_t *resource,
|
||||
const frameslot_t *frame_slot,
|
||||
bool transmitted)
|
||||
{
|
||||
if (!nr_sl_v2x_is_configured(mac) || resource == NULL || !mac->sl_v2x_scheduler.sps.active || !transmitted)
|
||||
return;
|
||||
|
||||
nr_sl_v2x_scheduler_t *scheduler = &mac->sl_v2x_scheduler;
|
||||
nr_sl_v2x_sps_state_t *sps = &scheduler->sps;
|
||||
scheduler->lbt.successes++;
|
||||
scheduler->lbt.consecutive_failures = 0;
|
||||
|
||||
if (sps->c_resel > 0)
|
||||
sps->c_resel--;
|
||||
mac->sl_c_resel = sps->c_resel;
|
||||
mac->sl_resel_counter = sps->c_resel;
|
||||
mac->SL_MAC_PARAMS->mac_tx_params.resel_counter = sps->c_resel;
|
||||
|
||||
if (sps->c_resel == 0) {
|
||||
if (nr_sl_v2x_random_unit() <= mac->m_slProbResourceKeep) {
|
||||
sps->c_resel = nr_sl_v2x_next_reselection_counter(mac);
|
||||
sps->c_resel_initial = sps->c_resel;
|
||||
sps->kept++;
|
||||
LOG_D(NR_MAC,
|
||||
"SL-V2X SPS keeping resource %4d.%2d subch %d for C_resel %d\n",
|
||||
sps->resource.sfn.frame,
|
||||
sps->resource.sfn.slot,
|
||||
sps->resource.sl_subchan_start,
|
||||
sps->c_resel);
|
||||
} else {
|
||||
LOG_D(NR_MAC,
|
||||
"SL-V2X SPS releasing resource %4d.%2d subch %d after C_resel expiry\n",
|
||||
frame_slot->frame,
|
||||
frame_slot->slot,
|
||||
resource->sl_subchan_start);
|
||||
nr_sl_v2x_release_sps_resource(mac);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sps->next_abs_slot += sps->p_rsvp_slots;
|
||||
}
|
||||
77
openair2/LAYER2/NR_MAC_UE/nr_ue_sci.h
Normal file
77
openair2/LAYER2/NR_MAC_UE/nr_ue_sci.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* \file nr_ue_sci.h
|
||||
* \brief Definitions and Structures for sci/slsch procedures for Sidelink UE
|
||||
* \author R. Knopp
|
||||
* \date 2023
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef __LAYER2_NR_UE_SCI_H__
|
||||
#define __LAYER2_NR_UE_SCI_H__
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
|
||||
typedef enum {
|
||||
NR_SL_SCI_FORMAT_1A = 0,
|
||||
NR_SL_SCI_FORMAT_2A = 1,
|
||||
NR_SL_SCI_FORMAT_2B = 2,
|
||||
NR_SL_SCI_FORMAT_2C = 3
|
||||
} nr_sci_format_t;
|
||||
|
||||
typedef struct {
|
||||
// 1st stage fields
|
||||
uint8_t priority; // 3 bits
|
||||
dci_field_t frequency_resource_assignment; // depending on sl-MaxNumPerReserve and N_subChannel^SL
|
||||
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
|
||||
1027
openair2/LAYER2/NR_MAC_UE/nr_ue_sci_slsch.c
Normal file
1027
openair2/LAYER2/NR_MAC_UE/nr_ue_sci_slsch.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -268,27 +268,6 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
|
||||
return mat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the first UL slot index in period
|
||||
* @param fs frame structure
|
||||
* @param mixed indicates whether to include in the count also mixed slot with UL symbols or only full UL slot
|
||||
* @return slot index
|
||||
*/
|
||||
int get_first_ul_slot(const frame_structure_t *fs, bool mixed)
|
||||
{
|
||||
DevAssert(fs);
|
||||
|
||||
if (fs->frame_type == TDD) {
|
||||
for (int i = 0; i < fs->numb_slots_period; i++) {
|
||||
if ((mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // FDD
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of DL slots per period (full DL slots + mixed slots with DL symbols)
|
||||
*/
|
||||
|
||||
@@ -66,62 +66,6 @@
|
||||
#define NR_RRC_RECONFIGURATION_DELAY_MS 10
|
||||
#define NR_RRC_BWP_SWITCHING_DELAY_MS 6
|
||||
|
||||
// #define DEBUG_DCI
|
||||
// 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}};
|
||||
|
||||
static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS],
|
||||
float pdcch_cl_adjust);
|
||||
|
||||
@@ -282,47 +226,6 @@ int get_mcs_from_SINRx10(int mcs_table, int SINRx10, int Nl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -782,45 +685,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)
|
||||
{
|
||||
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 || num_dl_sched <= 3) // above threshold or no activity
|
||||
new_mcs -= 1;
|
||||
// else we are within threshold boundaries
|
||||
|
||||
new_mcs = max(new_mcs, bler_options->min_mcs);
|
||||
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;
|
||||
}
|
||||
|
||||
nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_SearchSpace_t *ss,
|
||||
@@ -2338,6 +2202,7 @@ void dump_nr_list(NR_UE_info_t **list)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Create a new NR_list
|
||||
*/
|
||||
@@ -2463,6 +2328,7 @@ void remove_front_nr_list(NR_list_t *listP)
|
||||
if (listP->head < 0)
|
||||
listP->tail = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,6 @@ void set_cset_offset(uint16_t);
|
||||
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers);
|
||||
int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc);
|
||||
|
||||
int get_first_ul_slot(const frame_structure_t *fs, bool mixed);
|
||||
int get_ul_slots_per_period(const frame_structure_t *fs);
|
||||
int get_ul_slots_per_frame(const frame_structure_t *fs);
|
||||
int get_dl_slots_per_period(const frame_structure_t *fs);
|
||||
@@ -396,7 +395,6 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac,
|
||||
int xp_pdsch_antenna_ports);
|
||||
|
||||
int get_mcs_from_SINRx10(int mcs_table, int SINRx10, int Nl);
|
||||
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);
|
||||
int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
|
||||
@@ -438,12 +436,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 slots_per_frame, int size);
|
||||
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac);
|
||||
|
||||
@@ -102,15 +102,6 @@
|
||||
|
||||
uint8_t nr_get_rv(int rel_round);
|
||||
|
||||
/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...).
|
||||
* Especially useful in the scheduler and to keep "classes" of users. */
|
||||
typedef struct {
|
||||
int head;
|
||||
int *next;
|
||||
int tail;
|
||||
int len;
|
||||
} NR_list_t;
|
||||
|
||||
typedef enum {
|
||||
nrRA_gNB_IDLE,
|
||||
nrRA_Msg2,
|
||||
@@ -520,13 +511,6 @@ typedef struct NR_UE_harq {
|
||||
|
||||
//! 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
|
||||
@@ -708,19 +692,6 @@ typedef struct {
|
||||
float pdcch_cl_adjust;
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct NR_mac_dir_stats {
|
||||
uint64_t lc_bytes[64];
|
||||
uint64_t rounds[8];
|
||||
uint64_t errors;
|
||||
uint64_t total_bytes;
|
||||
uint32_t current_bytes;
|
||||
uint64_t total_sdu_bytes;
|
||||
uint32_t total_rbs;
|
||||
uint32_t total_rbs_retx;
|
||||
uint32_t num_mac_sdu;
|
||||
uint32_t current_rbs;
|
||||
} NR_mac_dir_stats_t;
|
||||
|
||||
typedef struct NR_mac_stats {
|
||||
NR_mac_dir_stats_t dl;
|
||||
NR_mac_dir_stats_t ul;
|
||||
@@ -737,14 +708,6 @@ typedef struct NR_mac_stats {
|
||||
int NPRB;
|
||||
} NR_mac_stats_t;
|
||||
|
||||
typedef struct NR_bler_options {
|
||||
double upper;
|
||||
double lower;
|
||||
uint8_t min_mcs;
|
||||
uint8_t max_mcs;
|
||||
uint8_t harq_round_max;
|
||||
} NR_bler_options_t;
|
||||
|
||||
typedef struct nr_mac_rrc_ul_if_s {
|
||||
f1_reset_du_initiated_func_t f1_reset;
|
||||
f1_reset_acknowledge_cu_initiated_func_t f1_reset_acknowledge;
|
||||
|
||||
@@ -46,3 +46,4 @@ ENCODE_DECODE(t_reordering, T_REORDERING)
|
||||
ENCODE_DECODE(sn_size_ul, SN_SIZE)
|
||||
ENCODE_DECODE(sn_size_dl, SN_SIZE)
|
||||
ENCODE_DECODE(discard_timer, DISCARD_TIMER)
|
||||
ENCODE_DECODE(discard_timer_sl, DISCARD_TIMER_SL)
|
||||
|
||||
@@ -26,10 +26,12 @@ int decode_t_reordering(int v);
|
||||
int decode_sn_size_ul(int v);
|
||||
int decode_sn_size_dl(int v);
|
||||
int decode_discard_timer(int v);
|
||||
int decode_discard_timer_sl(int v);
|
||||
|
||||
int encode_t_reordering(int v);
|
||||
int encode_sn_size_ul(int v);
|
||||
int encode_sn_size_dl(int v);
|
||||
int encode_discard_timer(int v);
|
||||
|
||||
|
||||
#endif /* _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ */
|
||||
|
||||
@@ -58,12 +58,21 @@
|
||||
|
||||
#define SIZEOF_NR_PDCP_DISCARD_TIMER INT_LIST_SIZE(VALUES_NR_PDCP_DISCARD_TIMER)
|
||||
|
||||
#define VALUES_NR_PDCP_DISCARD_TIMER_SL \
|
||||
3, 10, 20, 25, 30, 40, 50, 60, 75, 100, 150, 200, 250, 300, 500, 750, 1500, -1 /* -1 means infinity */
|
||||
|
||||
#define VALUES_NR_PDCP_DISCARD_TIMER_SL_STR \
|
||||
"ms3", "ms10", "ms20", "ms25", "ms30", "ms40", "ms50", "ms60", "ms75", "ms100", "ms150", "ms200", "ms250", "ms300", "ms500", "ms750", "ms1500", "infinity"
|
||||
|
||||
#define SIZEOF_NR_PDCP_DISCARD_TIMER_SL INT_LIST_SIZE(VALUES_NR_PDCP_DISCARD_TIMER_SL)
|
||||
|
||||
/* configuration of NR PDCP, coming from configuration file */
|
||||
typedef struct {
|
||||
struct {
|
||||
int sn_size;
|
||||
int t_reordering;
|
||||
int discard_timer;
|
||||
int discard_timer_sl;
|
||||
} drb;
|
||||
} nr_pdcp_configuration_t;
|
||||
|
||||
|
||||
@@ -640,6 +640,69 @@ void nr_pdcp_add_drb(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 t_reordering = 20;
|
||||
|
||||
// get SDAP config
|
||||
sdap_config_t sdap = {0};
|
||||
sdap.pdusession_id = 0;
|
||||
sdap.drb_id = slrb_id;
|
||||
|
||||
int role = 0;
|
||||
if (s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_SDAP_Header_r16 == NR_SL_SDAP_Config_r16__sl_SDAP_Header_r16_present)
|
||||
{
|
||||
role |= SDAP_UL_TX | SDAP_DL_RX;
|
||||
}
|
||||
sdap.role = role;
|
||||
sdap.defaultDRB = s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_DefaultRB_r16 == true ? true : false;
|
||||
|
||||
if (s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16) {
|
||||
sdap.mappedQFIs2AddCount = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16->list.count;
|
||||
DevAssert(sdap.mappedQFIs2AddCount <= SDAP_MAX_QFI);
|
||||
LOG_D(SDAP, "SL DRB %d: mapped QFIs = %d \n", slrb_id, sdap.mappedQFIs2AddCount);
|
||||
|
||||
long standardized_PQI = 0;
|
||||
for (int i = 0; i < sdap.mappedQFIs2AddCount; i++){
|
||||
DevAssert(i < SDAP_MAX_QFI);
|
||||
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 < SDAP_MAX_QFI)
|
||||
sdap.mappedQFIs2Add[i] = standardized_PQI;
|
||||
LOG_D(SDAP, "SL DRB %d: Captured mappedQoS_FlowsToAdd[%d] from RRC: %ld\n", slrb_id, i, sdap.mappedQFIs2Add[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// add SDAP entity
|
||||
nr_sdap_addmod_entity(GNB_FLAG_NO, srcid, &sdap);
|
||||
|
||||
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,
|
||||
(sdap.role & (SDAP_UL_RX | SDAP_DL_RX)) != 0,
|
||||
(sdap.role & (SDAP_UL_TX | SDAP_DL_TX)) != 0,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb_ue, ue,
|
||||
sn_size, t_reordering, discard_timer,
|
||||
security_parameters);
|
||||
|
||||
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 nr_pdcp_add_srbs(eNB_flag_t enb_flag,
|
||||
ue_id_t UEid,
|
||||
NR_SRB_ToAddModList_t *const srb2add_list,
|
||||
|
||||
@@ -131,4 +131,6 @@ void nr_pdcp_count_update(ue_id_t ue_id,
|
||||
|
||||
void nr_pdcp_get_drb_count_values(ue_id_t ue_id, rb_id_t rb_id, nr_pdcp_count_t *ul_count, nr_pdcp_count_t *dl_count);
|
||||
|
||||
void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *sl_rb_config, const nr_pdcp_entity_security_keys_and_algos_t *security_parameters);
|
||||
|
||||
#endif /* NR_PDCP_OAI_API_H */
|
||||
|
||||
@@ -43,6 +43,13 @@
|
||||
#include "openair3/ocp-gtpu/gtp_itf.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static logical_chan_id_t get_sl_lcid_from_drb(int drb_id)
|
||||
{
|
||||
logical_chan_id_t lcid = 4 + drb_id - 1;
|
||||
AssertFatal(lcid >= 4 && lcid <= 19, "Invalid SL DRB ID %d for LCID %d\n", drb_id, lcid);
|
||||
return lcid;
|
||||
}
|
||||
|
||||
#include <executables/softmodem-common.h>
|
||||
|
||||
static nr_rlc_ue_manager_t *nr_rlc_ue_manager;
|
||||
@@ -802,6 +809,71 @@ 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);
|
||||
logical_chan_id_t lcid = get_sl_lcid_from_drb(drb_id);
|
||||
ue->lcid2rb[lcid - 1].type = NR_LCID_DRB;
|
||||
ue->lcid2rb[lcid - 1].choice.drb_id = drb_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;
|
||||
@@ -853,6 +925,57 @@ 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);
|
||||
logical_chan_id_t lcid = get_sl_lcid_from_drb(drb_id);
|
||||
ue->lcid2rb[lcid - 1].type = NR_LCID_DRB;
|
||||
ue->lcid2rb[lcid - 1].choice.drb_id = drb_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) {
|
||||
@@ -869,6 +992,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);
|
||||
}
|
||||
|
||||
struct srb0_data {
|
||||
int ue_id;
|
||||
void *data;
|
||||
|
||||
@@ -63,6 +63,7 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -385,6 +385,86 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id)
|
||||
return nr_ue_if_module_inst[module_id];
|
||||
}
|
||||
|
||||
/*
|
||||
int nr_ue_scireq(nr_scireq_t *scireq) {
|
||||
|
||||
sl_nr_rx_config_request_t *sl_config = &scireq->sl_config_req;
|
||||
NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0);
|
||||
sl_config->sfn = scireq->frame;
|
||||
sl_config->slot = scireq->slot;
|
||||
|
||||
LOG_T(PHY, "Entering UE SCI configuration frame %d slot %d \n", scireq->frame, scireq->slot);
|
||||
// ue_sci_configuration(UE_mac, sl_config, scireq->frame, scireq->slot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int nr_ue_sl_indication_rk(nr_sidelink_indication_t *sl_info)
|
||||
{
|
||||
pthread_mutex_lock(&mac_IF_mutex);
|
||||
uint32_t ret_mask = 0x0;
|
||||
module_id_t module_id = sl_info->module_id;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
if ((!sl_info->sci_ind && !sl_info->rx_ind)) {
|
||||
// indication to schedule SCI reception
|
||||
if (mac->phy_config_request_sent)
|
||||
nr_ue_sl_scheduler(sl_info);
|
||||
} else {
|
||||
// SL indication after reception of SCI or SL PDU
|
||||
if (sl_info && sl_info->sci_ind && sl_info->sci_ind->number_of_SCIs) {
|
||||
LOG_T(MAC,"[L2][IF MODULE][SL INDICATION][SCI_IND]\n");
|
||||
for (int i = 0; i < sl_info->sci_ind->number_of_SCIs; i++) {
|
||||
LOG_T(MAC,">>>NR_IF_Module i=%d, sl_info->sci_ind->number_of_scis=%d\n",i,sl_info->sci_ind->number_of_SCIs);
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
int8_t ret = handle_sci(sl_info->module_id,
|
||||
sl_info->frame_rx,
|
||||
sl_info->slot_rx,
|
||||
sl_info->sci_ind->sci_pdu+i);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
sl_nr_sci_indication_pdu_t *sci_index = sl_info->sci_ind->sci_pdu+i;
|
||||
|
||||
AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is NULL!\n" );
|
||||
AssertFatal( nr_ue_if_module_inst[module_id]->scheduled_response != NULL, "scheduled_response is NULL!\n" );
|
||||
sl_nr_rx_config_request_t *sl_config = get_sl_config_request(mac, sl_info->slot_rx);
|
||||
fill_sl_scheduled_response(&scheduled_response, sl_config, NULL, NULL, sl_info->module_id, sl_info->frame_rx, sl_info->slot_rx, sl_info->phy_data);
|
||||
nr_ue_if_module_inst[module_id]->scheduled_response(&scheduled_response);
|
||||
}
|
||||
sl_info->sci_ind = NULL;
|
||||
}
|
||||
|
||||
if (sl_info->rx_ind != NULL) {
|
||||
|
||||
for (int i = 0; i < sl_info->rx_ind->number_pdus; ++i) {
|
||||
|
||||
sl_nr_rx_indication_body_t rx_indication_body = sl_info->rx_ind->rx_indication_body[i];
|
||||
LOG_D(NR_MAC, "Sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n",
|
||||
rx_indication_body.pdu_type,
|
||||
sl_info->rx_ind->number_pdus);
|
||||
|
||||
switch(rx_indication_body.pdu_type){
|
||||
|
||||
case SL_NR_RX_PDU_TYPE_SSB:
|
||||
break;
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH:
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Unknown RX indication type\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
sl_info->rx_ind = NULL;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mac_IF_mutex);
|
||||
return ret_mask;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static void handle_sl_bch(int ue_id,
|
||||
sl_nr_ue_mac_params_t *sl_mac,
|
||||
uint8_t *const sl_mib,
|
||||
@@ -425,6 +505,28 @@ 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, 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_sci1_indication_pdu(mac,module_id,cc_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
|
||||
@@ -466,11 +568,46 @@ 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, "[UE%d]SL-MAC Received SLSCH: rx_slsch_pdu:%p, rx_slsch_len %d, ack_nack %d, harq_pid %d\n",
|
||||
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:
|
||||
AssertFatal(1 == 0, "Incorrect type received. %s\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,"%d.%d Received PSCCH PDU %d/%d PSCCH RSRP %d, length %d, sub-channel index %d, Nid %x, payload %llx\n", 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, cc_id, frame, slot, &sci_ind->sci_pdu[idx], phy_data);
|
||||
break;
|
||||
case SL_SCI_FORMAT_2_ON_PSSCH:
|
||||
LOG_D(NR_MAC,"%d.%d Received PSSCH PDU %d/%d PSSCH RSRP %d, length %d, payload %llx\n", 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,6 +621,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;
|
||||
@@ -493,6 +631,8 @@ 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);
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).frame = frame; //frameP
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).slot = slot;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu_size = sdu_size;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).gnb_index = gNB_index;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND(message_p).rx_slss_id = cellid; // cellid is rx slss id
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
|
||||
bool csi_meas,
|
||||
bool is_neighboring_cell,
|
||||
int rsrp_dBm);
|
||||
|
||||
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id);
|
||||
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload);
|
||||
void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id);
|
||||
|
||||
@@ -2681,6 +2681,8 @@ void *rrc_nrue(void *notUsed)
|
||||
|
||||
nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu,
|
||||
sbcch->sdu_size, sbcch->rx_slss_id);
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_MEAS_DATA_IND:
|
||||
|
||||
LOG_D(NR_RRC, "[%s][Nid_cell %i] Received %s measurements: RSRP = %i (dBm)\n",
|
||||
@@ -3057,15 +3059,25 @@ void handle_t430_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 = get_NR_UE_rrc_inst(instance);
|
||||
nr_pdcp_entity_security_keys_and_algos_t security_up_parameters = get_security_rrc_parameters(rrc, false);
|
||||
|
||||
// these 3 are configured differently in Sidelink
|
||||
int has_integrity = 0;
|
||||
int has_ciphering = 0;
|
||||
// int has_rohc = 0;
|
||||
|
||||
security_up_parameters.ciphering_algorithm = has_ciphering ? rrc->cipheringAlgorithm : 0;
|
||||
security_up_parameters.integrity_algorithm = has_integrity ? rrc->integrityProtAlgorithm : 0;
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
|
||||
AssertFatal(ueinfo != NULL, "Sidelink UE info not configured\n");
|
||||
|
||||
//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, &security_up_parameters);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
#include "common/utils/ocp_itti/intertask_interface.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.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);
|
||||
@@ -87,11 +89,12 @@ void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc,
|
||||
struct NR_SetupRelease_RLF_TimersAndConstants *rlf_TimersAndConstants);
|
||||
|
||||
int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source);
|
||||
//void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source, ueinfo_t *ueinfo);
|
||||
|
||||
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, nr_pdcp_entity_security_keys_and_algos_t *security_up_parameters);
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
@@ -105,4 +108,3 @@ void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf);
|
||||
|
||||
/** @}*/
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,6 +30,19 @@
|
||||
#include "rrc_defs.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "nr-uesoftmodem.h"
|
||||
#include "tun_if.h"
|
||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.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)
|
||||
{
|
||||
@@ -109,6 +122,15 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
sl_res_pool->sl_PSSCH_Config_r16 = calloc(1, sizeof(NR_SetupRelease_SL_PSSCH_Config_r16_t));
|
||||
sl_res_pool->sl_PSSCH_Config_r16->present = NR_SetupRelease_SL_PSSCH_Config_r16_PR_setup;
|
||||
sl_res_pool->sl_PSSCH_Config_r16->choice.setup = calloc(1, sizeof(NR_SL_PSSCH_Config_r16_t));
|
||||
|
||||
sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_BetaOffsets2ndSCI_r16 =
|
||||
calloc(1, sizeof(*sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_BetaOffsets2ndSCI_r16));
|
||||
for(int i=0; i<4; i++) {
|
||||
long *p = calloc(1, sizeof(long));
|
||||
*p = i<<2; // valid values: 0...15, for the moment choose 0,4,8,12
|
||||
ASN_SEQUENCE_ADD(&sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_BetaOffsets2ndSCI_r16->list, p);
|
||||
}
|
||||
|
||||
sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_PSSCH_DMRS_TimePatternList_r16 =
|
||||
calloc(1, sizeof(*sl_res_pool->sl_PSSCH_Config_r16->choice.setup->sl_PSSCH_DMRS_TimePatternList_r16));
|
||||
for(int i=0; i<3; i++) {
|
||||
@@ -117,8 +139,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 +202,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,8 +216,13 @@ 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_TxPercentageList_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 = calloc(1, sizeof(*sl_res_pool->sl_TxPercentageList_r16));
|
||||
sl_res_pool->sl_TxPercentageList_r16->list.array = (NR_SL_TxPercentageConfig_r16_t **)malloc16_clear(sizeof(NR_SL_TxPercentageConfig_r16_t*));
|
||||
sl_res_pool->sl_TxPercentageList_r16->list.array[0] = (NR_SL_TxPercentageConfig_r16_t *)malloc16_clear(sizeof(NR_SL_TxPercentageConfig_r16_t));
|
||||
sl_res_pool->sl_MinMaxMCS_List_r16 = NULL;
|
||||
|
||||
sl_res_pool->ext1 = calloc(1, sizeof(*sl_res_pool->ext1));
|
||||
@@ -193,9 +249,72 @@ static void prepare_NR_SL_ResourcePool(NR_SL_ResourcePool_r16_t *sl_res_pool,
|
||||
if (is_txpool)
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", SL_CONFIG_STRING_SL_PRECONFIGURATION, 0,SL_CONFIG_STRING_SL_TX_RPOOL_LIST, 0);
|
||||
else
|
||||
{
|
||||
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);
|
||||
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 +471,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 +570,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;
|
||||
@@ -508,19 +680,70 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
return;
|
||||
}
|
||||
|
||||
static uint8_t get_sl_tun_qfi(NR_SL_PreconfigurationNR_r16_t *sl_preconfig)
|
||||
{
|
||||
NR_SL_RadioBearerConfig_r16_t *slrb =
|
||||
sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.array[0];
|
||||
DevAssert(slrb != NULL);
|
||||
struct NR_SL_SDAP_Config_r16 *sdap = slrb->sl_SDAP_Config_r16;
|
||||
DevAssert(sdap != NULL && sdap->sl_MappedQoS_Flows_r16 != NULL);
|
||||
struct NR_SL_SDAP_Config_r16__sl_MappedQoS_Flows_r16__sl_MappedQoS_FlowsList_r16 *flows =
|
||||
sdap->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16;
|
||||
DevAssert(flows != NULL && flows->list.count > 0);
|
||||
NR_SL_QoS_Profile_r16_t *profile = flows->list.array[0];
|
||||
DevAssert(profile != NULL && profile->sl_PQI_r16 != NULL);
|
||||
const long standardized_PQI = profile->sl_PQI_r16->choice.sl_StandardizedPQI_r16;
|
||||
DevAssert(standardized_PQI >= 0 && standardized_PQI < SDAP_MAX_QFI);
|
||||
return standardized_PQI;
|
||||
}
|
||||
|
||||
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 sync_source,
|
||||
ueinfo_t *ueinfo,
|
||||
nr_pdcp_entity_security_keys_and_algos_t *security_up_parameters)
|
||||
{
|
||||
|
||||
AssertFatal(rrc_inst, "RRC instance not created.\n");
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = rrc_inst->sl_preconfig;
|
||||
|
||||
AssertFatal(rrc_inst->sl_preconfig, "Check if SL-preconfig was created");
|
||||
|
||||
AssertFatal(sync_source != SL_SYNC_SOURCE_GNBENB, "Sync source GNB not supported\n");
|
||||
|
||||
LOG_D(NR_RRC, "SL L2 SRCid %x, SL ipv4 addr X.X.%d.%d\n", ueinfo->srcid, ueinfo->thirdOctet, ueinfo->fourthOctet);
|
||||
#if 0
|
||||
nas_config(1 + ueinfo->srcid, ueinfo->thirdOctet, ueinfo->fourthOctet, "oai_sl_tun");
|
||||
#else
|
||||
char ip[20];
|
||||
snprintf(ip,
|
||||
sizeof(ip),
|
||||
"10.0.%d.%d",
|
||||
ueinfo->thirdOctet, ueinfo->fourthOctet);
|
||||
|
||||
char ifname[IFNAMSIZ];
|
||||
tun_generate_ifname(ifname, "oai_sl_tun", ueinfo->srcid);
|
||||
int sl_tun_sock = tun_alloc(ifname);
|
||||
if (sl_tun_sock >= 0 && tun_config(ifname, ip, NULL))
|
||||
{
|
||||
setup_ue_ipv4_route(ifname, ueinfo->srcid, ip);
|
||||
}
|
||||
#endif
|
||||
nr_rrc_mac_config_req_sl_preconfig(rrc_inst->ue_id, sl_preconfig, sync_source);
|
||||
|
||||
// SL RadioBearers
|
||||
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], security_up_parameters);
|
||||
}
|
||||
if (sl_tun_sock >= 0) {
|
||||
set_qfi(get_sl_tun_qfi(sl_preconfig), 0, ueinfo->srcid);
|
||||
start_sdap_tun_ue(ueinfo->srcid, 0, sl_tun_sock);
|
||||
}
|
||||
// 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;
|
||||
|
||||
@@ -74,9 +74,27 @@
|
||||
#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_RSRC_SEL_TX_PERCENTAGE "sl_TxPercentage"
|
||||
|
||||
|
||||
#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 +166,37 @@
|
||||
*/
|
||||
#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}, \
|
||||
{SL_CONFIG_STRING_RSRC_SEL_TX_PERCENTAGE,NULL,0,.i64ptr=&sl_res_pool->sl_TxPercentageList_r16->list.array[0]->sl_TxPercentage_r16,.defint64val=0,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
|
||||
|
||||
28
targets/PROJECTS/NR-SIDELINK/CONF/channelmod_rfsimu.conf
Normal file
28
targets/PROJECTS/NR-SIDELINK/CONF/channelmod_rfsimu.conf
Normal file
@@ -0,0 +1,28 @@
|
||||
#/* configuration for channel modelisation */
|
||||
#/* To be included in main config file when */
|
||||
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
|
||||
channelmod = {
|
||||
max_chan=10;
|
||||
modellist="modellist_rfsimu_1";
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "rfsimu_channel_ue0"
|
||||
type = "AWGN";
|
||||
ploss_dB = 10;
|
||||
noise_power_dB = -10;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
},
|
||||
{
|
||||
model_name = "rfsimu_channel_enB0"
|
||||
type = "AWGN";
|
||||
ploss_dB = 10;
|
||||
noise_power_dB = -10;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
28
targets/PROJECTS/NR-SIDELINK/CONF/channelmod_rfsimu_nb.conf
Normal file
28
targets/PROJECTS/NR-SIDELINK/CONF/channelmod_rfsimu_nb.conf
Normal file
@@ -0,0 +1,28 @@
|
||||
#/* configuration for channel modelisation */
|
||||
#/* To be included in main config file when */
|
||||
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
|
||||
channelmod = {
|
||||
max_chan=10;
|
||||
modellist="modellist_rfsimu_1";
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "rfsimu_channel_ue0"
|
||||
type = "AWGN";
|
||||
ploss_dB = 10;
|
||||
noise_power_dB = -10;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
},
|
||||
{
|
||||
model_name = "rfsimu_channel_enB0"
|
||||
type = "AWGN";
|
||||
ploss_dB = 10;
|
||||
noise_power_dB = -10;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
155
targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf
Normal file
155
targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf
Normal file
@@ -0,0 +1,155 @@
|
||||
SIDELINK_PRECONFIGURATION = (
|
||||
{
|
||||
# TDD ULDL CONFIG used for sidelink
|
||||
sl_dl_UL_TransmissionPeriodicity = 6;
|
||||
sl_nrofDownlinkSlots = 6;
|
||||
sl_nrofDownlinkSymbols = 0;
|
||||
sl_nrofUplinkSlots = 4;
|
||||
sl_nrofUplinkSymbols = 0;
|
||||
sl_csi_rs = (
|
||||
{
|
||||
symb_l0 = 5;
|
||||
# csi_type 2 is not supported 38211, 8.4.1.5.3
|
||||
csi_Type = 1;
|
||||
sl_powerControlOffset = 1;
|
||||
sl_powerControlOffsetSS = 1;
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
sl_AllowedResourceSelectionConfig = 3; // Supported only {0, 3, 4, 6}
|
||||
|
||||
sl_FrequencyCommonConfig = (
|
||||
{
|
||||
sl_offstToCarrier = 0;
|
||||
sl_subcarrierSpacing = 1;//0-15Khz, 1-30Khz
|
||||
sl_carrierBandwidth = 106;//numPRBs
|
||||
#NR bands for Sidelink n47, n38. N47 - 5855Mhz - 5925Mhz
|
||||
#SL SSB chosen to be located from RB10 to RB21. points to the middle of the SSB block.
|
||||
#SSB location should be within Sidelink BWP
|
||||
# this is 2584.95 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
sl_absoluteFrequencySSB = 516990;
|
||||
# this is 2575.92 MHz (center frequency is 2585.1 MHz
|
||||
sl_absoluteFrequencyPointA = 515184;
|
||||
}
|
||||
);
|
||||
|
||||
sl_BWP = (
|
||||
{
|
||||
#RB start 0, RB size = 106. occupies complete Bw.
|
||||
sl_locationAndBandwidth = 28875;
|
||||
# Num Symbols used for Sidelink in an uplink slot
|
||||
# Herein, sl_LengthSymbols represents an index; not the number of symbols.
|
||||
# This index value can be from 0 to 7 representing the (7 to 14 symbols)
|
||||
sl_LengthSymbols = 7;
|
||||
#Sidelink Starting symbol in a slot
|
||||
#Value can be between symbols 0 to 7
|
||||
sl_StartSymbol = 0;
|
||||
}
|
||||
);
|
||||
|
||||
sl_syncCfg = (
|
||||
{
|
||||
#NUM SL-SSB within 16 frames
|
||||
sl_NumSSB_WithinPeriod_0 = 4;
|
||||
#Slot Offset for the first txn in the 16 frame period
|
||||
sl_TimeOffsetSSB_0 = 8;
|
||||
#interval in slots for repetition of SL-SSB
|
||||
sl_TimeInterval_0 = 120;
|
||||
}
|
||||
);
|
||||
|
||||
sl_ConfiguredGrantConfig = (
|
||||
{
|
||||
sl_NrOfHARQ_Processes = 16;
|
||||
sl_HARQ_ProcID_offset = 0;
|
||||
sl_periodic_rsc_rsr_interval = 100;
|
||||
}
|
||||
);
|
||||
sl_RxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//10RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
sl_TxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//50RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
rsrc_selection_params = (
|
||||
{
|
||||
# Resource selection parameters
|
||||
sl_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_TxPercentage = 0; // index of {20, 35, 50}
|
||||
}
|
||||
);
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 0;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
156
targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf
Normal file
156
targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf
Normal file
@@ -0,0 +1,156 @@
|
||||
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_TxPercentage = 0; // index of {20, 35, 50}
|
||||
}
|
||||
);
|
||||
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 1;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 2;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user