Compare commits

...

24 Commits

Author SHA1 Message Date
Robert Schmidt
e0927b58ff warnings and undeclared functions 2026-05-19 13:58:33 +02:00
Robert Schmidt
fac4760bc8 procedures 2026-05-19 13:58:33 +02:00
Robert Schmidt
22f5b3b3ba sidelink procedures
rename to psbch_pscch_pssch_processing()
introduce slsch_status_t
2026-05-19 13:58:33 +02:00
Robert Schmidt
2fae82250e is this needed? 2026-05-19 13:58:33 +02:00
Robert Schmidt
ae3a2115cd SLSCH 2026-05-19 13:57:23 +02:00
Robert Schmidt
3926a060fa defs 2026-05-19 13:55:48 +02:00
Robert Schmidt
e73133f764 CSI 2026-05-19 13:55:48 +02:00
Robert Schmidt
aca3824fde PSCCH 2026-05-19 13:55:48 +02:00
Robert Schmidt
a44481ae85 PSFCH 2026-05-19 13:55:48 +02:00
Robert Schmidt
80fc10423b SCI 2026-05-19 13:55:47 +02:00
Robert Schmidt
88ff8e2a2f TODO: nr_pusch_dmrs_delta() not defined 2026-05-19 13:52:30 +02:00
Robert Schmidt
b0c6e23dd4 channel estimation sidelink 2026-05-19 13:52:21 +02:00
Robert Schmidt
1f3fe83c96 sl_measurements 2026-05-19 13:50:46 +02:00
Robert Schmidt
c55a4bb0c5 nr_get_G_SL 2026-05-19 13:50:46 +02:00
Robert Schmidt
046ec8d839 colors 2026-05-19 13:50:46 +02:00
Robert Schmidt
56a97fdc20 PDCCH/DCI
nr_pdcch_unscrambling() will be used in sidelink code later.
2026-05-19 13:50:44 +02:00
Robert Schmidt
d503df5dc4 delay table init 2026-05-19 12:02:08 +02:00
Robert Schmidt
5b277d1eec NR_UE_PUCCH0_LUT_t: pucch0_lut 2026-05-19 12:02:08 +02:00
Robert Schmidt
81b433fc1c PUSCH 2026-05-19 12:02:07 +02:00
Robert Schmidt
4fbdf73f08 sl_harq_processes init 2026-05-19 11:56:34 +02:00
Robert Schmidt
b39d9dd0ef gold 2026-05-19 11:56:34 +02:00
Robert Schmidt
45bccc3d73 Polar 2026-05-19 11:56:34 +02:00
Robert Schmidt
5e7f4e38d0 FAPI defines 2026-05-19 11:56:34 +02:00
Robert Schmidt
d5061cf12d Move common 2026-05-19 08:10:43 +02:00
46 changed files with 5168 additions and 317 deletions

View File

@@ -1019,16 +1019,22 @@ 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_pscch_tx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psfch_tx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/csi_rx.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/csi_sl_rx.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
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_slsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_slsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_slsch_ue.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_prach.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_sci.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pucch_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/csi_rx.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
@@ -1038,6 +1044,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_sl_channel_estimation.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c
@@ -1924,6 +1931,8 @@ target_link_libraries(nr-uesoftmodem PRIVATE
time_management softmodem_common
-Wl,--end-group dl)
# TODO for sidelink
target_link_libraries(nr-uesoftmodem PRIVATE PHY_NR)
target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_meas)
target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB})
target_link_libraries(nr-uesoftmodem PRIVATE nr_nas lib_uicc usim_lib SECURITY)

View File

@@ -1457,3 +1457,237 @@ void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id,
*amf_pointer = (fiveg_s_tmsi >> 32) & 0x3F;
*m_tmsi = fiveg_s_tmsi;
}
// the following tables contain 10 times the value reported in 214 (in line with SCF specification and to avoid fractional values)
//Table 5.1.3.1-1 of 38.214
static const uint16_t Table_51311[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260},
{2, 6020}, {2, 6790}, {4, 3400}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160},
{4, 6580}, {6, 4380}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7190},
{6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480}, {2, 0}, {4, 0}, {6, 0}};
// Table 5.1.3.1-2 of 38.214
static const uint16_t Table_51312[32][2] = {{2, 1200}, {2, 1930}, {2, 3080}, {2, 4490}, {2, 6020}, {4, 3780}, {4, 4340},
{4, 4900}, {4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670},
{6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {8, 6825},
{8, 7110}, {8, 7540}, {8, 7970}, {8, 8410}, {8, 8850}, {8, 9165}, {8, 9480},
{2, 0}, {4, 0}, {6, 0}, {8, 0}};
//Table 5.1.3.1-3 of 38.214
static const uint16_t Table_51313[32][2] = {{2, 300}, {2, 400}, {2, 500}, {2, 640}, {2, 780}, {2, 990}, {2, 1200}, {2, 1570},
{2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260}, {2, 6020}, {4, 3400},
{4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160}, {6, 4380}, {6, 4660}, {6, 5170},
{6, 5670}, {6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {2, 0}, {4, 0}, {6, 0}};
static const uint16_t Table_61411[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490},
{2, 5260}, {2, 6020}, {2, 6790}, {4, 3400}, {4, 3780}, {4, 4340}, {4, 4900},
{4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160},
{6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480},
{2, 0}, {2, 0}, {4, 0}, {6, 0}};
static const uint16_t Table_61412[32][2] = {{2, 300}, {2, 400}, {2, 500}, {2, 640}, {2, 780}, {2, 990}, {2, 1200},
{2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260},
{2, 6020}, {2, 6790}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160},
{4, 6580}, {4, 6990}, {4, 7720}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7720},
{2, 0}, {2, 0}, {4, 0}, {6, 0}};
uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][0]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][0]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][0]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx);
return 0;
}
}
uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][1]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][1]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][1]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx);
return 0;
}
}
uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][0]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][0]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][0]);
break;
case 3:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61411[Imcs][0]);
break;
case 4:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61412[Imcs][0]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx);
return 0;
}
}
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][1]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][1]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][1]);
break;
case 3:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61411[Imcs][1]);
break;
case 4:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61412[Imcs][1]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx);
return 0;
}
}
#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 target_coderate) {
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 = 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);
}
int get_nRECSI_RS(uint8_t freq_density,
uint16_t nr_of_rbs,
int nb_antennas_tx) {
AssertFatal(freq_density > 0, "freq_density must be greater than 1\n");
uint8_t nr_rbs_w_csi_rs = nr_of_rbs / freq_density;
// Actually, kprime + 1 sub-carriers are used by csi-rs. kprime can be 0 or 1 but nb_antennas_tx can be greater than 2.
uint8_t subcarriers_used = nb_antennas_tx > 2 ? 2 : nb_antennas_tx;
return nr_rbs_w_csi_rs * subcarriers_used;
}

View File

@@ -369,6 +369,28 @@ uint64_t nr_build_full_5g_s_tmsi(const uint64_t part1, const uint16_t part2);
/** @brief Deconstruct full 5G-S-TMSI into its components */
void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id, uint8_t *amf_pointer, uint32_t *m_tmsi);
/** \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);
/** \brief Computes Q based on I_MCS PDSCH and table_idx for uplink. Implements MCS Tables from 38.214. */
uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx);
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx);
/** @brief Helper for SL CSI in UE */
int get_nRECSI_RS(uint8_t freq_density, uint16_t nr_of_rbs, int nb_antennas_tx);
/** @brief Helper for SL SCI2 in UE */
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 target_coderate);
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b)))

View File

@@ -117,12 +117,6 @@ unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
}
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KBLU "\x1B[34m"
#define RESET "\033[0m"
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
int ru_id;

View File

@@ -554,7 +554,7 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
}
sampleShift = pbch_processing(UE, proc, phy_data);
pdcch_processing(UE, proc, phy_data);
pdcch_processing(UE, proc, phy_data,0);
if (phy_data->dlsch[0].active
&& (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) {
// indicate to tx thread to wait for DLSCH decoding
@@ -590,7 +590,7 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
AssertFatal((phy_data->sl_rx_action >= SL_NR_CONFIG_TYPE_RX_PSBCH &&
phy_data->sl_rx_action < SL_NR_CONFIG_TYPE_RX_MAXIMUM), "Incorrect SL RX Action Scheduled\n");
sampleShift = psbch_pscch_processing(UE, proc, phy_data);
sampleShift = psbch_pscch_pssch_processing(UE, proc, phy_data);
}
}
} else

View File

@@ -83,6 +83,19 @@ uint64_t sidelink_frequency[MAX_NUM_CCs][4];
// UE and OAI config variables
double cpuf;
// TODO sidelink: avoid linker errors for including gNB
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { abort(); return NULL; }
int get_nr_prach_duration(uint8_t prach_format) { abort(); return 0; }
int beam_index_allocation(bool das,
int fapi_beam_index,
NR_gNB_COMMON *common_vars,
int slot,
int symbols_per_slot,
int bitmap_symbols)
{
abort(); return 0;
}
int create_tasks_nrue(uint32_t ue_nb) {
LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb);
itti_wait_ready(1);

View File

@@ -321,6 +321,13 @@ extern char *parallel_config;
extern char *worker_config;
extern double cpuf;
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KBLU "\x1B[34m"
#define RESET "\033[0m"
#ifdef __cplusplus
}
#endif

View File

@@ -9,7 +9,8 @@
#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
@@ -24,7 +25,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
@@ -33,7 +35,8 @@ typedef enum sl_nr_rx_config_type_enum {
SL_NR_CONFIG_TYPE_RX_PSCCH,
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_PSFCH,
SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_CSI_RS,
SL_NR_CONFIG_TYPE_RX_MAXIMUM
} sl_nr_rx_config_type_enum_t;
@@ -41,7 +44,8 @@ typedef enum sl_nr_rx_config_type_enum {
typedef enum sl_nr_tx_config_type_enum {
SL_NR_CONFIG_TYPE_TX_PSBCH = SL_NR_CONFIG_TYPE_RX_MAXIMUM + 1,
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH,
SL_NR_CONFIG_TYPE_TX_PSFCH,
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH,
SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS,
SL_NR_CONFIG_TYPE_TX_MAXIMUM
} sl_nr_tx_config_type_enum_t;
@@ -73,7 +77,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
@@ -84,8 +88,14 @@ typedef struct sl_nr_ssb_pdu {
bool decode_status;
} sl_nr_ssb_pdu_t;
//Use the same structure of pdsch pdu for slsch pdu
typedef fapi_nr_pdsch_pdu_t sl_nr_slsch_pdu_t;
typedef struct sl_nr_slsch_pdu {
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;
} sl_nr_slsch_pdu_t;
typedef struct {
sl_rx_pdu_type_enum_t pdu_type;
@@ -195,6 +205,40 @@ 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
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_tti_csi_rs_pdu {
uint8_t subcarrier_spacing;
uint8_t cyclic_prefix;
uint16_t start_rb;
uint16_t nr_of_rbs;
uint8_t csi_type;
uint8_t row;
uint16_t freq_domain;
uint8_t symb_l0;
uint8_t symb_l1;
uint8_t cdm_type;
uint8_t freq_density;
uint16_t scramb_id;
uint8_t power_control_offset;
uint8_t power_control_offset_ss;
uint8_t measurement_bitmap;
} sl_nr_tti_csi_rs_pdu_t;
typedef struct {
sl_nr_rx_config_type_enum_t pdu_type; // indicates the type of RX config request
union {
@@ -202,6 +246,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
@@ -247,7 +294,8 @@ typedef struct sl_nr_tx_config_pscch_pssch_pdu {
//Guard symbol + AGC symbol are also excluded
//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
@@ -270,14 +318,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;
//....TBD.. any additional parameters
// PSFCH related parameters
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list;
uint16_t num_psfch_pdus;
// 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.
@@ -386,8 +441,26 @@ typedef struct {
fapi_nr_tdd_table_t tdd_table;
//only 1 SL-BWP can be configured in REL16, REL17
sl_nr_bwp_config_t sl_bwp_config;
// scrambling ID used for PSSCH SCI transmissions
uint32_t sl_DMRS_ScrambleId;
} sl_nr_phy_config_request_t;
/* Dependencies */
typedef enum NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR {
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_NOTHING, /* No components present */
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots4,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots5,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots8,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots10,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots16,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots20,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots32,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots40,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots64,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots80,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots160,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots320,
NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR_slots640
} NR_UE_SL_CSI_ResourcePeriodicityAndOffset_PR;
#endif

View File

@@ -306,6 +306,7 @@ int main(int argc, char *argv[])
if (decoder_int16 == 1) {
decoderState = polar_decoder_int16(channelOutput_int16,
(uint64_t *)estimatedOutput,
(uint16_t *)NULL,
0,
polarMessageType,
testLength,

View File

@@ -10,6 +10,8 @@
#define __NR_POLAR_DCI_DEFS__H__
#define NR_POLAR_DCI_MESSAGE_TYPE 1 // int8_t
#define NR_POLAR_SCI_MESSAGE_TYPE (NR_POLAR_PSBCH_MESSAGE_TYPE + 1) //int8_t
#define NR_POLAR_SCI2_MESSAGE_TYPE (NR_POLAR_SCI_MESSAGE_TYPE + 1) //int8_t
#define NR_POLAR_DCI_CRC_PARITY_BITS 24
#define NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS 3

View File

@@ -643,6 +643,7 @@ static inline void nr_polar_info_extraction_from_u(uint64_t *Cprime,
uint32_t polar_decoder_int16(int16_t *input,
uint64_t *out,
uint16_t *nid,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,
@@ -817,6 +818,7 @@ uint32_t polar_decoder_int16(int16_t *input,
out[0] = Ar;
if (nid) *nid=crc&65535;
polarReturn(polarParams);
return crc ^ rxcrc;
}

View File

@@ -129,6 +129,7 @@ int8_t polar_decoder(double *input,
uint32_t polar_decoder_int16(int16_t *input,
uint64_t *out,
uint16_t *nid,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,

View File

@@ -9,6 +9,7 @@
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_REFSIG/pss_nr.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include "PHY/NR_REFSIG/sl_refsig_defs.h"
@@ -368,8 +369,10 @@ void term_nr_ue_transport(PHY_VARS_NR_UE *ue)
{
const int N_RB_DL = ue->frame_parms.N_RB_DL;
const int N_RB_UL = ue->frame_parms.N_RB_UL;
const int N_RB_SL = ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_UL;
free_nr_ue_dl_harq(ue->dl_harq_processes, NR_MAX_HARQ_PROCESSES, N_RB_DL);
free_nr_ue_ul_harq(ue->ul_harq_processes, NR_MAX_HARQ_PROCESSES, N_RB_UL, ue->frame_parms.nb_antennas_tx);
free_nr_ue_ul_harq(ue->sl_harq_processes, NR_MAX_HARQ_PROCESSES, N_RB_SL, ue->SL_UE_PHY_PARAMS.sl_frame_params.nb_antennas_tx);
}
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSES], int number_of_processes, int num_rb)
@@ -448,6 +451,7 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue)
{
nr_init_dl_harq_processes(ue->dl_harq_processes, NR_MAX_HARQ_PROCESSES, ue->frame_parms.N_RB_DL);
nr_init_ul_harq_processes(ue->ul_harq_processes, NR_MAX_HARQ_PROCESSES, ue->frame_parms.N_RB_UL, ue->frame_parms.nb_antennas_tx);
nr_init_ul_harq_processes(ue->sl_harq_processes, NR_MAX_HARQ_PROCESSES, ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_UL, ue->frame_parms.nb_antennas_tx);
}
void clean_UE_harq(PHY_VARS_NR_UE *UE)
@@ -531,4 +535,66 @@ void sl_ue_phy_init(PHY_VARS_NR_UE *UE)
// Generate PSS time domain samples used for correlation during SLSS reception.
sl_generate_pss_ifft_samples(&UE->SL_UE_PHY_PARAMS, &UE->SL_UE_PHY_PARAMS.init_params);
// PSCCH DMRS gold sequences (TX)
UE->nr_gold_pscch_dmrs = (uint32_t ***)malloc16(sl_fp->slots_per_frame * sizeof(uint32_t **));
uint32_t ***pscch_dmrs = UE->nr_gold_pscch_dmrs;
AssertFatal(pscch_dmrs != NULL, "NR SL UE init: pscch_dmrs malloc failed\n");
int pscch_dmrs_init_length = (((sl_fp->N_RB_UL << 1) * 3) >> 5) + 1;
for (int slot = 0; slot < sl_fp->slots_per_frame; slot++) {
pscch_dmrs[slot] = (uint32_t **)malloc16(sl_fp->symbols_per_slot * sizeof(uint32_t *));
AssertFatal(pscch_dmrs[slot] != NULL, "NR SL UE init: pscch_dmrs for slot %d - malloc failed\n", slot);
for (int symb = 0; symb < sl_fp->symbols_per_slot; symb++) {
pscch_dmrs[slot][symb] = (uint32_t *)malloc16(pscch_dmrs_init_length * sizeof(uint32_t));
AssertFatal(pscch_dmrs[slot][symb] != NULL, "NR SL UE init: pscch_dmrs slot %d symb %d - malloc failed\n", slot, symb);
}
}
nr_init_pscch_dmrs(sl_fp,UE->nr_gold_pscch_dmrs, UE->SL_UE_PHY_PARAMS.sl_config.sl_DMRS_ScrambleId);
// PSCCH DMRS gold sequences (RX)
UE->nr_gold_pscch = (uint32_t ***)malloc16(sl_fp->slots_per_frame * sizeof(uint32_t **));
uint32_t ***pscch_dmrs_rx = UE->nr_gold_pscch;
AssertFatal(pscch_dmrs_rx != NULL, "NR SL UE init: pscch_dmrs_rx malloc failed\n");
for (int slot = 0; slot < sl_fp->slots_per_frame; slot++) {
pscch_dmrs_rx[slot] = (uint32_t **)malloc16(sl_fp->symbols_per_slot * sizeof(uint32_t *));
AssertFatal(pscch_dmrs_rx[slot] != NULL, "NR SL UE init: pscch_dmrs_rx for slot %d - malloc failed\n", slot);
for (int symb = 0; symb < sl_fp->symbols_per_slot; symb++) {
pscch_dmrs_rx[slot][symb] = (uint32_t *)malloc16(pscch_dmrs_init_length * sizeof(uint32_t));
AssertFatal(pscch_dmrs_rx[slot][symb] != NULL, "NR SL UE init: pscch_dmrs_rx slot %d symb %d - malloc failed\n", slot, symb);
}
}
nr_init_pscch_dmrs(sl_fp, pscch_dmrs_rx, UE->SL_UE_PHY_PARAMS.sl_config.sl_DMRS_ScrambleId);
// SLSCH allocation
UE->max_nb_slsch = NR_SLSCH_RX_MAX;
UE->slsch = (NR_gNB_ULSCH_t *)malloc16(UE->max_nb_slsch * sizeof(NR_gNB_ULSCH_t));
for (int i = 0; i < UE->max_nb_slsch; i++) {
LOG_I(PHY, "Allocating Transport Channel Buffers for SLSCH %d/%d\n", i, UE->max_nb_slsch);
UE->slsch[i] = new_gNB_ulsch(UE->max_ldpc_iterations, sl_fp->N_RB_UL);
}
// PSSCH vars allocation
int Prx = sl_fp->nb_antennas_rx;
int N_RB_UL = sl_fp->N_RB_UL;
int n_buf = 2 * Prx;
int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB;
int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch & 7);
UE->pssch_thres = 10;
UE->pssch_vars = (NR_gNB_PUSCH *)malloc16_clear(UE->max_nb_slsch * sizeof(NR_gNB_PUSCH));
for (int SLSCH_id = 0; SLSCH_id < NR_SLSCH_RX_MAX; SLSCH_id++) {
NR_gNB_PUSCH *pssch = &UE->pssch_vars[SLSCH_id];
pssch->ul_ch_estimates = malloc16(n_buf * sizeof(int32_t *));
pssch->rxdataF_comp = malloc16(n_buf * sizeof(int32_t *));
for (int i = 0; i < n_buf; i++) {
pssch->ul_ch_estimates[i] = malloc16_clear(sizeof(int32_t) * sl_fp->ofdm_symbol_size * sl_fp->symbols_per_slot);
pssch->rxdataF_comp[i] = malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * sl_fp->symbols_per_slot);
}
pssch->llr = malloc16_clear((8 * ((3 * 8 * 6144) + 12)) * sizeof(int16_t));
pssch->ul_valid_re_per_slot = malloc16_clear(sizeof(int16_t) * sl_fp->symbols_per_slot);
}
// UE->sl_measurements = calloc(1, sizeof(struct PHY_MEASUREMENTS_gNB_s));
init_delay_table(sl_fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, sl_fp->delay_table);
}

View File

@@ -2,8 +2,48 @@
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include "sl_refsig_defs.h"
#include "openair1/PHY/gold.h"
#include "sl_refsig_defs.h"
#include "openair1/PHY/LTE_TRANSPORT/transport_proto.h"
#include "common/utils/LOG/log.h"
void nr_init_pscch_dmrs(NR_DL_FRAME_PARMS *fp, uint32_t ***nr_gold, uint16_t nid)
{
unsigned int n = 0, x1 = 0, x2 = 0, x2tmp0 = 0;
uint8_t reset;
int pdcch_dmrs_init_length = (((fp->N_RB_UL << 1) * 3) >> 5) + 1;
for (int ns = 0; ns < fp->slots_per_frame; ns++) {
for (int l = 0; l < fp->symbols_per_slot; l++) {
reset = 1;
x2tmp0 = ((fp->symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
x2tmp0 <<= 17;
x2 = (x2tmp0 + (nid << 1)) % (1U << 31); //cinit
for (n=0; n<pdcch_dmrs_init_length; n++) {
nr_gold[ns][l][n] = gold_generic(&x1, &x2, reset);
reset = 0;
}
}
}
}
void nr_init_pssch_dmrs_oneshot(NR_DL_FRAME_PARMS *fp,
uint16_t N_id,
uint32_t *pssch_dmrs,
int slot,
int symb)
{
uint32_t x1 = 0, x2 = 0, n = 0;
int pusch_dmrs_init_length = ((fp->N_RB_UL * 12) >> 5) + 1;
int reset = 1;
x2 = ((1U << 17) * (fp->symbols_per_slot*slot + symb + 1) * ((N_id << 1) + 1) + (N_id << 1));
LOG_D(PHY,"PSSCH DMRS slot %d, symb %d x2 %x\n", slot, symb, x2);
for (n=0; n<pusch_dmrs_init_length; n++) {
pssch_dmrs[n] = gold_generic(&x1, &x2, reset);
reset = 0;
}
}
void sl_init_psbch_dmrs_gold_sequences(PHY_VARS_NR_UE *UE)
{

View File

@@ -7,8 +7,44 @@
#include "PHY/defs_nr_UE.h"
typedef struct port_freq_indices {
uint8_t p;
uint16_t k;
} port_freq_indices_t;
typedef struct csi_rs_params {
uint8_t size;
uint8_t j[16];
uint8_t k_n[6];
uint8_t kprime;
uint8_t lprime;
uint8_t ports;
uint8_t koverline[16];
uint8_t loverline[16];
double rho;
double alpha;
uint8_t gs;
} csi_rs_params_t;
void sl_generate_pss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint8_t n_sl_id2, uint16_t scaling);
void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_INIT_PARAMS_t *sl_init_params);
void sl_generate_sss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint16_t slss_id, uint16_t scaling);
void sl_init_psbch_dmrs_gold_sequences(PHY_VARS_NR_UE *UE);
void nr_init_pscch_dmrs(NR_DL_FRAME_PARMS *fp, uint32_t ***nr_gold, uint16_t nid);
void nr_init_pssch_dmrs_oneshot(NR_DL_FRAME_PARMS *fp,
uint16_t N_id,
uint32_t *pssch_dmrs,
int slot,
int symb);
void get_csi_rs_freq_ind_sl(const NR_DL_FRAME_PARMS* frame_parms,
uint16_t n,
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* csi_params,
csi_rs_params_t* table_params,
port_freq_indices_t* port_freq_indices);
void get_csi_rs_params_from_table(const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params,
csi_rs_params_t* table_params);
#endif

View File

@@ -19,6 +19,18 @@ nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t leng
return (G);
}
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) {
uint32_t G_SL, slsch_re;
slsch_re = ((NR_NB_SC_PER_RB*nb_symb_sch) - (nb_re_dmrs*length_dmrs)) * nb_rb;
if (sci1_dmrs_overlap > 0) slsch_re += (nb_re_dmrs * sci1_rb); // return the dmrs that are not transmitted due to SCI1
slsch_re -= sci1_re; // REs taken by SCI1
slsch_re -= sci2_re; // REs taken by SCI2
slsch_re -= csi_rs_re; // REs taken by CSI_RS
G_SL = slsch_re * Qm * Nl;
return(G_SL);
}
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r)
{
uint32_t E;

View File

@@ -35,6 +35,8 @@ uint32_t nr_get_G(uint16_t nb_rb,
uint8_t Qm,
uint8_t Nl);
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);
uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r);
void compute_nr_prach_seq(uint8_t short_sequence, uint8_t num_sequences, uint8_t rootSequenceIndex, c16_t X_u[64][839]);

View File

@@ -1496,7 +1496,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// run polar decoder on llrs
decoderState =
polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
polar_decoder_int16((int16_t *)llrs, decodedPayload, (uint16_t*)NULL, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
// Decoder reversal
decodedPayload[0] = reverse_bits(decodedPayload[0], nb_bit);

View File

@@ -0,0 +1,331 @@
/*
* 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.0 (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
*/
#include <string.h>
#include "PHY/sse_intrin.h"
#include "PHY/defs_gNB.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/NR_REFSIG/sl_refsig_defs.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_UE_ESTIMATION/filt16a_32.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include "common/utils/nr/nr_common.h"
#include "executables/softmodem-common.h"
//#define DEBUG_CH
//#define DEBUG_PUSCH
#define NO_INTERP 1
#define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y)))
__attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *in1,
int *offset1,
const int step1,
c16_t *in2,
int *offset2,
const int step2,
const int modulo2,
const int N) {
int localOffset1=*offset1;
int localOffset2=*offset2;
c32_t cumul={0};
for (int i=0; i<N; i++) {
cumul=c32x16maddShift(in1[localOffset1], in2[localOffset2], cumul, 15);
localOffset1+=step1;
localOffset2= (localOffset2 + step2) % modulo2;
}
*offset1=localOffset1;
*offset2=localOffset2;
return c16x32div(cumul, N);
}
int nr_pssch_channel_estimation(PHY_VARS_NR_UE *ue,
int rxFSz,
c16_t rxdataF[][rxFSz],
unsigned char Ns,
unsigned short p,
unsigned char symbol,
int ul_id,
unsigned short bwp_start_subcarrier,
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
int *max_ch,
uint32_t *nvar) {
c16_t pilot[3280] __attribute__((aligned(32)));
const int chest_freq = ue->chest_freq;
#ifdef DEBUG_CH
FILE *debug_ch_est;
debug_ch_est = fopen("debug_ch_est.txt","w");
#endif
NR_gNB_PUSCH *pusch_vars = &ue->pssch_vars[ul_id];
c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates;
const int symbolSize = ue->SL_UE_PHY_PARAMS.sl_frame_params.ofdm_symbol_size;
const int soffset = 0;
const int nushift = (p>>1)&1;
int ch_offset = symbolSize*symbol;
const int symbol_offset = symbolSize*symbol;
const int k0 = bwp_start_subcarrier;
const int nb_rb_pusch = pssch_pdu->subchannel_size*pssch_pdu->l_subch;
LOG_D(PHY, "In %s: ch_offset %d, soffset %d, symbol_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n",
__FUNCTION__,
ch_offset, soffset,
symbol_offset,
symbolSize,
Ns,
k0,
symbol);
//------------------generate DMRS------------------//
// compute gold sequence based on Nid from SCI1A
int nb_re = ue->SL_UE_PHY_PARAMS.sl_frame_params.N_RB_UL*12;
uint32_t pssch_dmrs[(nb_re>>5)+1];
nr_init_pssch_dmrs_oneshot(&ue->SL_UE_PHY_PARAMS.sl_frame_params,pssch_pdu->Nid,pssch_dmrs,Ns,symbol);
float beta_dmrs_pusch = get_beta_dmrs(pssch_pdu->num_layers, pusch_dmrs_type1);
int16_t dmrs_scaling = (1 / beta_dmrs_pusch) * (1 << 14);
nr_pusch_dmrs_rx(NORMAL, pssch_dmrs, (c16_t *)pilot, (1000+p), 0, nb_rb_pusch,
(pssch_pdu->startrb)*NR_NB_SC_PER_RB, 0, dmrs_scaling);
//------------------------------------------------//
#ifdef DEBUG_PUSCH
for (int i = 0; i < (6 * nb_rb_pusch); i++) {
LOG_I(PHY, "In %s: %d + j*(%d)\n", __FUNCTION__, pilot[i].r,pilot[i].i);
}
#endif
int nest_count = 0;
uint64_t noise_amp2 = 0;
c16_t ul_ls_est[symbolSize] __attribute__((aligned(32)));
memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize);
delay_t delay;
memset(&delay, 0, sizeof(delay));
NR_DL_FRAME_PARMS *fp = &ue->SL_UE_PHY_PARAMS.sl_frame_params;
int nrx = fp->nb_antennas_rx;
c16_t ch_estimates_time[symbolSize] __attribute__((aligned(32)));
for (int aarx=0; aarx<nrx; aarx++) {
c16_t *rxdataF2 = (c16_t *)&rxdataF[aarx][symbol_offset];
c16_t *ul_ch = &ul_ch_estimates[p*nrx+aarx][ch_offset];
memset(ul_ch,0,sizeof(*ul_ch)*symbolSize);
#ifdef DEBUG_PUSCH
LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift);
LOG_I(PHY, "In %s ch est pilot, N_RB_UL %d\n", __FUNCTION__, fp->N_RB_UL);
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, fp->first_carrier_offset, nb_rb_pusch);
LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
#endif
if (chest_freq == 0) {
c16_t *pil = pilot;
int re_offset = k0;
LOG_D(PHY,"PSSCH estimation DMRS type 1, Freq-domain interpolation");
// For configuration type 1: k = 4*n + 2*k' + delta,
// where k' is 0 or 1, and delta is in Table 6.4.1.1.3-1 from TS 38.211
int pilot_cnt = 0;
int delta = 0; // nr_pusch_dmrs_delta(pusch_dmrs_type1, p);
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
// LS estimation
c32_t ch = {0};
for (int k_line = 0; k_line <= 1; k_line++) {
re_offset = (k0 + (n << 2) + (k_line << 1) + delta) % symbolSize;
ch = c32x16maddShift(*pil, rxdataF2[soffset + re_offset], ch, 16);
pil++;
}
c16_t ch16 = {.r = (int16_t)ch.r, .i = (int16_t)ch.i};
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i)));
for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) {
ul_ls_est[k] = ch16;
}
pilot_cnt += 2;
}
freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t*)ch_estimates_time);
nr_est_delay(symbolSize, ul_ls_est, ch_estimates_time, &delay);
int pusch_delay = delay.est_delay;
int delay_idx = get_delay_idx(pusch_delay, MAX_DELAY_COMP);
c16_t *ul_delay_table = fp->delay_table[delay_idx];
#ifdef DEBUG_PUSCH
LOG_I(NR_PHY,"Estimated delay = %i\n", pusch_delay >> 1);
#endif
pilot_cnt = 0;
for (int n = 0; n < 3*nb_rb_pusch; n++) {
// Channel interpolation
for (int k_line = 0; k_line <= 1; k_line++) {
// Apply delay
int k = pilot_cnt << 1;
c16_t ch16 = c16mulShift(ul_ls_est[k], ul_delay_table[k], 8);
#ifdef DEBUG_PUSCH
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
c16_t *rxF = &rxdataF2[soffset + re_offset];
LOG_I(NR_PHY,"pilot %4d: ul_delay` -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
pilot_cnt, ul_delay_table[k].r, ul_delay_table[k].i, rxF->r, rxF->i, ch16.r, ch16.i);
#endif
if (pilot_cnt == 0) {
c16multaddVectRealComplex(filt16_ul_p0, &ch16, ul_ch, 16);
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
c16multaddVectRealComplex(filt16_ul_p1p2, &ch16, ul_ch, 16);
} else if (pilot_cnt == (6 * nb_rb_pusch - 1)) {
c16multaddVectRealComplex(filt16_ul_last, &ch16, ul_ch, 16);
} else {
c16multaddVectRealComplex(filt16_ul_middle, &ch16, ul_ch, 16);
if (pilot_cnt % 2 == 0) {
ul_ch += 4;
}
}
pilot_cnt++;
}
}
// Revert delay
pilot_cnt = 0;
ul_ch = &ul_ch_estimates[p * nrx + aarx][ch_offset];
int inv_delay_idx = get_delay_idx(-pusch_delay, MAX_DELAY_COMP);
c16_t *ul_inv_delay_table = fp->delay_table[inv_delay_idx];
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
for (int k_line = 0; k_line <= 1; k_line++) {
int k = pilot_cnt << 1;
ul_ch[k] = c16mulShift(ul_ch[k], ul_inv_delay_table[k], 8);
ul_ch[k + 1] = c16mulShift(ul_ch[k + 1], ul_inv_delay_table[k + 1], 8);
noise_amp2 += c16amp2(c16sub(ul_ls_est[k], ul_ch[k]));
noise_amp2 += c16amp2(c16sub(ul_ls_est[k + 1], ul_ch[k + 1]));
#ifdef DEBUG_PUSCH
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
c16_t *rxF = &rxdataF2[soffset + re_offset];
LOG_I(NR_PHY,"ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i);
#endif
pilot_cnt++;
nest_count += 2;
}
}
} else { // no frequency-domain linear interpolation: average LS channel estimates of 6 DMRS REs per PRB
LOG_D(PHY,"PSSCH estimation DMRS type 1, no Freq-domain interpolation\n");
c16_t *rxF = &rxdataF2[soffset + nushift];
int pil_offset = 0;
int re_offset = k0;
c16_t ch;
// First PRB
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
#if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++)
*ul_ch=ch;
#else
c16multaddVectRealComplex(filt8_avlip0, &ch, ul_ch, 8);
ul_ch += 8;
c16multaddVectRealComplex(filt8_avlip1, &ch, ul_ch, 8);
ul_ch += 8;
c16multaddVectRealComplex(filt8_avlip2, &ch, ul_ch, 8);
ul_ch -= 12;
#endif
for (int pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) {
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i)));
#if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++)
*ul_ch=ch;
#else
ul_ch[3].r += (ch.r * 1365)>>15; // 1/12*16384
ul_ch[3].i += (ch.i * 1365)>>15; // 1/12*16384
ul_ch += 4;
c16multaddVectRealComplex(filt8_avlip3, &ch, ul_ch, 8);
ul_ch += 8;
c16multaddVectRealComplex(filt8_avlip4, &ch, ul_ch, 8);
ul_ch += 8;
c16multaddVectRealComplex(filt8_avlip5, &ch, ul_ch, 8);
ul_ch -= 8;
#endif
}
// Last PRB
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
#if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++)
*ul_ch=ch;
#else
ul_ch[3].r += (ch.r * 1365)>>15; // 1/12*16384
ul_ch[3].i += (ch.i * 1365)>>15; // 1/12*16384
ul_ch += 4;
c16multaddVectRealComplex(filt8_avlip3, &ch, ul_ch, 8);
ul_ch += 8;
c16multaddVectRealComplex(filt8_avlip6, &ch, ul_ch, 8);
#endif
}
#ifdef DEBUG_PUSCH
ul_ch = &ul_ch_estimates[p * ue->SL_UE_PHY_PARAMS.sl_frame_params.nb_antennas_rx + aarx][ch_offset];
for (int idxP = 0; idxP < ceil((float)nb_rb_pusch * 12 / 8); idxP++) {
for (int idxI = 0; idxI < 8; idxI++) {
LOG_I(NR_PHY,"%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i);
}
LOG_I(NR_PHY,"%d\n", idxP);
}
#endif
}
#ifdef DEBUG_CH
fclose(debug_ch_est);
#endif
if (nvar && nest_count > 0) {
*nvar = (uint32_t)(noise_amp2 / nest_count);
}
return 0;
}
uint32_t calc_power(const int16_t *x, const uint32_t size) {
int64_t sum_x = 0;
int64_t sum_x2 = 0;
for(int k = 0; k<size; k++) {
sum_x = sum_x + x[k];
sum_x2 = sum_x2 + x[k]*x[k];
}
return sum_x2/size - (sum_x/size)*(sum_x/size);
}

File diff suppressed because it is too large Load Diff

View File

@@ -60,7 +60,8 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
uint8_t number_of_candidates,
uint16_t *CCE,
uint8_t *L,
int llr_stride_per_symbol)
int llr_stride_per_symbol,
int pscch_processing)
{
/*
* This function will do demapping and deinterleaving from llr containing demodulated symbols
@@ -111,7 +112,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
int f_bundle_j_list[max_bundles];
// for each bundle
int c = 0, r = 0, f_bundle_j = 0;
for (int nb = 0; nb < max_bundles; nb++) {
for (int nb = 0; nb < max_bundles && pscch_processing == 0; nb++) {
if (coreset_interleaved == 0)
f_bundle_j = nb;
else {
@@ -127,7 +128,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
// Get cce_list indices by bundle index in ascending order
int f_bundle_j_list_ord[number_of_candidates][max_bundles];
for (int c_id = 0; c_id < number_of_candidates; c_id++) {
for (int c_id = 0; c_id < number_of_candidates && pscch_processing == 0; c_id++) {
int start_bund_cand = CCE[c_id] * num_bundles_per_cce;
int max_bund_per_cand = L[c_id] * num_bundles_per_cce;
int f_bundle_j_list_id = 0;
@@ -144,14 +145,19 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
int rb_count = 0;
for (int c_id = 0; c_id < number_of_candidates; c_id++) {
for (int symbol_idx = 0; symbol_idx < coreset_time_dur; symbol_idx++) {
for (int cce_count = 0; cce_count < L[c_id]; cce_count++) {
for (int k = 0; k < NR_NB_REG_PER_CCE / reg_bundle_size_L; k++) { // loop over REG bundles
int f = f_bundle_j_list_ord[c_id][k + NR_NB_REG_PER_CCE * cce_count / reg_bundle_size_L];
c16_t *in = llr + f * B_rb * RE_PER_RB_OUT_DMRS + symbol_idx * llr_stride_per_symbol;
// loop over the RBs of the bundle
memcpy(e_rx + RE_PER_RB_OUT_DMRS * rb_count, in, B_rb * RE_PER_RB_OUT_DMRS * sizeof(*e_rx));
rb_count += B_rb;
}
if (pscch_processing == 0) {
for (int cce_count = 0; cce_count < L[c_id]; cce_count++) {
for (int k = 0; k < NR_NB_REG_PER_CCE / reg_bundle_size_L; k++) { // loop over REG bundles
int f = f_bundle_j_list_ord[c_id][k + NR_NB_REG_PER_CCE * cce_count / reg_bundle_size_L];
c16_t *in = llr + f * B_rb * RE_PER_RB_OUT_DMRS + symbol_idx * llr_stride_per_symbol;
// loop over the RBs of the bundle
memcpy(e_rx + RE_PER_RB_OUT_DMRS * rb_count, in, B_rb * RE_PER_RB_OUT_DMRS * sizeof(*e_rx));
rb_count += B_rb;
}
}
} // pscch_processing == 0
else { //this will need to be changed a bit when we scan for multiple SCI
memcpy(e_rx,llr+(RE_PER_RB_OUT_DMRS*coreset_nbr_rb),coreset_nbr_rb*coreset_time_dur*RE_PER_RB_OUT_DMRS*sizeof(uint32_t));
}
}
}
@@ -309,7 +315,8 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue,
nr_phy_data_t *phy_data,
int llr_size_symbol,
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
c16_t llr[llr_size_symbol])
c16_t llr[llr_size_symbol],
int pscch_processing)
{
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
@@ -317,7 +324,11 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue,
int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16);
__attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size];
int n_rb, cset_start;
get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &cset_start);
if (pscch_processing == 0) get_coreset_rballoc(coreset->frequency_domain_resource,&n_rb,&cset_start);
else {
cset_start = coreset->frequency_domain_resource[0];
n_rb = coreset->frequency_domain_resource[1];
}
int rb_offset = cset_start + coreset->rb_offset;
unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id;
int dmrs_ref = 0;
@@ -351,7 +362,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue,
rxdataF_ext,
pdcch_dl_ch_estimates_ext,
fp,
coreset->frequency_domain_resource,
pscch_processing ? NULL : coreset->frequency_domain_resource,
coreset->rb_offset,
n_rb,
phy_pdcch_config->pdcch_config[ss_idx].BWPStart);
@@ -435,7 +446,8 @@ void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue,
int num_monitoring_occ,
int max_symb,
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol])
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol],
int pscch_processing)
{
const NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
@@ -459,17 +471,18 @@ void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue,
phy_data,
llr_size_symbol,
rxdataF,
&pdcch_llr[ss_idx][occ][rel_symb_monOcc * llr_size_symbol]);
&pdcch_llr[ss_idx][occ][rel_symb_monOcc * llr_size_symbol],
pscch_processing);
}
}
}
}
static void nr_pdcch_unscrambling(c16_t *e_rx,
uint16_t scrambling_RNTI,
uint32_t length,
uint16_t pdcch_DMRS_scrambling_id,
int16_t *z2)
void nr_pdcch_unscrambling(c16_t *e_rx,
uint16_t scrambling_RNTI,
uint32_t length,
uint16_t pdcch_DMRS_scrambling_id,
int16_t *z2)
{
uint32_t rnti = (uint32_t) scrambling_RNTI;
uint16_t n_id = pdcch_DMRS_scrambling_id;
@@ -487,12 +500,15 @@ static void nr_pdcch_unscrambling(c16_t *e_rx,
static void nr_dci_decoding_procedure(const UE_nr_rxtx_proc_t *proc,
c16_t *pdcch_e_rx,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
fapi_nr_dci_indication_t *dci_ind)
fapi_nr_dci_indication_t *dci_ind,
sl_nr_sci_indication_t *sci_ind,
int16_t *rsrp_dBm)
{
int e_rx_cand_idx = 0;
// if DCI for SIB we don't break after finding 1st DCI with that RNTI
// there might be SIB1 and otherSIB in the same slot with the same length
bool is_SI = rel15->rnti == SI_RNTI;
AssertFatal(dci_ind == NULL || sci_ind == NULL,"One of dci_ind or sci_ind needs to be NULL\n");
for (int j = 0; j < rel15->number_of_candidates; j++) {
int CCEind = rel15->CCE[j];
@@ -505,14 +521,15 @@ static void nr_dci_decoding_procedure(const UE_nr_rxtx_proc_t *proc,
// same rnti and size at a different aggregation level
int dci_length = rel15->dci_length_options[k];
int ind;
for (ind = 0; ind < dci_ind->number_of_dcis; ind++) {
if (!is_SI && rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) {
break;
if (dci_ind) {
for (ind = 0; ind < dci_ind->number_of_dcis; ind++) {
if (!is_SI && rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) {
break;
}
}
if (ind < dci_ind->number_of_dcis)
continue;
}
if (ind < dci_ind->number_of_dcis)
continue;
uint64_t dci_estimation[2] = {0};
LOG_D(NR_PHY_DCI,
"(%i.%i) Trying DCI candidate %d of %d number of candidates, CCE %d (%d), L %d, length %d, format %d\n",
@@ -529,39 +546,57 @@ static void nr_dci_decoding_procedure(const UE_nr_rxtx_proc_t *proc,
int16_t tmp_e[16 * 108];
nr_pdcch_unscrambling(&pdcch_e_rx[e_rx_cand_idx],
rel15->coreset.scrambling_rnti,
L * 108,
sci_ind ? L * 18 : L * 108,
rel15->coreset.pdcch_dmrs_scrambling_id,
tmp_e);
const uint32_t crc = polar_decoder_int16(tmp_e, dci_estimation, 1, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
uint16_t Nid;
const uint32_t crc = polar_decoder_int16(tmp_e, dci_estimation, &Nid, 1, sci_ind ? NR_POLAR_SCI_MESSAGE_TYPE : NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
rnti_t n_rnti = rel15->rnti;
if (crc == n_rnti) {
LOG_D(NR_PHY_DCI,
"(%i.%i) Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n",
"(%i.%i) Received %s indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n",
proc->frame_rx,
proc->nr_slot_rx,
sci_ind ? "SCI" : "DCI",
n_rnti,
rel15->dci_format_options[k],
CCEind,
dci_length,
*(unsigned long long *)dci_estimation);
AssertFatal(dci_ind->number_of_dcis < sizeofArray(dci_ind->dci_list), "Fix allocation\n");
fapi_nr_dci_indication_pdu_t *dci = dci_ind->dci_list + dci_ind->number_of_dcis;
*dci = (fapi_nr_dci_indication_pdu_t){
.rnti = n_rnti,
.n_CCE = CCEind,
.N_CCE = L,
.dci_format = rel15->dci_format_options[k],
.ss_type = rel15->ss_type_options[k],
.coreset_type = rel15->coreset.CoreSetType,
};
int n_rb, cset_start;
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start);
dci->cset_start = rel15->BWPStart + cset_start + rel15->coreset.rb_offset;
dci->payloadSize = dci_length;
memcpy(dci->payloadBits, dci_estimation, (dci_length + 7) / 8);
dci_ind->number_of_dcis++;
if (dci_ind) {
AssertFatal(dci_ind->number_of_dcis < sizeofArray(dci_ind->dci_list), "Fix allocation\n");
fapi_nr_dci_indication_pdu_t *dci = dci_ind->dci_list + dci_ind->number_of_dcis;
*dci = (fapi_nr_dci_indication_pdu_t){
.rnti = n_rnti,
.n_CCE = CCEind,
.N_CCE = L,
.dci_format = rel15->dci_format_options[k],
.ss_type = rel15->ss_type_options[k],
.coreset_type = rel15->coreset.CoreSetType,
};
int n_rb, cset_start;
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start);
dci->cset_start = rel15->BWPStart + cset_start + rel15->coreset.rb_offset;
dci->payloadSize = dci_length;
memcpy(dci->payloadBits, dci_estimation, (dci_length + 7) / 8);
dci_ind->number_of_dcis++;
}
else {
sl_nr_sci_indication_pdu_t *sci = &sci_ind->sci_pdu[sci_ind->number_of_SCIs];
*sci = (sl_nr_sci_indication_pdu_t){
.sci_format_type = SL_SCI_FORMAT_1A_ON_PSCCH,
.subch_index = 0,
.pscch_rsrp = *rsrp_dBm,
.sci_payloadlen = dci_length,
.Nid = Nid
};
memcpy(sci->sci_payloadBits,&dci_estimation,8);
sci_ind->number_of_SCIs++;
//ue->SL_UE_PHY_PARAMS.pscch.rx_ok++;
}
break; // If DCI is found, no need to check for remaining DCI lengths
} else {
LOG_D(NR_PHY_DCI,
@@ -583,12 +618,17 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
int max_monOcc,
PHY_VARS_NR_UE *ue,
nr_phy_data_t *phy_data,
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size])
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size],
int sci_indication)
{
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
nr_downlink_indication_t dl_indication;
nr_sidelink_indication_t sl_indication;
fapi_nr_dci_indication_t dci_ind = {.SFN = proc->frame_rx, .slot = proc->nr_slot_rx};
sl_nr_sci_indication_t sci_ind = {.sfn = proc->frame_rx, .slot = proc->nr_slot_rx};
for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) {
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[ss_idx];
@@ -596,8 +636,12 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, ue->frame_parms.symbols_per_slot, unused_start_symb);
const int llr_stride = llr_size / rel15->coreset.duration;
int n_rb, cset_start;
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start);
if (!sci_indication) {
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start);
} else {
n_rb = rel15->coreset.frequency_domain_resource[0];
cset_start = rel15->coreset.frequency_domain_resource[1];
}
for (int m = 0; m < num_monitoring_occ; m++) {
/// PDCCH/DCI e-sequence (input to rate matching).
c16_t pdcch_e_rx[NR_MAX_PDCCH_SIZE];
@@ -612,25 +656,34 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
rel15->number_of_candidates,
rel15->CCE,
rel15->L,
llr_stride);
llr_stride,
sci_indication);
nr_dci_decoding_procedure(proc, pdcch_e_rx, rel15, &dci_ind);
nr_dci_decoding_procedure(proc, pdcch_e_rx, rel15, sci_indication ? (fapi_nr_dci_indication_t*)NULL : &dci_ind, sci_indication ? &sci_ind : (sl_nr_sci_indication_t*)NULL,NULL);
}
}
for (int i = 0; i < dci_ind.number_of_dcis; i++) {
for (int i = 0; i < (sci_indication? sci_ind.number_of_SCIs : dci_ind.number_of_dcis); i++) {
LOG_D(PHY,
"Frame.slot: %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
"Frame.slot: %d.%d: DCI %i of %d total DCIs found --> %s %x : format %d\n",
proc->frame_rx,
proc->nr_slot_rx,
i + 1,
dci_ind.number_of_dcis,
dci_ind.dci_list[i].rnti,
dci_ind.dci_list[i].dci_format);
sci_indication ? sci_ind.number_of_SCIs : dci_ind.number_of_dcis,
sci_indication ? "Nid" : "RNTI",
sci_indication ? sci_ind.sci_pdu[i].Nid : dci_ind.dci_list[i].rnti,
sci_indication ? sci_ind.sci_pdu[i].sci_format_type : dci_ind.dci_list[i].dci_format);
}
/* Send to MAC */
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
ue->if_inst->dl_indication(&dl_indication);
if (sci_indication) {
nr_fill_sl_indication(&sl_indication, NULL, &sci_ind, proc, ue, phy_data);
ue->if_inst->sl_indication(&sl_indication);
}
else {
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
ue->if_inst->dl_indication(&dl_indication);
}
phy_pdcch_config->nb_search_space = 0;
}

View File

@@ -391,6 +391,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
uint64_t tmp=0;
const uint32_t decoderState = polar_decoder_int16(pbch_e_rx,
(uint64_t *)&tmp,
(uint16_t*)NULL,
0,
NR_POLAR_PBCH_MESSAGE_TYPE,
NR_POLAR_PBCH_PAYLOAD_BITS,

View File

@@ -188,6 +188,7 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue,
uint64_t tmp = 0;
decoderState = polar_decoder_int16(psbch_e_rx,
(uint64_t *)&tmp,
(uint16_t*)NULL,
0,
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,

View File

@@ -0,0 +1,68 @@
/*
* 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_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_sci((PHY_VARS_NR_UE *)ue,&pdcch_pdu_rel15,(c16_t *)txdataF,amp,(NR_DL_FRAME_PARMS*)frame_parms,nr_slot_tx));
}

View 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(txdataF, frame_parms, amp, nr_slot_tx, &pucch_pdu);
}

View File

@@ -0,0 +1,220 @@
/*
* 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_sci.c
* \brief Implements SCI encoding and PSCCH TX procedures for sidelink. Based on nr_dci.c.
* \author R. Knopp
* \date 2023
* \version 0.1
* \company Eurecom
*/
#include "PHY/defs_nr_UE.h"
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "common/utils/nr/nr_common.h"
//#define DEBUG_PSCCH_DMRS
//#define DEBUG_SCI
//#define DEBUG_CHANNEL_CODING
void nr_sci_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint32_t scrambling_RNTI, uint32_t *out,int sci2_flag)
{
int roundedSz = ((size + 31) / 32);
uint32_t *seq = gold_cache(sci2_flag > 0 ? (Nid << 15) + 1010 : (scrambling_RNTI << 15) + Nid, roundedSz);
for (int i = 0; i < roundedSz; i++)
out[i] = in[i] ^ seq[i];
}
uint32_t nr_generate_sci(PHY_VARS_NR_UE *ue,
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
c16_t *txdataF,
int16_t amp,
NR_DL_FRAME_PARMS *frame_parms,
int slot) {
uint16_t cset_start_sc;
uint8_t cset_start_symb, cset_nsymb;
int k,l,k_prime,dci_idx, dmrs_idx;
// compute rb_offset and n_prb based on frequency allocation
// for SCI: FreqDomainResource[0] = startRB, FreqDomainResource[1] = numRBs
int rb_offset = pdcch_pdu_rel15->FreqDomainResource[0];
int n_rb = pdcch_pdu_rel15->FreqDomainResource[1];
cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB;
c16_t mod_dmrs[pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols][(((n_rb+rb_offset+pdcch_pdu_rel15->BWPStart)*6+15)>>5)<<5] __attribute__((aligned(16)));
uint32_t sci_Nid = 0;
for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) {
/*The coreset is initialised
* in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0
* or the rb_offset for other coresets
* in time: by its first slot and its first symbol*/
const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d];
uint32_t **gold_pscch_dmrs = ue->nr_gold_pscch_dmrs[slot];
cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
dci_idx = 0;
LOG_D(NR_PHY, "pscch: rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart);
LOG_D(NR_PHY, "pscch: starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
// DMRS length is per OFDM symbol
uint32_t dmrs_length = (n_rb+pdcch_pdu_rel15->BWPStart)*6; //2(QPSK)*3(per RB)*6(REG per CCE)
uint32_t encoded_length = dci_pdu->AggregationLevel*18; //2(QPSK)*9(per RB) for SCI
if (dci_pdu->RNTI != 0xFFFF)
LOG_D(PHY, "SCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t SCI encoded length %d (precoder_granularity %d, reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d\n",
rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType,
dci_pdu->ScramblingId,dci_pdu->ScramblingRNTI,dci_pdu->PayloadSizeBits);
dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset
/// DMRS QPSK modulation
for (int symb=cset_start_symb; symb<cset_start_symb + pdcch_pdu_rel15->DurationSymbols; symb++) {
nr_modulation(gold_pscch_dmrs[symb], dmrs_length, DMRS_MOD_ORDER, (int16_t*)mod_dmrs[symb]); //Qm = 2 as DMRS is QPSK modulated
#ifdef DEBUG_PSCCH_DMRS
if(dci_pdu->RNTI!=0xFFFF) {
for (int i=0; i<dmrs_length>>1; i++)
printf("symb %d i %d %p gold seq 0x%08x mod_dmrs %d %d\n", symb, i,
&gold_pscch_dmrs[symb][i>>5],gold_pscch_dmrs[symb][i>>5], mod_dmrs[symb][i].r, mod_dmrs[symb][i].i);
}
#endif
}
/// SCI payload processing
// CRC attachment + Scrambling + Channel coding + Rate matching
uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
uint16_t n_RNTI = dci_pdu->RNTI;
uint16_t Nid = dci_pdu->ScramblingId;
uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI, 1,
NR_POLAR_SCI_MESSAGE_TYPE,
dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
#ifdef DEBUG_CHANNEL_CODING
//debug dump sci
printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu->AggregationLevel);
printf("SCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]);
printf("Encoded Payload (length:%u dwords):\n", encoded_length>>5);
for (int i=0; i<encoded_length>>5; i++)
printf("[%d]->0x%08x \t", i,encoder_output[i]);
printf("\n");
#endif
/// Scrambling
uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0};
nr_sci_scrambling(encoder_output, encoded_length, Nid, scrambling_RNTI, scrambled_output, 0);
#ifdef DEBUG_CHANNEL_CODING
printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\n \
[6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n",
scrambled_output[0], scrambled_output[1], scrambled_output[2], scrambled_output[3], scrambled_output[4],scrambled_output[5],
scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] );
#endif
/// QPSK modulation
c16_t mod_dci[encoded_length] __attribute__((aligned(16)));
nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, (int16_t*)mod_dci); //Qm = 2 as DMRS is QPSK modulated
#ifdef DEBUG_SCI
for (int i=0; i<encoded_length>>1; i++)
printf("i %d mod_dci %d %d\n", i, mod_dci[i].r, mod_dci[i].i );
#endif
/// Resource mapping
if (cset_start_sc >= frame_parms->ofdm_symbol_size)
cset_start_sc -= frame_parms->ofdm_symbol_size;
int num_regs = dci_pdu->AggregationLevel/pdcch_pdu_rel15->DurationSymbols;
/*Mapping the encoded SCI along with the DMRS */
for(int symbol_idx = 0; symbol_idx < pdcch_pdu_rel15->DurationSymbols; symbol_idx++) {
// allocating rbs per symbol
for (int reg_count = 0; reg_count < num_regs; reg_count++) {
if (reg_count == 0) k = cset_start_sc + pdcch_pdu_rel15->dci_pdu[d].CceIndex * NR_NB_SC_PER_RB;
if (k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
l = cset_start_symb + symbol_idx;
// dmrs index depends on reference point for k according to 38.211 7.4.1.3.2
if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
dmrs_idx = reg_count * 3;
else
dmrs_idx = (pdcch_pdu_rel15->dci_pdu[d].CceIndex + rb_offset + reg_count) * 3;
k_prime = 0;
for (int m = 0; m < NR_NB_SC_PER_RB; m++) {
if (m == (k_prime << 2) + 1) { // DMRS if not already mapped
txdataF[l * frame_parms->ofdm_symbol_size + k].r = (amp * mod_dmrs[l][dmrs_idx].r) >> 15;
txdataF[l * frame_parms->ofdm_symbol_size + k].i = (amp * mod_dmrs[l][dmrs_idx].i) >> 15;
#ifdef DEBUG_PSCCH_DMRS
LOG_I(PHY,
"PSCCH DMRS %d: l %d position %d => (%d,%d)\n",
dmrs_idx,
l,
k,
txdataF[l * frame_parms->ofdm_symbol_size + k].r,
txdataF[l * frame_parms->ofdm_symbol_size + k].i);
#endif
dmrs_idx++;
k_prime++;
} else { // SCI payload
txdataF[l * frame_parms->ofdm_symbol_size + k].r = (amp * mod_dci[dci_idx].r) >> 15;
txdataF[l * frame_parms->ofdm_symbol_size + k].i = (amp * mod_dci[dci_idx].i) >> 15;
#ifdef DEBUG_SCI
LOG_I(PHY,
"PSCCH: l %d position %d => (%d,%d)\n",
l,
k,
txdataF[l * frame_parms->ofdm_symbol_size + k].r,
txdataF[l * frame_parms->ofdm_symbol_size + k].i);
#endif
dci_idx++;
}
k++;
if (k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
} // m
} // reg_count
} // symbol_idx
LOG_D(NR_PHY,
"SCI: payloadSize = %d | payload = %llx\n",
dci_pdu->PayloadSizeBits,
*(unsigned long long *)dci_pdu->Payload);
sci_Nid = Nid;
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
return sci_Nid;
}

View File

@@ -0,0 +1,85 @@
/*
* 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.0 (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/nr_ulsch.h
* \brief functions used for PUSCH/ULSCH physical and transport channels for gNB
* \author Ahmed Hussein
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: ahmed.hussein@iis.fraunhofer.de
* \note
* \warning
*/
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#include "common/utils/threadPool/thread-pool.h"
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL);
NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
/*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2
@param phy_vars_gNB, Pointer to PHY data structure for gNB
@param UE_id, ID of UE transmitting this PUSCH
@param ulsch_llr, Pointer to received llr in ulsch
@param frame_parms, Pointer to frame descriptor structure
@param nb_symb_sch, number of symbols used in the uplink shared channel
@param nb_re_dmrs, number of DMRS resource elements in one RB
@param nr_tti_rx, current received TTI
@param harq_pid, harq process id
@param is_crnti
*/
int nr_slsch_decoding(struct PHY_VARS_NR_UE_s *UE,
uint8_t UE_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G,
const UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int8_t *ack_nack_rcvd,
uint8_t num_acks);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param llr, Pointer to llr bits
@param size, length of llr bits
@param q, codeword index (0,1)
@param Nid, cell id
@param n_RNTI, CRNTI
*/
void nr_ulsch_unscrambling(int16_t* llr, uint32_t size, uint32_t Nid, uint32_t n_RNTI);
void nr_ulsch_layer_demapping(int16_t *llr_cw, uint8_t Nl, uint8_t mod_order, uint32_t length, int16_t **llr_layers);
NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid);
void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB);
void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB);
NR_gNB_SCH_STATS_t *get_ulsch_stats(PHY_VARS_gNB *gNB,NR_gNB_ULSCH_t *ulsch);

View File

@@ -0,0 +1,299 @@
/*
* 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.0 (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/nr_slsch_decoding.c
* \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12
* \author Ahmed Hussein
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: ahmed.hussein@iis.fraunhofer.de
* \note
* \warning
*/
#include "PHY/defs_nr_UE.h"
// [from gNB coding]
#include "PHY/defs_gNB.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "openair1/SCHED_NR_UE/defs.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/LOG/log.h"
#include <syscall.h>
#include "executables/nr-uesoftmodem.h"
#include "PHY/sse_intrin.h"
//#define DEBUG_ULSCH_DECODING
//#define gNB_DEBUG_TRACE
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
//#define DEBUG_CRC
#ifdef DEBUG_CRC
#define PRINT_CRC_CHECK(a) a
#else
#define PRINT_CRC_CHECK(a)
#endif
//extern double cpuf;
/*
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL)
{
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated
if (N_RB_UL != 273) {
a_segments = a_segments*N_RB_UL;
a_segments = a_segments/273 +1;
}
if (ulsch->harq_process) {
if (ulsch->harq_process->b) {
free_and_zero(ulsch->harq_process->b);
ulsch->harq_process->b = NULL;
}
for (int r = 0; r < a_segments; r++) {
free_and_zero(ulsch->harq_process->c[r]);
free_and_zero(ulsch->harq_process->d[r]);
}
free_and_zero(ulsch->harq_process->c);
free_and_zero(ulsch->harq_process->d);
free_and_zero(ulsch->harq_process->d_to_be_cleared);
free_and_zero(ulsch->harq_process);
ulsch->harq_process = NULL;
}
}
NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
{
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated
if (N_RB_UL != 273) {
a_segments = a_segments*N_RB_UL;
a_segments = a_segments/273 +1;
}
uint32_t ulsch_bytes = a_segments * 1056; // allocated bytes per segment
NR_gNB_ULSCH_t ulsch = {0};
ulsch.max_ldpc_iterations = max_ldpc_iterations;
ulsch.harq_pid = -1;
ulsch.active = false;
NR_UL_gNB_HARQ_t *harq = malloc16_clear(sizeof(*harq));
init_abort(&harq->abort_decode);
ulsch.harq_process = harq;
harq->b = malloc16_clear(ulsch_bytes * sizeof(*harq->b));
harq->c = malloc16_clear(a_segments * sizeof(*harq->c));
harq->d = malloc16_clear(a_segments * sizeof(*harq->d));
for (int r = 0; r < a_segments; r++) {
harq->c[r] = malloc16_clear(8448 * sizeof(*harq->c[r]));
harq->d[r] = malloc16_clear(68 * 384 * sizeof(*harq->d[r]));
}
harq->d_to_be_cleared = calloc(a_segments, sizeof(bool));
AssertFatal(harq->d_to_be_cleared != NULL, "out of memory\n");
return(ulsch);
}
*/
int nr_slsch_decoding(struct PHY_VARS_NR_UE_s *UE,
uint8_t SLSCH_id,
short *slsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pssch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G,
const UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int8_t *ack_nack_rcvd,
uint8_t num_acks)
{
nrLDPC_TB_decoding_parameters_t TB;
memset(&TB, 0, sizeof(TB));
nrLDPC_slot_decoding_parameters_t slot_parameters = {.frame = frame,
.slot = nr_tti_rx,
.nb_TBs = 1,
.threadPool = &get_nrUE_params()->Tpool,
.TBs = &TB};
int max_num_segments = 0;
NR_gNB_ULSCH_t *slsch = &UE->slsch[SLSCH_id];
NR_UL_gNB_HARQ_t *harq_process = slsch->harq_process;
if (!harq_process) {
LOG_E(PHY, "slsch_decoding.c: NULL harq_process pointer\n");
return -1;
}
TB.G = G;
// The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead
TB.harq_unique_pid = SLSCH_id;
// ------------------------------------------------------------------
TB.nb_rb = pssch_pdu->rb_size;
TB.Qm = pssch_pdu->qam_mod_order;
TB.mcs = pssch_pdu->mcs_index;
TB.nb_layers = pssch_pdu->nrOfLayers;
// ------------------------------------------------------------------
TB.processedSegments = &harq_process->processedSegments;
int TBS = pssch_pdu->pusch_data.tb_size;
TB.BG = pssch_pdu->maintenance_parms_v3.ldpcBaseGraph;
TB.A = TBS << 3;
/*
NR_gNB_PHY_STATS_t *stats = UE->slsch_stats;
if (stats) {
stats->frame = frame;
stats->ulsch_stats.round_trials[harq_process->round]++;
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]);
stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]);
}
if (!harq_process->harq_to_be_cleared) {
stats->ulsch_stats.current_Qm = TB.Qm;
stats->ulsch_stats.current_RI = TB.nb_layers;
stats->ulsch_stats.total_bytes_tx += TBS;
}
}
*/
LOG_D(PHY,
"SLSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n",
harq_pid,
slsch->rnti,
TB.A,
TB.G,
TB.mcs,
TB.nb_layers,
TB.nb_rb,
TB.Qm,
pssch_pdu->target_code_rate / 10240.0f,
pssch_pdu->pusch_data.rv_index,
harq_process->round,
harq_process->harq_to_be_cleared);
// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F)
nr_segmentation(NULL,
NULL,
lenWithCrc(1, TB.A), // size in case of 1 segment
&TB.C,
&TB.K,
&TB.Z, // [hna] Z is Zc
&TB.F,
TB.BG);
harq_process->C = TB.C;
harq_process->K = TB.K;
harq_process->Z = TB.Z;
harq_process->F = TB.F;
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * TB.nb_layers; // number of segments to be allocated
if (TB.C > a_segments) {
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB.A);
return (-1);
}
if (TB.nb_rb != 273) {
a_segments = a_segments * TB.nb_rb;
a_segments = a_segments / 273 + 1;
}
if (TB.C > a_segments) {
LOG_E(PHY, "Illegal harq_process->C %d > %d\n", harq_process->C, a_segments);
return -1;
}
max_num_segments = max(max_num_segments, TB.C);
#ifdef DEBUG_ULSCH_DECODING
printf("slsch decoding nr segmentation Z %d\n", TB.Z);
if (!frame % 100)
printf("K %d C %d Z %d \n", TB.K, TB.C, TB.Z);
printf("Segmentation: C %d, K %d\n", TB.C, TB.K);
#endif
TB.max_ldpc_iterations = slsch->max_ldpc_iterations;
TB.rv_index = pssch_pdu->pusch_data.rv_index;
TB.tbslbrm = pssch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
TB.abort_decode = &harq_process->abort_decode;
set_abort(&harq_process->abort_decode, false);
nrLDPC_segment_decoding_parameters_t segments[max_num_segments];
memset(segments, 0, sizeof(segments));
TB.segments = segments;
uint32_t r_offset = 0;
for (int r = 0; r < TB.C; r++) {
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB.segments[r];
segment_parameters->E = nr_get_E(TB.G, TB.C, TB.Qm, TB.nb_layers, r);
segment_parameters->R = nr_get_R_ldpc_decoder(TB.rv_index,
segment_parameters->E,
TB.BG,
TB.Z,
&harq_process->llrLen,
harq_process->round);
segment_parameters->llr = slsch_llr + r_offset;
segment_parameters->d = harq_process->d[r];
segment_parameters->d_to_be_cleared = &harq_process->d_to_be_cleared[r];
segment_parameters->c = harq_process->c[r];
segment_parameters->decodeSuccess = false;
reset_meas(&segment_parameters->ts_deinterleave);
reset_meas(&segment_parameters->ts_rate_unmatch);
reset_meas(&segment_parameters->ts_ldpc_decode);
r_offset += segment_parameters->E;
}
if (harq_process->harq_to_be_cleared) {
for (int r = 0; r < TB.C; r++) {
harq_process->d_to_be_cleared[r] = true;
}
harq_process->harq_to_be_cleared = false;
}
int ret_decoder = UE->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
// post decode
uint32_t offset = 0;
for (int r = 0; r < TB.C; r++) {
nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = TB.segments[r];
// Copy c to b in case of decoding success
if (nrLDPC_segment_decoding_parameters.decodeSuccess) {
memcpy(harq_process->b + offset,
harq_process->c[r],
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
} else {
LOG_D(PHY, "sidelink segment error %d/%d\n", r, harq_process->C);
LOG_D(PHY, "SLSCH %d in error\n", SLSCH_id);
}
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
}
return ret_decoder;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,548 @@
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
/*!
* \brief Top-level routines for transmission of the PSSCH TS 38.211 v 16.3.0
*/
#include <stdint.h>
#include "PHY/gold.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_REFSIG/ptrs_nr.h"
#include "PHY/NR_REFSIG/sl_refsig_defs.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/MODULATION/modulation_common.h"
#include "common/utils/assertions.h"
#include "common/utils/nr/nr_common.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/NR_TRANSPORT/nr_dci.h"
#include "PHY/defs_nr_common.h"
#include "PHY/TOOLS/tools_defs.h"
#include "executables/nr-softmodem.h"
#include "executables/nr-uesoftmodem.h"
#include "executables/softmodem-common.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include <openair2/UTIL/OPT/opt.h>
//#define DEBUG_PUSCH_MAPPING
//#define DEBUG_MAC_PDU
//#define DEBUG_DFT_IDFT
//extern int32_t uplink_counter;
void nr_pssch_codeword_scrambling_sci(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t* out)
{
uint8_t reset, b_idx;
uint32_t x1 = 0, x2 = 0, s = 0;
reset = 1;
x2 = (Nid<<15) + 1010;
for (int i=0; i<size; i++) {
b_idx = i&0x1f;
if (b_idx==0) {
s = gold_generic(&x1, &x2, reset);
reset = 0;
if (i)
out++;
}
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
//printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
}
}
void nr_pssch_codeword_scrambling_sci_2layer(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t* out)
{
uint8_t reset, b_idx;
uint32_t x1 = 0, x2 = 0, s = 0;
reset = 1;
x2 = (Nid<<15) + 1010;
for (int i=0; i<size; i+=4) {
b_idx = i&0x1f;
if (b_idx==0) {
s = gold_generic(&x1, &x2, reset);
reset = 0;
if (i)
out++;
}
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
*out ^= (((in[i+1])&1) ^ ((s>>(b_idx+1))&1))<<(b_idx+1);
*out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<(b_idx+2);
*out ^= (((in[i+1])&1) ^ ((s>>(b_idx+1))&1))<<(b_idx+3);
//printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
}
}
int dmrs_pscch_mask[2] = {7,15} ;
void nr_ue_slsch_procedures(PHY_VARS_NR_UE *UE,
const unsigned char harq_pid,
const uint32_t frame,
const uint8_t slot,
nr_phy_data_tx_t *phy_data,
c16_t **txdataF)
{
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot);
int Wf[2], Wt[2];
int l_prime[2], delta;
uint8_t nb_dmrs_re_per_rb;
int i;
int sample_offsetF, N_RE_prime;
bool is_csi_rs_slot = false;
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)
is_csi_rs_slot = true;
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = is_csi_rs_slot ? (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&phy_data->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu : NULL;
if (csi_params)
LOG_D(NR_PHY, "Tx start_rb %i, cdm_type %i, csi_type %i, freq_density %i, nr_of_rbs %i, row %i symb_l0 %i is_csi_rs_slot %i\n",
csi_params->start_rb, csi_params->cdm_type, csi_params->csi_type, csi_params->freq_density, csi_params->nr_of_rbs, csi_params->row, csi_params->symb_l0, is_csi_rs_slot);
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
uint16_t number_dmrs_symbols = 0;
NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch;
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu = &phy_data->nr_sl_pssch_pscch_pdu;
NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->sl_harq_processes[harq_pid];
NR_DL_FRAME_PARMS *frame_parms = pscch_pssch_pdu == NULL ? &UE->frame_parms : &UE->SL_UE_PHY_PARAMS.sl_frame_params;
int start_symbol = (1+pscch_pssch_pdu->pssch_startsym);
uint16_t ul_dmrs_symb_pos = pscch_pssch_pdu->dmrs_symbol_position;
uint8_t number_of_symbols = pscch_pssch_pdu->pssch_numsym;
uint8_t dmrs_type = pusch_dmrs_type1;
uint16_t start_rb = pscch_pssch_pdu->startrb;
uint16_t nb_rb = pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size;
uint8_t Nl = pscch_pssch_pdu->num_layers;
uint8_t mod_order = pscch_pssch_pdu->mod_order;
uint16_t rnti = 0;
uint8_t cdm_grps_no_data = 1;
uint16_t start_sc = frame_parms->first_carrier_offset + start_rb*NR_NB_SC_PER_RB;
uint16_t Tpmi = 0;
if (start_sc >= frame_parms->ofdm_symbol_size)
start_sc -= frame_parms->ofdm_symbol_size;
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
uint8_t first_dmrs_symbol = 0;
bool is_first_dmrs_symbol = true;
for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) {
if((ul_dmrs_symb_pos >> i) & 0x01) {
number_dmrs_symbols += 1;
if (is_first_dmrs_symbol) {
first_dmrs_symbol = i;
is_first_dmrs_symbol = false;
}
if (csi_params && csi_params->symb_l0 != 0)
AssertFatal(i != csi_params->symb_l0, "CSI-RS (symb_l0 %d) MUST not be sent in DMRS symbol (%d)\n", csi_params->symb_l0, i);
}
}
if (csi_params && csi_params->symb_l0 != 0)
AssertFatal(csi_params->symb_l0 > pscch_pssch_pdu->pscch_numsym, "CSI-RS (symb_l0 %d) MUST not be sent in PSCCH symbol (%d)\n", csi_params->symb_l0, pscch_pssch_pdu->pscch_numsym);
nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data;
//LOG_I(NR_PHY,"%s TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",pscch_pssch_pdu==NULL?"PUSCH":"PSSCH",
// rnti,start_rb,nb_rb,mod_order,Nl,Tpmi,pscch_pssch_pdu==NULL?pusch_pdu->bwp_start:0,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
// TbD num_of_mod_symbols is set but never used
uint16_t num_CSI_REs = is_csi_rs_slot ? get_nRECSI_RS(csi_params->freq_density, csi_params->nr_of_rbs, get_nrUE_params()->nb_antennas_tx) : 0;
int num_CSI_REs_per_RB = is_csi_rs_slot ? (num_CSI_REs/csi_params->nr_of_rbs) : 0;
N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh - num_CSI_REs_per_RB;
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
/////////////////////////ULSCH coding/////////////////////////
///////////
int sci2_re = get_NREsci2(pscch_pssch_pdu->sci2_alpha_times_100,
pscch_pssch_pdu->sci2_payload_len,
pscch_pssch_pdu->sci2_beta_offset,
pscch_pssch_pdu->pssch_numsym,
pscch_pssch_pdu->pscch_numsym,
pscch_pssch_pdu->pscch_numrbs,
pscch_pssch_pdu->l_subch,
pscch_pssch_pdu->subchannel_size,
pscch_pssch_pdu->target_coderate);
//if (pscch_pssch_pdu) LOG_I(NR_PHY,"dmrs_symbol_position %x, pscch_numsym %d\n",pscch_pssch_pdu->dmrs_symbol_position,pscch_pssch_pdu->pscch_numsym);
AssertFatal(pscch_pssch_pdu->pscch_numsym==2 || pscch_pssch_pdu->pscch_numsym==3,"illegal pscch_numsym %d\n",pscch_pssch_pdu->pscch_numsym);
int sci1_dmrs_overlap = pscch_pssch_pdu->dmrs_symbol_position & dmrs_pscch_mask[pscch_pssch_pdu->pscch_numsym-2];
uint16_t sci1_re = pscch_pssch_pdu->pscch_numsym * pscch_pssch_pdu->pscch_numrbs * NR_NB_SC_PER_RB;
unsigned int G = nr_get_G_SL(nb_rb, number_of_symbols, 6, number_dmrs_symbols, sci1_dmrs_overlap, sci1_re, pscch_pssch_pdu->pscch_numrbs, sci2_re, num_CSI_REs, mod_order, Nl);
// Following code checks, after PSCCH symbols and DMRS symbols, whether PSSCH symbols are used by SCI2 or not,
// If true, then CSI-RS MUST not be sent in those PSSCH symbols containing SCI2.
if (csi_params && csi_params->symb_l0 != 0) {
int32_t next_symbs_sci2_re = 0;
int32_t sci1_re = 12 * pscch_pssch_pdu->pscch_numrbs;
int32_t non_sci1_re = 12 * nb_rb - sci1_re;
next_symbs_sci2_re = first_dmrs_symbol <= pscch_pssch_pdu->pscch_numsym ? sci2_re - (non_sci1_re / 2 - (non_sci1_re * (pscch_pssch_pdu->pscch_numsym - 1)) - (12 * nb_rb) / 2) : sci2_re - (12 * nb_rb) / 2;
int8_t remaining_sci2_symb = next_symbs_sci2_re > 0 ? ceil(next_symbs_sci2_re / (12 * nb_rb)) : 0;
int8_t non_csi_rs_symbs = pscch_pssch_pdu->pscch_numsym + 1 + remaining_sci2_symb; // 1 is for first dmrs symbol
AssertFatal(csi_params->symb_l0 > non_csi_rs_symbs, "CSI-RS MUST not be sent in PSSCH symbol containing SCI2");
}
uint32_t Gsci2 = sci2_re*2*Nl;
ws_trace_t tmp = {.nr = true,
.direction = DIRECTION_UPLINK,
.pdu_buffer = harq_process_ul_ue->payload_AB,
.pdu_buffer_size = pscch_pssch_pdu->tb_size,
.ueid = 0,
.rntiType = WS_C_RNTI,
.rnti = rnti,
.sysFrame = frame,
.subframe = slot,
.harq_pid = harq_pid,
.oob_event = 0,
.oob_event_value = 0};
trace_pdu(&tmp);
uint8_t ULSCH_ids = 0;
if (nr_ulsch_encoding(UE, ulsch_ue, pscch_pssch_pdu,harq_pid, frame, slot , &G, 1, &ULSCH_ids) == -1)
return;
uint32_t sci2_encoded_output[sci2_re*2];
if (pscch_pssch_pdu) {
LOG_D(NR_PHY,"Generating SCI2/PSSCH with %d RE, payload %llx\n",sci2_re,*(unsigned long long*)pscch_pssch_pdu->sci2_payload);
// do SCI2 encoding
polar_encoder_fast((uint64_t*)pscch_pssch_pdu->sci2_payload, (void*)sci2_encoded_output, 0, 1,
NR_POLAR_SCI2_MESSAGE_TYPE,
pscch_pssch_pdu->sci2_payload_len, sci2_re);
}
///////////
////////////////////////////////////////////////////////////////////
/////////////////////////SLSCH scrambling/////////////////////////
///////////
uint32_t available_bits = G;
uint32_t scrambled_output[(available_bits>>5)+1];
uint32_t scrambled_output_sci[(Gsci2>>5)+1];
memset(scrambled_output, 0, ((available_bits>>5)+1)*sizeof(uint32_t));
memset(scrambled_output_sci, 0, ((Gsci2>>5)+1)*sizeof(uint32_t));
// for (int i=0;i<(Gsci2>>5)+1;i++) LOG_I(NR_PHY,"sci2_encoded[%d] %x\n",i,sci2_encoded_output[i]);
// for (int g=0;g<G;g++) LOG_I(NR_PHY,"coded_output_f[%d] %d\n",g,harq_process_ul_ue->f[g]);
// LOG_I(NR_PHY,"Scrambling with Nid %x\n",phy_data->pscch_Nid);
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
G,
phy_data->pscch_Nid,
1010,
false,
NULL,
scrambled_output);
if (Nl==1)
nr_sci_scrambling(sci2_encoded_output,
Gsci2,
phy_data->pscch_Nid,1010,
scrambled_output_sci,1);
else
nr_pssch_codeword_scrambling_sci_2layer(sci2_encoded_output,
Gsci2,
phy_data->pscch_Nid,
scrambled_output_sci);
/////////////
//////////////////////////////////////////////////////////////////////////
/////////////////////////ULSCH modulation/////////////////////////
///////////
int max_num_re = Nl*number_of_symbols*nb_rb*NR_NB_SC_PER_RB;
int32_t d_mod[max_num_re] __attribute__ ((aligned(16)));
if (Gsci2 > 0) {
nr_modulation(scrambled_output_sci, // assume one codeword for the moment
Gsci2,
2,
(int16_t *)d_mod);
//for (int i=0;i<Gsci2;i+=2) LOG_I(NR_PHY,"SCI2 RE %d/%d: (%d,%d)\n",i/2,Gsci2/2,((int16_t*)d_mod)[i],((int16_t*)d_mod)[i+1]);
int32_t d_mod2[max_num_re] __attribute__ ((aligned(16)));
nr_modulation(scrambled_output, // assume one codeword for the moment
available_bits,
mod_order,
(int16_t *)d_mod2);
LOG_D(NR_PHY,"SCI bits %d (sci2_re %d), PSSCH bits %d (PSCCH RE %d), max_re %d\n",Gsci2,sci2_re,available_bits,available_bits/mod_order,max_num_re);
memcpy(d_mod+sci2_re,d_mod2,available_bits*sizeof(int32_t)/mod_order);
}
else
nr_modulation(scrambled_output, // assume one codeword for the moment
available_bits,
mod_order,
(int16_t *)d_mod);
///////////
////////////////////////////////////////////////////////////////////////
/////////////////////////DMRS Modulation/////////////////////////
///////////
uint16_t n_dmrs = (start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
c16_t mod_dmrs[n_dmrs] __attribute((aligned(16)));
/////////////////////////SLSCH layer mapping/////////////////////////
///////////
c16_t tx_layers[Nl][(available_bits/mod_order)+sci2_re] __attribute__((aligned(64)));
nr_ue_layer_mapping((c16_t *)d_mod,
Nl,
(available_bits/mod_order)+sci2_re,
tx_layers);
///////////
////////////////////////////////////////////////////////////////////////
/////////////////////////SLSCH RE mapping/////////////////////////
///////////
int encoded_length = frame_parms->N_RB_UL*14*NR_NB_SC_PER_RB*mod_order*Nl;
c16_t tx_precoding[Nl][encoded_length] __attribute__((aligned(64)));
for (int nl=0; nl < Nl; nl++) {
uint8_t k_prime = 0;
uint16_t m = 0;
#ifdef DEBUG_PUSCH_MAPPING
LOG_I(NR_PHY,"NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
#endif
int dmrs_port = get_dmrs_port(nl,Nl);
if (dmrs_port < 0) return;
// DMRS params for this dmrs port
get_Wt(Wt, dmrs_port, dmrs_type);
get_Wf(Wf, dmrs_port, dmrs_type);
delta = get_delta(dmrs_port, dmrs_type);
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
uint16_t k = start_sc;
uint16_t n = 0;
uint8_t is_dmrs_sym = 0;
uint8_t is_csi_rs_sym = 0;
uint16_t dmrs_idx = 0;
int16_t csi_rs_rb = 0;
int is_pscch_sym = 0;
if (l<(start_symbol + pscch_pssch_pdu->pscch_numsym)) {
is_pscch_sym = 1;
}
if (is_csi_rs_slot && l == csi_params->symb_l0) {
is_csi_rs_sym = 1;
csi_rs_rb = csi_params->start_rb;
}
if ((ul_dmrs_symb_pos >> l) & 0x01) {
is_dmrs_sym = 1;
dmrs_idx = start_rb*6;
// TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part
// Perform this on gold sequence, not required when SC FDMA operation is done,
LOG_D(PHY,"DMRS in symbol %d\n",l);
uint32_t pssch_dmrs[((frame_parms->N_RB_UL * 12) >> 5) + 1];
nr_init_pssch_dmrs_oneshot(frame_parms,phy_data->pscch_Nid,pssch_dmrs,slot,l);
nr_modulation(pssch_dmrs, n_dmrs*2, DMRS_MOD_ORDER, (int16_t*)mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
} else {
dmrs_idx = 0;
}
for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) {
uint8_t is_dmrs = 0;
uint8_t is_csi_rs = 0;
if (is_pscch_sym && i==(pscch_pssch_pdu->startrb)) {
i+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
k+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
if (is_dmrs_sym) {
dmrs_idx+=(6*pscch_pssch_pdu->pscch_numrbs);
n+=(3*pscch_pssch_pdu->pscch_numrbs);
}
}
LOG_D(NR_PHY, "symbol %d re %d/%d k %d\n", l, i, nb_rb*NR_NB_SC_PER_RB, k);
sample_offsetF = l*frame_parms->ofdm_symbol_size + k;
if (is_dmrs_sym) {
if (k == ((start_sc+get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type))%frame_parms->ofdm_symbol_size))
is_dmrs = 1;
}
if (is_csi_rs_sym) {
AssertFatal(1==0,"No SL CSI-RS for now\n");
/*
if ((k >= csi_params->start_rb * NR_NB_SC_PER_RB) && (i % NR_NB_SC_PER_RB == 0) && (csi_rs_rb < csi_params->nr_of_rbs)) {
csi_rs_params_t table_params;
get_csi_rs_params_from_table(csi_params, &table_params);
port_freq_indices_t *port_freq_indices = (port_freq_indices_t *)malloc(table_params.ports*sizeof(port_freq_indices));
get_csi_rs_freq_ind_sl(frame_parms, csi_rs_rb, csi_params, &table_params, port_freq_indices);
if (k == port_freq_indices[nl].k) {
is_csi_rs = 1;
csi_rs_rb++;
LOG_D(NR_PHY, "Tx port_freq_indices.p %i, port_freq_indices.k %d, is_csi_rs %d, k = %i, RE %i, csi_rs_rb %i\n",
port_freq_indices[nl].p, port_freq_indices[nl].k, is_csi_rs, k, i, csi_rs_rb);
}
free(port_freq_indices);
port_freq_indices = NULL;
}*/
}
if (is_dmrs == 1) {
tx_precoding[nl][sample_offsetF].r = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx].r) >> 15;
tx_precoding[nl][sample_offsetF].i = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx].i) >> 15;
#ifdef DEBUG_PUSCH_MAPPING
LOG_I(NR_PHY,"DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
nl, dmrs_idx, l, k, k_prime, n,
tx_precoding[nl][sample_offsetF].r,
tx_precoding[nl][sample_offsetF].i);
#endif
dmrs_idx++;
k_prime++;
k_prime&=1;
n+=(k_prime)?0:1;
} else if (!is_dmrs_sym || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
if (!is_csi_rs) {
tx_precoding[nl][sample_offsetF].r = tx_layers[nl][m].r;
tx_precoding[nl][sample_offsetF].i = tx_layers[nl][m].i;
} else {
tx_precoding[nl][sample_offsetF] = (c16_t){.r=0,.i=0};
}
#ifdef DEBUG_PUSCH_MAPPING
LOG_I(NR_PHY,"DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
nl, m, l, k,
tx_precoding[nl][sample_offsetF].r,
tx_precoding[nl][sample_offsetF].i);
#endif
if (!is_csi_rs)
m++;
} else {
tx_precoding[nl][sample_offsetF] = (c16_t){.r=0,.i=0};
}
if (++k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
} //for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++)
}//for (l=start_symbol; l<start_symbol+number_of_symbols; l++)
}//for (nl=0; nl < Nl; nl++)
/////////////////////////ULSCH precoding/////////////////////////
///////////
///Layer Precoding and Antenna port mapping
// tx_layers 0-3 are mapped on antenna ports
// The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx
// The same precoding matrix is applied on prg_size RBs, Thus
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
// The Precoding matrix:
for (int ap=0; ap<frame_parms->nb_antennas_tx; ap++) {
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
uint16_t k = start_sc;
int is_pscch_sym = 0;
if (pscch_pssch_pdu && l<(start_symbol + pscch_pssch_pdu->pscch_numsym)) {
is_pscch_sym = 1;
}
for (int rb=0; rb<nb_rb; rb++) {
if (is_pscch_sym && rb==(pscch_pssch_pdu->startrb)) {
k+=(pscch_pssch_pdu->pscch_numrbs*NR_NB_SC_PER_RB);
if (k>=frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
rb=pscch_pssch_pdu->startrb+pscch_pssch_pdu->pscch_numrbs;
}
//get pmi info
uint8_t pmi=Tpmi;
if (pmi == 0) {//unitary Precoding
if (k + NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { // RB does not cross DC
if (ap<Nl)
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)],
NR_NB_SC_PER_RB*sizeof(int32_t));
else
memset(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
0,
NR_NB_SC_PER_RB*sizeof(int32_t));
} else { // RB does cross DC
int neg_length = frame_parms->ofdm_symbol_size - k;
int pos_length = NR_NB_SC_PER_RB - neg_length;
if (ap<Nl) {
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)],
neg_length*sizeof(int32_t));
memcpy(&txdataF[ap][l*frame_parms->ofdm_symbol_size],
&tx_precoding[ap][2*(l*frame_parms->ofdm_symbol_size)],
pos_length*sizeof(int32_t));
} else {
memset(&txdataF[ap][l*frame_parms->ofdm_symbol_size + k],
0,
neg_length*sizeof(int32_t));
memset(&txdataF[ap][l*frame_parms->ofdm_symbol_size],
0,
pos_length*sizeof(int32_t));
}
}
k += NR_NB_SC_PER_RB;
if (k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
}
else {
//get the precoding matrix weights:
const char *W_prec;
switch (frame_parms->nb_antennas_tx) {
case 1://1 antenna port
W_prec = nr_W_1l_2p[pmi][ap];
break;
case 2://2 antenna ports
if (Nl == 1)//1 layer
W_prec = nr_W_1l_2p[pmi][ap];
else//2 layers
W_prec = nr_W_2l_2p[pmi][ap];
break;
case 4://4 antenna ports
if (Nl == 1)//1 layer
W_prec = nr_W_1l_4p[pmi][ap];
else if (Nl == 2)//2 layers
W_prec = nr_W_2l_4p[pmi][ap];
else if (Nl == 3)//3 layers
W_prec = nr_W_3l_4p[pmi][ap];
else//4 layers
W_prec = nr_W_4l_4p[pmi][ap];
break;
default:
LOG_D(PHY,"Precoding 1,2, or 4 antenna ports are currently supported\n");
W_prec = nr_W_1l_2p[pmi][ap];
break;
}
for (int i=0; i<NR_NB_SC_PER_RB; i++) {
int32_t re_offset = l*frame_parms->ofdm_symbol_size + k;
c16_t precodatatx_F = nr_layer_precoder(encoded_length,tx_precoding, W_prec, Nl, re_offset);
txdataF[ap][re_offset].r = precodatatx_F.r;
txdataF[ap][re_offset].i = precodatatx_F.i;
if (++k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
}
}
} //RB loop
} // symbol loop
}// port loop
}

View File

@@ -15,6 +15,8 @@
#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1
#define NR_PUSCH_y 3 // UCI placeholder bit
#define FILTER_MARGIN 32
typedef enum {
BIT_TYPE_ULSCH = 0, // Default: UL-SCH data
BIT_TYPE_ACK = 1, // HARQ-ACK bit
@@ -85,6 +87,8 @@ int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue,
Transport Block.
@param[in] phy_vars_ue pointer to ue variables
@param[in] ulsch Pointer to ULSCH descriptor
@param[in] pscch_pssch_pdu Pointer to PSSCH descriptor. Non-null means PSSCH is used here
@param[in] sl_harq_pid Index of harq_pid for PSSCH
@param[in] frame frame index
@param[in] slot slot index
@param[in] G array of Gs
@@ -94,6 +98,8 @@ int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue,
*/
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
NR_UE_ULSCH_t *ulsch,
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
uint8_t sl_harq_pid,
const uint32_t frame,
const uint8_t slot,
unsigned int *G,
@@ -344,6 +350,96 @@ void nr_pbch_unscrambling(int16_t *demod_pbch_e,
uint32_t pbch_a_prime,
uint32_t *pbch_a_interleaved);
void nr_pbch_quantize(int16_t *pbch_llr8, int16_t *pbch_llr, uint16_t len);
void nr_pdcch_unscrambling(c16_t *e_rx,
uint16_t scrambling_RNTI,
uint32_t length,
uint16_t pdcch_DMRS_scrambling_id,
int16_t *z2);
int nr_pssch_channel_estimation(PHY_VARS_NR_UE *ue,
int rxFSz,
c16_t rxdataF[][rxFSz],
unsigned char Ns,
unsigned short p,
unsigned char symbol,
int ul_id,
unsigned short bwp_start_subcarrier,
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu,
int *max_ch,
uint32_t *nvar);
void nr_ue_slsch_procedures(PHY_VARS_NR_UE *UE,
const unsigned char harq_pid,
const uint32_t frame,
const uint8_t slot,
nr_phy_data_tx_t *phy_data,
c16_t **txdataF);
void nr_rx_pssch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
nr_phy_data_t *phy_data,
int rxFSz,
c16_t rxdataF[][rxFSz],
int16_t *llrs,
uint8_t ulsch_id,
uint32_t frame,
uint8_t slot,
unsigned char harq_pid,
bool *is_csi_rs_slot);
void nr_pscch_scrambling(uint32_t *in,
uint32_t size,
uint32_t Nid,
uint32_t scrambling_RNTI,
uint32_t *out,
int sci_flag);
void nr_sci_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint32_t scrambling_RNTI, uint32_t *out,int sci2_flag);
uint32_t nr_generate_sci(PHY_VARS_NR_UE *ue,
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
c16_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);
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);
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);
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);
int nr_csi_rs_sinr_estimation(const PHY_VARS_NR_UE *ue,
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
const uint8_t N_ports,
uint8_t mem_offset,
const c16_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
const uint32_t interference_plus_noise_power,
const int16_t log2_re,
int32_t *precoded_sinr_dB);
/**@}*/
#endif

View File

@@ -137,6 +137,8 @@ int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue,
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
NR_UE_ULSCH_t *ulsch,
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu,
uint8_t sl_harq_pid,
const uint32_t frame,
const uint8_t slot,
unsigned int *G,
@@ -144,6 +146,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
uint8_t *ULSCH_ids)
{
start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS);
AssertFatal(!(pscch_pssch_pdu && nb_ulsch > 1), "pscch_pssch_pdu %p nb_ulsch %d\n", pscch_pssch_pdu, nb_ulsch);
nrLDPC_TB_encoding_parameters_t TBs[nb_ulsch];
memset(TBs, 0, sizeof(TBs));
@@ -158,24 +161,27 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
.TBs = TBs};
int max_num_segments = 0;
for (uint_fast8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
const uint8_t ULSCH_id = ULSCH_ids[pusch_id];
const uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
max_num_segments = max(max_num_segments, harq_process->C);
}
if (!pscch_pssch_pdu) {
for (uint_fast8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
const uint8_t ULSCH_id = ULSCH_ids[pusch_id];
const uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
max_num_segments = max(max_num_segments, harq_process->C);
}
} else
max_num_segments = ue->ul_harq_processes[sl_harq_pid].C;
nrLDPC_segment_encoding_parameters_t segments[nb_ulsch][max_num_segments];
memset(segments, 0, sizeof(segments));
for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
uint8_t harq_pid = pscch_pssch_pdu ? sl_harq_pid : ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id];
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
NR_UL_UE_HARQ_t *harq_process = pscch_pssch_pdu ? &ue->sl_harq_processes[harq_pid] : &ue->ul_harq_processes[harq_pid];
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch[ULSCH_id].pusch_pdu;
const uint16_t nb_rb = pusch_pdu->rb_size;
const uint16_t nb_rb = pscch_pssch_pdu ? pscch_pssch_pdu->l_subch * pscch_pssch_pdu->subchannel_size : pusch_pdu->rb_size;
TB_parameters->harq_unique_pid = 2 * harq_pid + ULSCH_id;
TB_parameters->C = harq_process->C;
TB_parameters->K = harq_process->K;
@@ -184,13 +190,13 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
TB_parameters->BG = harq_process->BG;
TB_parameters->Kb = harq_process->Kb;
TB_parameters->nb_rb = nb_rb;
TB_parameters->Qm = pusch_pdu->qam_mod_order;
TB_parameters->mcs = pusch_pdu->mcs_index;
TB_parameters->nb_layers = pusch_pdu->nrOfLayers;
TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index;
TB_parameters->Qm = pscch_pssch_pdu ? pscch_pssch_pdu->mod_order : pusch_pdu->qam_mod_order;
TB_parameters->mcs = pscch_pssch_pdu ? pscch_pssch_pdu->mcs : pusch_pdu->mcs_index;
TB_parameters->nb_layers = pscch_pssch_pdu ? pscch_pssch_pdu->num_layers : pusch_pdu->nrOfLayers;
TB_parameters->rv_index = pscch_pssch_pdu ? pscch_pssch_pdu->rv_index : pusch_pdu->pusch_data.rv_index;
TB_parameters->G = G[pusch_id];
TB_parameters->tbslbrm = pusch_pdu->tbslbrm;
TB_parameters->A = pusch_pdu->pusch_data.tb_size / 8;
TB_parameters->tbslbrm = pscch_pssch_pdu ? pscch_pssch_pdu->tbslbrm : pusch_pdu->tbslbrm;
TB_parameters->A = pscch_pssch_pdu ? pscch_pssch_pdu->tb_size : pusch_pdu->pusch_data.tb_size / 8;
TB_parameters->segments = segments[pusch_id];
memset(harq_process->f, 0, 14 * nb_rb * 12 * 16);

View File

@@ -1166,7 +1166,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
rm_info = calc_rate_match_info_uci(pusch_pdu, harq_process_ul_ue, nl_qm, &G[pusch_id]);
}
if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) {
if (nr_ulsch_encoding(UE, &phy_data->ulsch, NULL, 0, frame, slot, G, 1, ULSCH_ids) == -1) {
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
return;
}

View File

@@ -118,9 +118,14 @@ typedef struct {
prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET];
} NR_gNB_PRS;
// forward declaration for sidelink PSSCH PDU pointer in HARQ process
struct sl_nr_rx_config_pssch_sci_pdu;
typedef struct {
/// Nfapi ULSCH PDU
nfapi_nr_pusch_pdu_t ulsch_pdu; // !!
nfapi_nr_pusch_pdu_t ulsch_pdu;
/// Sidelink PSSCH PDU pointer (NULL for UL, set for SL reception)
struct sl_nr_rx_config_pssch_sci_pdu *pssch_pdu;
/// Index of current HARQ round for this DLSCH
uint8_t round;
bool new_rx;
@@ -157,7 +162,7 @@ typedef struct {
//////////////////////////////////////////////////////////////
} NR_UL_gNB_HARQ_t;
typedef struct {
typedef struct NR_gNB_ULSCH_s {
uint32_t frame;
uint32_t slot;
// identifier for concurrent beams
@@ -231,7 +236,7 @@ typedef struct {
int32_t debugBuff_sample_offset;
} NR_gNB_COMMON;
typedef struct {
typedef struct NR_gNB_PUSCH_s {
/// \brief Hold the channel estimates in frequency domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
@@ -319,7 +324,7 @@ typedef struct gNB_L1_proc_t_s {
gNB_L1_rxtx_proc_t L1_proc_tx;
} gNB_L1_proc_t;
typedef struct {
typedef struct PHY_MEASUREMENTS_gNB_s {
// common measurements
//! estimated noise power (linear)
unsigned int n0_power[MAX_NUM_RU_PER_gNB];

View File

@@ -74,6 +74,14 @@
#include "radio/COMMON/common_lib.h"
#include "NR_IF_Module.h"
#define MAX_PUCCH0_NID 8
typedef struct {
int nb_id;
int Nid[MAX_PUCCH0_NID];
int lut[MAX_PUCCH0_NID][160][14];
} NR_UE_PUCCH0_LUT_t;
/// Context data structure for gNB subframe processing
typedef struct {
/// Component Carrier index
@@ -202,6 +210,7 @@ typedef struct {
#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 PBCH_A 24
#define NR_SLSCH_RX_MAX 2
typedef struct {
int16_t amp;
@@ -267,6 +276,10 @@ typedef struct {
int used_by_ue;
} nrUE_cell_params_t;
// forward declarations for PSSCH reusing PUSCH
struct NR_gNB_ULSCH_s;
struct NR_gNB_PUSCH_s;
/// Top-level PHY Data Structure for UE
typedef struct PHY_VARS_NR_UE_s {
/// \brief Module ID indicator for this instance
@@ -338,6 +351,7 @@ typedef struct PHY_VARS_NR_UE_s {
uint8_t prs_active_gNBs;
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_HARQ_PROCESSES];
NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_HARQ_PROCESSES];
NR_UL_UE_HARQ_t sl_harq_processes[NR_MAX_HARQ_PROCESSES];
// Scrambling IDs used in PUSCH DMRS
c16_t X_u[64][839];
@@ -431,6 +445,21 @@ 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_s *slsch;
struct NR_gNB_PUSCH_s *pssch_vars;
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;
// PUCCH0 Look-up table for cyclic-shifts
NR_UE_PUCCH0_LUT_t pucch0_lut;
// Threading
Actor_t sync_actor;
Actor_t *dl_actors;
Actor_t *ul_actors;
@@ -517,6 +546,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 {
@@ -525,6 +556,13 @@ 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;

View File

@@ -86,6 +86,48 @@ 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;
@@ -103,6 +145,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;
@@ -111,6 +159,15 @@ typedef struct sl_nr_ue_phy_params {
// Sidelink PHY PARAMETERS USED FOR PSBCH reception/Txn
SL_NR_UE_PSBCH_t psbch;
// 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;

View File

@@ -5,6 +5,8 @@
#ifndef __openair_GOLD_H__
#define __openair_GOLD_H__
#include <stdint.h>
static inline uint32_t gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset)
{
int32_t n;

View File

@@ -66,7 +66,7 @@
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp);
int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data,int pscch_processing);
void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
@@ -117,14 +117,16 @@ void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue,
int num_monitoring_occ,
int max_symb,
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol]);
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol],
int pscch_processing);
void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
int llr_size,
int max_monOcc,
PHY_VARS_NR_UE *ue,
nr_phy_data_t *phy_data,
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size]);
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size],
int sci_indication);
void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
@@ -135,7 +137,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu);
int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
int psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp);
/*! \brief This function prepares the sl indication to pass to the MAC
*/
@@ -152,5 +154,12 @@ void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
void *typeSpecific,
uint16_t rx_slss_id);
typedef struct {
uint8_t *b;
int TBS;
int harq_pid;
bool rxok;
} slsch_status_t;
#endif
/** @}*/

View File

@@ -1011,7 +1011,7 @@ static int get_max_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config)
return max_pdcch_symb;
}
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data, int pscch_processing)
{
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
if (phy_pdcch_config->nb_search_space == 0)
@@ -1019,7 +1019,7 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
TracyCZone(ctx, true);
/* process PDCCH */
LOG_D(PHY, " ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", proc->frame_rx % 1024, proc->nr_slot_rx);
LOG_D(PHY, " ------ --> %s ChannelComp/LLR Frame.slot %d.%d ------ \n", pscch_processing ? "PSCCH" : "PDCCH", proc->frame_rx % 1024, proc->nr_slot_rx);
start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config, fp->symbols_per_slot);
@@ -1042,9 +1042,9 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
for (int ant = 0; ant < fp->nb_antennas_rx; ant++)
memcpy(rxdataF_symb[ant], &rxdataF[ant][symbol * fp->ofdm_symbol_size], sizeof(c16_t) * fp->ofdm_symbol_size);
nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr);
nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr,pscch_processing);
if (symbol == last_symb_pdcch) {
nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr);
nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr,pscch_processing);
UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr) / sizeof(c16_t), 0);
}
}

View File

@@ -13,6 +13,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 "PHY/NR_UE_TRANSPORT/nr_slsch.h"
#include "executables/nr-uesoftmodem.h"
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
sl_nr_rx_indication_t *rx_ind,
@@ -60,6 +62,19 @@ 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->b;
rx_slsch_pdu->pdu_length = slsch_status->TBS;
rx_slsch_pdu->harq_pid = slsch_status->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;
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;
@@ -92,6 +107,7 @@ static int nr_ue_psbch_procedures(PHY_VARS_NR_UE *ue,
struct complex16 dl_ch_estimates[][estimateSz],
nr_phy_data_t *phy_data,
c16_t rxdataF[][fp->samples_per_slot_wCP])
{
int ret = 0;
DevAssert(ue);
@@ -147,21 +163,190 @@ static int nr_ue_psbch_procedures(PHY_VARS_NR_UE *ue,
return ret;
}
int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
extern int dmrs_pscch_mask[2];
int nr_slsch_procedures(PHY_VARS_NR_UE *ue, int frame_rx, int slot_rx, int SLSCH_id, const 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) {
AssertFatal(1==0,"Don't do SL CSI-RS for now\n");
/*
freq_density = ue->csirs_vars[0]->csirs_config_pdu.freq_density;
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(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);
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);
//----------------------------------------------------------
//--------------------- SLSCH 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_slsch_decoding\n", frame_rx, slot_rx);
int nbDecode =
nr_slsch_decoding(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);
sl_nr_rx_indication_t sl_rx_indication;
nr_sidelink_indication_t sl_indication;
slsch_status_t slsch_status;
ue->slsch[SLSCH_id].active = false;
NR_UL_gNB_HARQ_t *harq_process = &ue->slsch[SLSCH_id].harq_process[harq_pid];
slsch_status.b = harq_process->b;
slsch_status.TBS = slsch_pdu->tb_size;
slsch_status.harq_pid = harq_pid;
slsch_status.rxok = nbDecode>0 ? true : false;
LOG_D(NR_PHY, "%4d.%2d SLSCH %s received ok \n", proc->frame_rx, proc->nr_slot_rx,nbDecode>0 ? "" : "not");
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 = (uint8_t*)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, (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);
return nbDecode;
}
int psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
{
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
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;
bool is_csi_rs_slot = false;
int8_t *ack_nack_rcvd = NULL;
int sampleShift = INT_MAX;
start_meas(&sl_phy_params->phy_proc_sl_rx);
LOG_D(NR_PHY, " ****** Sidelink RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx % 1024, nr_slot_rx);
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;
@@ -204,7 +389,6 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
// PSBCH present in symbols 0, 5-12 for normal cp
sym = (sym == 0) ? 5 : sym + 1;
}
ue->adjust_rxgain = nr_sl_psbch_rsrp_measurements(ue, sl_phy_params, fp, rxdataF, false);
LOG_D(NR_PHY, " ------ Decode SL-MIB: frame.slot %d.%d ------ \n", frame_rx % 1024, nr_slot_rx);
@@ -235,7 +419,188 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
LOG_I(NR_PHY, "============================================\n");
}
}
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;
phy_data->phy_pdcch_config.nb_search_space = 1;
pdcch_processing(ue, proc, phy_data,1);
LOG_D(NR_PHY,"returned from pscch processing\n");
}
else if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SCI) {
sl_nr_rx_config_pssch_sci_pdu_t *pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu;
LOG_D(NR_PHY,"sci2_len = %d\n",pssch_pdu->sci2_len);
LOG_D(NR_PHY,"sci2_beta_offset = %d\n",pssch_pdu->sci2_beta_offset);
LOG_D(NR_PHY,"sci2_alpha_times_100= %d\n",pssch_pdu->sci2_alpha_times_100);
LOG_D(NR_PHY,"pssch_targetCodeRate = %d\n",pssch_pdu->targetCodeRate);
LOG_D(NR_PHY,"pssch_num_layers = %d\n",pssch_pdu->num_layers);
LOG_D(NR_PHY,"dmrs_symbol_position = %d\n",pssch_pdu->dmrs_symbol_position);
int num_dmrs = 0;
for (int s = 0; s < pssch_pdu->pssch_numsym; s++)
num_dmrs += (pssch_pdu->dmrs_symbol_position >> s) & 1;
LOG_D(NR_PHY,"num_dmrs = %d\n",num_dmrs);
LOG_D(NR_PHY,"Nid = %x\n",pssch_pdu->Nid);
LOG_D(NR_PHY,"startrb = %d\n",pssch_pdu->startrb);
LOG_D(NR_PHY,"pscch_numsym = %d\n",pssch_pdu->pscch_numsym);
LOG_D(NR_PHY,"pscch_numrbs = %d\n",pssch_pdu->pscch_numrbs);
LOG_D(NR_PHY,"num_subch= %d\n",pssch_pdu->num_subch);
LOG_D(NR_PHY,"subchannel_size = %d\n",pssch_pdu->subchannel_size);
LOG_D(NR_PHY,"l_subch = %d\n",pssch_pdu->l_subch);
LOG_D(NR_PHY,"pssch_numsym = %d\n",pssch_pdu->pssch_numsym);
LOG_D(NR_PHY,"sense_pssch = %d\n",pssch_pdu->sense_pssch);
ue->slsch->harq_process->pssch_pdu = &phy_data->nr_sl_pssch_sci_pdu;
uint8_t freq_density = 0;
uint8_t nr_of_rbs = 0;
if (is_csi_rs_slot) {
AssertFatal(1==0,"Don't do SL CSIRS for now\n");
/*
freq_density = ue->csirs_vars[0]->csirs_config_pdu.freq_density;
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 sci2_re = get_NREsci2(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);
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];
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;
uint16_t start_symbol = 1;
uint16_t number_symbols = pssch_pdu->pssch_numsym;
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;
uint32_t G = nr_get_G_SL(rb_size,
pssch_pdu->pssch_numsym,
num_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);
LOG_D(NR_PHY,"Starting slot FEP for SLSCH (symbol %d to %d) pscch_numsym %d pssch_numsym %d REs with SCI2 %d G %d\n",
1 + pssch_pdu->pscch_numsym, pssch_pdu->pssch_numsym,
pssch_pdu->pscch_numsym, pssch_pdu->pssch_numsym, sci2_re, G);
for (int sym=1+pssch_pdu->pscch_numsym; sym<=pssch_pdu->pssch_numsym;sym++) {
nr_slot_fep(ue, fp, proc->nr_slot_rx, sym, rxdataF, link_type_sl, 0, ue->common_vars.rxdata);
}
int16_t *llrs = (int16_t*)__builtin_alloca_with_align(G*sizeof(int16_t),64);
nr_rx_pssch(ue,
proc,
phy_data,
rxdataF_sz,
rxdataF,
llrs,
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->nr_slot_rx, psfch_pdu->start_symbol_index, rxdataF, link_type_sl, 0, ue->common_vars.rxdata);
ack_nack_rcvd[k] = 0; // TODO missing: 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);
}
}
UEscopeCopy(ue, commonRxdataF, rxdataF, sizeof(int32_t), fp->nb_antennas_rx, rxdataF_sz, 0);
return sampleShift;
@@ -246,6 +611,10 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc
int slot_tx = proc->nr_slot_tx;
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;
@@ -282,7 +651,54 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc
}
tx_action = 1;
}
else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS ||
phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
if (phy_data->sl_tx_action >= SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH && phy_data->sl_tx_action <= SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS)
LOG_D(NR_PHY, "(%d.%d) Sending %s\n", frame_tx, slot_tx, sl_tx_actions[phy_data->sl_tx_action - SL_NR_CONFIG_TYPE_TX_PSBCH]);
phy_data->pscch_Nid = nr_generate_sci1(ue, txdataF[0], fp, AMP, slot_tx, &phy_data->nr_sl_pssch_pscch_pdu) &0xFFFF;
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)&phy_data->nr_sl_pssch_pscch_pdu.nr_sl_csi_rs_pdu;
csi_params->scramb_id = phy_data->pscch_Nid % (1 << 10);
nr_ue_slsch_procedures(ue, phy_data->nr_sl_pssch_pscch_pdu.harq_pid, frame_tx, slot_tx, phy_data, txdataF);
sl_phy_params->pscch.num_pscch_tx ++;
sl_phy_params->pssch.num_pssch_sci2_tx ++;
sl_phy_params->pssch.num_pssch_tx ++;
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
uint16_t beta_csirs = get_softmodem_params()->sl_mode ? (uint16_t)(AMP * (ceil(sqrt(phy_data->nr_sl_pssch_pscch_pdu.num_layers / fp->nb_antennas_tx)))) & 0xFFFF : AMP;
LOG_D(NR_PHY, "Tx beta_csirs: %d, scramb_id %i (%d.%d)\n", beta_csirs, csi_params->scramb_id, frame_tx, slot_tx);
AssertFatal(false, "CSI_RS not supported\n");
//nr_generate_csi_rs(fp,
// (int32_t **)txdataF,
// beta_csirs,
// ue->nr_csi_info,
// csi_params,
// slot_tx,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL);
}
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
for (int k = 0; k < phy_data->nr_sl_pssch_pscch_pdu.num_psfch_pdus; k++) {
nr_generate_psfch0(ue,
txdataF,
fp,
AMP,
slot_tx,
&phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list[k]);
}
sl_phy_params->psfch.num_psfch_tx ++;
free(phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list);
phy_data->nr_sl_pssch_pscch_pdu.psfch_pdu_list = NULL;
}
tx_action = 1;
}
bool was_symbol_used[NR_SYMBOLS_PER_SLOT];
for (int i = 0; i < 14; i++)
was_symbol_used[i] = true;
@@ -301,3 +717,4 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc
LOG_D(NR_PHY, "****** end Sidelink TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx);
stop_meas(&sl_phy_params->phy_proc_sl_tx);
}

View File

@@ -1294,7 +1294,7 @@ int main(int argc, char **argv)
nr_ue_scheduled_response(&scheduled_response);
pbch_processing(UE, &UE_proc, &phy_data);
pdcch_processing(UE, &UE_proc, &phy_data);
pdcch_processing(UE, &UE_proc, &phy_data,0);
pdsch_processing(UE,
&UE_proc,
&phy_data);

View File

@@ -46,6 +46,7 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index)
{
return 1;
}
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); }
// to solve link errors
double cpuf;
// void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
@@ -624,7 +625,7 @@ int main(int argc, char **argv)
sl_uerx->psbch.rx_ok = 1;
}
} else
psbch_pscch_processing(UE_RX, &proc, &phy_data_rx);
psbch_pscch_pssch_processing(UE_RX, &proc, &phy_data_rx);
} // noise trials

View File

@@ -496,7 +496,7 @@ int main(int argc, char **argv)
if (input_fd == NULL) {
uint8_t ULSCH_ids[] = {0};
nr_ulsch_pre_encoding(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids);
nr_ulsch_encoding(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids);
nr_ulsch_encoding(UE, ulsch_ue, NULL, 0, 0, 0, &G, 1, ULSCH_ids);
}
printf("\n");

View File

@@ -1943,198 +1943,6 @@ static const int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l[12][8] = {
{0, 3072, -1, -1, 3, 1539, -1, -1}, // 14 // (DMRS l' position)
};
// the following tables contain 10 times the value reported in 214 (in line with SCF specification and to avoid fractional values)
//Table 5.1.3.1-1 of 38.214
static const uint16_t Table_51311[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260},
{2, 6020}, {2, 6790}, {4, 3400}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160},
{4, 6580}, {6, 4380}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7190},
{6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480}, {2, 0}, {4, 0}, {6, 0}};
// Table 5.1.3.1-2 of 38.214
static const uint16_t Table_51312[32][2] = {{2, 1200}, {2, 1930}, {2, 3080}, {2, 4490}, {2, 6020}, {4, 3780}, {4, 4340},
{4, 4900}, {4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670},
{6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {8, 6825},
{8, 7110}, {8, 7540}, {8, 7970}, {8, 8410}, {8, 8850}, {8, 9165}, {8, 9480},
{2, 0}, {4, 0}, {6, 0}, {8, 0}};
//Table 5.1.3.1-3 of 38.214
static const uint16_t Table_51313[32][2] = {{2, 300}, {2, 400}, {2, 500}, {2, 640}, {2, 780}, {2, 990}, {2, 1200}, {2, 1570},
{2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260}, {2, 6020}, {4, 3400},
{4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160}, {6, 4380}, {6, 4660}, {6, 5170},
{6, 5670}, {6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {2, 0}, {4, 0}, {6, 0}};
static const uint16_t Table_61411[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490},
{2, 5260}, {2, 6020}, {2, 6790}, {4, 3400}, {4, 3780}, {4, 4340}, {4, 4900},
{4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160},
{6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480},
{2, 0}, {2, 0}, {4, 0}, {6, 0}};
static const uint16_t Table_61412[32][2] = {{2, 300}, {2, 400}, {2, 500}, {2, 640}, {2, 780}, {2, 990}, {2, 1200},
{2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260},
{2, 6020}, {2, 6790}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160},
{4, 6580}, {4, 6990}, {4, 7720}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7720},
{2, 0}, {2, 0}, {4, 0}, {6, 0}};
uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][0]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][0]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][0]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx);
return 0;
}
}
uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][1]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][1]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][1]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx);
return 0;
}
}
uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][0]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][0]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][0]);
break;
case 3:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61411[Imcs][0]);
break;
case 4:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61412[Imcs][0]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx);
return 0;
}
}
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][1]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][1]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][1]);
break;
case 3:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61411[Imcs][1]);
break;
case 4:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61412[Imcs][1]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx);
return 0;
}
}
// Table 5.1.2.2.1-1 38.214
uint8_t getRBGSize(uint16_t bwp_size, long rbg_size_config)
{

View File

@@ -190,13 +190,6 @@ uint32_t nr_compute_tbs(uint16_t Qm,
uint8_t tb_scaling,
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);
/** \brief Computes Q based on I_MCS PDSCH and table_idx for uplink. Implements MCS Tables from 38.214. */
uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx);
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx);
int srs_binomial_sum(int count, int Lmax);
int srs_codebook_nb_res(NR_SRS_Config_t *srs_config);
int srs_non_codebook_nb_res(NR_SRS_Config_t *srs_config);

View File

@@ -334,7 +334,7 @@ static void sl_schedule_rx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_I
} else if (rx_action >= SL_NR_CONFIG_TYPE_RX_PSCCH && rx_action <= SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH) {
// TBD..
} else if (rx_action == SL_NR_CONFIG_TYPE_RX_PSFCH) {
} else if (rx_action == SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH_PSFCH) {
// TBD..
}
@@ -381,7 +381,7 @@ static void sl_schedule_tx_actions(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_I
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH) {
// TBD....
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSFCH) {
} else if (tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH) {
// TBD....
}