From 85aaf3a0bae47cdaa4551ed4cd6aed3306015330 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 9 Jun 2023 16:42:32 +0200 Subject: [PATCH 001/119] upper layers handling of radio link monitoring --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 8 +++ openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 7 ++- .../SIMULATION/NR_PHY/nr_dummy_functions.c | 4 ++ openair2/COMMON/mac_messages_def.h | 1 + openair2/COMMON/mac_messages_types.h | 10 +++- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 - openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 - openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 25 ++++---- openair2/RRC/NR_UE/L2_interface_ue.c | 10 ++++ openair2/RRC/NR_UE/rrc_UE.c | 32 ++++------ openair2/RRC/NR_UE/rrc_defs.h | 5 ++ openair2/RRC/NR_UE/rrc_proto.h | 9 ++- openair2/RRC/NR_UE/rrc_timers_and_constants.c | 60 +++++++++++++++++++ 14 files changed, 136 insertions(+), 41 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index a425d6b0f5..20cc15dda2 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -49,6 +49,12 @@ typedef struct { uint32_t sr; } fapi_nr_uci_pdu_rel15_t; +typedef enum { + RLM_no_monitoring = 0, + RLM_out_of_sync = 1, + RLM_in_sync = 2 +} rlm_t; + typedef struct { uint32_t rsrp; int rsrp_dBm; @@ -56,6 +62,7 @@ typedef struct { uint8_t i1; uint8_t i2; uint8_t cqi; + rlm_t radiolink_monitoring; } fapi_nr_csirs_measurements_t; typedef struct { @@ -125,6 +132,7 @@ typedef struct { uint16_t cell_id; uint16_t ssb_start_subcarrier; short rsrp_dBm; + rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync } fapi_nr_ssb_pdu_t; typedef struct { diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index b38184f453..068e1dacf3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -1006,6 +1006,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t csirs_measurements.i1 = *i1; csirs_measurements.i2 = *i2; csirs_measurements.cqi = cqi; + csirs_measurements.radiolink_monitoring = RLM_no_monitoring; // TODO do be activated in case of RLM based on CSI-RS nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind = {0}; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 5609f7d608..0a71a1fbae 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -159,15 +159,18 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, fapiPbch_t *pbch = (fapiPbch_t *)typeSpecific; memcpy(ssb_pdu->pdu, pbch->decoded_output, sizeof(pbch->decoded_output)); ssb_pdu->additional_bits = pbch->xtra_byte; - ssb_pdu->ssb_index = (frame_parms->ssb_index)&0x7; + ssb_pdu->ssb_index = (frame_parms->ssb_index) & 0x7; ssb_pdu->ssb_length = frame_parms->Lmax; ssb_pdu->cell_id = frame_parms->Nid_cell; ssb_pdu->ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; ssb_pdu->rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; + ssb_pdu->radiolink_monitoring = RLM_in_sync; // TODO to be removed from here ssb_pdu->decoded_pdu = true; } - else + else { + ssb_pdu->radiolink_monitoring = RLM_out_of_sync; // TODO to be removed from here ssb_pdu->decoded_pdu = false; + } } break; case FAPI_NR_CSIRS_IND: diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index 930e0d3840..dccdce2934 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -28,6 +28,10 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) { return 0; } int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { return 0; } +void nr_mac_rrc_sync_ind(const module_id_t module_id, + const frame_t frame, + const bool in_sync) {} + void rrc_data_ind(const protocol_ctxt_t *const ctxt_pP, const rb_id_t Srb_id, const sdu_size_t sdu_sizeP, diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index eeef0d4494..d4a923b90b 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -30,6 +30,7 @@ // Messages between RRC and MAC layers MESSAGE_DEF(RRC_MAC_IN_SYNC_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacInSyncInd, rrc_mac_in_sync_ind) MESSAGE_DEF(RRC_MAC_OUT_OF_SYNC_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacOutOfSyncInd, rrc_mac_out_of_sync_ind) +MESSAGE_DEF(NR_RRC_MAC_SYNC_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSyncInd, nr_rrc_mac_sync_ind) MESSAGE_DEF(RRC_MAC_BCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacBcchDataReq, rrc_mac_bcch_data_req) MESSAGE_DEF(RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacBcchDataInd, rrc_mac_bcch_data_ind) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index 6a671eeb10..fde990b0fe 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -36,13 +36,14 @@ // Defines to access message fields. #define RRC_MAC_IN_SYNC_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_in_sync_ind #define RRC_MAC_OUT_OF_SYNC_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_out_of_sync_ind +#define NR_RRC_MAC_SYNC_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_sync_ind #define RRC_MAC_BCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_req #define RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_ind #define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind -#define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req -#define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind +#define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req +#define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind #define RRC_MAC_CCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_req #define RRC_MAC_CCCH_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_cnf @@ -72,6 +73,11 @@ typedef struct RrcMacInSyncInd_s { typedef RrcMacInSyncInd RrcMacOutOfSyncInd; +typedef struct NRRrcMacSyncInd_s { + uint32_t frame; + bool in_sync; +} NRRrcMacSyncInd; + typedef struct RrcMacBcchDataReq_s { uint32_t frame; uint32_t sdu_size; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 77a0fc8e58..99c7ba6dcd 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -367,12 +367,9 @@ typedef struct { } PUCCH_sched_t; typedef struct { - uint32_t ssb_index; /// SSB RSRP in dBm short ssb_rsrp_dBm; - int consecutive_bch_failures; - } NR_SSB_meas_t; typedef struct NR_UL_TIME_ALIGNMENT { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 2cc400d2d2..22fbef5614 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -269,8 +269,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id, AssertFatal(mac->mib != NULL, "nr_ue_decode_mib() mac->mib == NULL\n"); - mac->ssb_measurements.consecutive_bch_failures = 0; // resetting decoding failures - uint16_t frame = (mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused); uint16_t frame_number_4lsb = 0; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 1459d97dc6..d4d03d408f 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1052,14 +1052,6 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, } -void handle_bch_failure(NR_UE_MAC_INST_t *mac) -{ - mac->ssb_measurements.consecutive_bch_failures++; - //TODO handle this properly by scheduling re-synchronization - AssertFatal(mac->ssb_measurements.consecutive_bch_failures < 100, - "Radio link failure caused by 100 consecutive PBCH detection failures.\n"); -} - // L2 Abstraction Layer int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len){ return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, ack_nack, pduP, pdu_len); @@ -1098,7 +1090,17 @@ int8_t handle_dlsch(nr_downlink_indication_t *dl_info, int pdu_id) return 0; } -int8_t handle_csirs_measurements(module_id_t module_id, frame_t frame, int slot, fapi_nr_csirs_measurements_t *csirs_measurements) { +void handle_rlm(rlm_t rlm_result, int frame, module_id_t module_id) +{ + if (rlm_result == RLM_no_monitoring) + return; + bool is_sync = rlm_result == RLM_in_sync ? true : false; + nr_mac_rrc_sync_ind(module_id, frame, is_sync); +} + +int8_t handle_csirs_measurements(module_id_t module_id, frame_t frame, int slot, fapi_nr_csirs_measurements_t *csirs_measurements) +{ + handle_rlm(csirs_measurements->radiolink_monitoring, frame, module_id); return nr_ue_process_csirs_measurements(module_id, frame, slot, csirs_measurements); } @@ -1197,6 +1199,9 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info) switch(rx_indication_body.pdu_type){ case FAPI_NR_RX_PDU_TYPE_SSB: + handle_rlm(rx_indication_body.ssb_pdu.radiolink_monitoring, + dl_info->frame, + dl_info->module_id); if(rx_indication_body.ssb_pdu.decoded_pdu) { handle_ssb_meas(mac, rx_indication_body.ssb_pdu.ssb_index, @@ -1209,8 +1214,6 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info) rx_indication_body.ssb_pdu.ssb_start_subcarrier, rx_indication_body.ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; } - else - handle_bch_failure(mac); break; case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(dl_info->module_id, diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index ce0b2ff44b..7222defbe4 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -39,6 +39,16 @@ typedef uint32_t channel_t; +void nr_mac_rrc_sync_ind(const module_id_t module_id, + const frame_t frame, + const bool in_sync) +{ + MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SYNC_IND); + NR_RRC_MAC_SYNC_IND (message_p).frame = frame; + NR_RRC_MAC_SYNC_IND (message_p).in_sync = in_sync; + itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); +} + int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index c8d4403094..9d14f19ece 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2264,24 +2264,6 @@ nr_rrc_ue_establish_srb2( return 0; } - -void nr_rrc_handle_timers(unsigned int mod_id) -{ - NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[mod_id].timers_and_constants; - // T304 - if (timers->T304_active == true) { - timers->T304_cnt += 10; - if(timers->T304_cnt >= timers->T304_k) { - // TODO - // For T304 of MCG, in case of the handover from NR or intra-NR - // handover, initiate the RRC re-establishment procedure; - // In case of handover to NR, perform the actions defined in the - // specifications applicable for the source RAT. - } - } -} - - void *rrc_nrue_task(void *args_p) { MessageDef *msg_p; @@ -2308,10 +2290,22 @@ void *rrc_nrue_task(void *args_p) LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); break; + case NR_RRC_MAC_SYNC_IND: + LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n", + ue_mod_id, + ITTI_MSG_NAME (msg_p), + NR_RRC_MAC_SYNC_IND (msg_p).frame); + nr_sync_msg_t sync_msg = NR_RRC_MAC_SYNC_IND (msg_p).in_sync ? + IN_SYNC : OUT_OF_SYNC; + NR_UE_Timers_Constants_t *tac = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants; + handle_rlf_sync(tac, sync_msg); + break; + case NRRRC_SLOT_PROCESS: LOG_D(NR_RRC, "[UE %d] Receided %s: frame %d slot %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NRRRC_SLOT_PROCESS (msg_p).frame, NRRRC_SLOT_PROCESS (msg_p).slot); - nr_rrc_handle_timers(ue_mod_id); + NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants; + nr_rrc_handle_timers(timers); break; case NR_RRC_MAC_BCCH_DATA_IND: diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 996069ad68..28d3c52cef 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -182,6 +182,11 @@ typedef struct NR_UE_Timers_Constants_s { uint32_t T319_k; } NR_UE_Timers_Constants_t; +typedef enum { + OUT_OF_SYNC = 0, + IN_SYNC = 1 +} nr_sync_msg_t; + typedef struct NR_UE_RRC_INST_s { NR_MeasConfig_t *meas_config; diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 418c71240c..f303d809fe 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -113,6 +113,10 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const uint8_t* pduP, const sdu_size_t pdu_len); +void nr_mac_rrc_sync_ind(const module_id_t module_id, + const frame_t frame, + const bool in_sync); + /**\brief \param module_id module id \param CC_id component carrier id @@ -133,8 +137,7 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index); \param void *args_p Pointer on arguments to start the task. */ void *rrc_nrue_task(void *args_p); -/**\brief RRC timers update at UE. */ -void *nr_rrc_timers_update(); +void nr_rrc_handle_timers(NR_UE_Timers_Constants_t *timers); /**\brief RRC NSA UE task. \param void *args_p Pointer on arguments to start the task. */ @@ -162,6 +165,8 @@ void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac); void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac); void nr_rrc_set_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1); void nr_rrc_set_T304(NR_UE_Timers_Constants_t *tac, NR_ReconfigurationWithSync_t *reconfigurationWithSync); +void handle_rlf_sync(NR_UE_Timers_Constants_t *tac, + nr_sync_msg_t sync_msg); void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc, struct NR_SetupRelease_RLF_TimersAndConstants *rlf_TimersAndConstants); diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index f9fc11095b..50c2240339 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -21,6 +21,29 @@ #include "openair2/RRC/NR_UE/rrc_proto.h" +void nr_rrc_handle_timers(NR_UE_Timers_Constants_t *timers) +{ + // T304 + if (timers->T304_active == true) { + timers->T304_cnt += 10; + if(timers->T304_cnt >= timers->T304_k) { + // TODO + // For T304 of MCG, in case of the handover from NR or intra-NR + // handover, initiate the RRC re-establishment procedure; + // In case of handover to NR, perform the actions defined in the + // specifications applicable for the source RAT. + } + } + if (timers->T310_active == true) { + timers->T310_cnt += 10; + if(timers->T310_cnt >= timers->T310_k) { + // TODO + // handle detection of radio link failure + // as described in 5.3.10.3 of 38.331 + AssertFatal(false, "Radio link failure! Not handled yet!\n"); + } + } +} void nr_rrc_set_T304(NR_UE_Timers_Constants_t *tac, NR_ReconfigurationWithSync_t *reconfigurationWithSync) { @@ -402,6 +425,43 @@ void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc, } } +void handle_rlf_sync(NR_UE_Timers_Constants_t *tac, + nr_sync_msg_t sync_msg) +{ + if (sync_msg == IN_SYNC) { + tac->N310_cnt = 0; + if (tac->T310_active) { + tac->N311_cnt++; + // Upon receiving N311 consecutive "in-sync" indications + if (tac->N311_cnt >= tac->N311_k) { + // stop timer T310 + tac->T310_active = false; + tac->T310_cnt = 0; + tac->N311_cnt = 0; + } + } + } + else { + // OUT_OF_SYNC + tac->N311_cnt = 0; + if(tac->T300_active || + tac->T301_active || + tac->T304_active || + tac->T310_active || + tac->T311_active || + tac->T319_active) + return; + tac->N310_cnt++; + // upon receiving N310 consecutive "out-of-sync" indications + if (tac->N310_cnt >= tac->N310_k) { + // start timer T310 + tac->T310_active = true; + tac->T310_cnt = 0; + tac->N310_cnt = 0; + } + } +} + void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac) { // 38.331 9.2.3 Default values timers and constants From a773d024e84204f6fbe0dfbc602541c8afa88fc6 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 19 Jun 2023 09:48:17 +0200 Subject: [PATCH 002/119] no sanitize on generated ldpc code --- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc104_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc112_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc120_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc128_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc144_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc160_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc16_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc176_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc192_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc208_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc224_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc240_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc256_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc288_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc2_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc320_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc32_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc352_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc384_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc4_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc64_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc72_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc80_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc88_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc8_byte.c | 2 +- openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc96_byte.c | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc104_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc104_byte.c index a1e7193db5..2eea416f89 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc104_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc104_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=104, byte encoding -static inline void ldpc_BG2_Zc104_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc104_byte(uint8_t *c,uint8_t *d) { __m64 *csimd=(__m64 *)c,*dsimd=(__m64 *)d; __m64 *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc112_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc112_byte.c index 621cfaad22..8808a1b915 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc112_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc112_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=112, byte encoding -static inline void ldpc_BG2_Zc112_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc112_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc120_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc120_byte.c index 63639822ef..21e79114d0 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc120_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc120_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=120, byte encoding -static inline void ldpc_BG2_Zc120_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc120_byte(uint8_t *c,uint8_t *d) { __m64 *csimd=(__m64 *)c,*dsimd=(__m64 *)d; __m64 *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc128_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc128_byte.c index ad1bc53f1f..f82e92c6b3 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc128_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc128_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=128, byte encoding -static inline void ldpc_BG2_Zc128_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc128_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc144_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc144_byte.c index 59806345c9..1e26b3535d 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc144_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc144_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=144, byte encoding -static inline void ldpc_BG2_Zc144_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc144_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc160_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc160_byte.c index b2f90e62d0..1c95ccb315 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc160_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc160_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=160, byte encoding -static inline void ldpc_BG2_Zc160_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc160_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc16_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc16_byte.c index 9668daaf20..7fb64cfc4c 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc16_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc16_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=16, byte encoding -static inline void ldpc_BG2_Zc16_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc16_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc176_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc176_byte.c index b73e85e18e..090a394d60 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc176_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc176_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=176, byte encoding -static inline void ldpc_BG2_Zc176_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc176_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc192_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc192_byte.c index bc90a35a86..94ac2a3220 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc192_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc192_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=192, byte encoding -static inline void ldpc_BG2_Zc192_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc192_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc208_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc208_byte.c index f9343323bb..3453a2f3d1 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc208_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc208_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=208, byte encoding -static inline void ldpc_BG2_Zc208_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc208_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc224_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc224_byte.c index 8969c624de..4938de2b2a 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc224_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc224_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=224, byte encoding -static inline void ldpc_BG2_Zc224_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc224_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc240_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc240_byte.c index c2004d7645..997a34f198 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc240_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc240_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=240, byte encoding -static inline void ldpc_BG2_Zc240_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc240_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc256_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc256_byte.c index cd86a0ca22..cb7ce41314 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc256_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc256_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=256, byte encoding -static inline void ldpc_BG2_Zc256_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc256_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc288_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc288_byte.c index 9e349d5424..df03405c2d 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc288_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc288_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=288, byte encoding -static inline void ldpc_BG2_Zc288_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc288_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc2_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc2_byte.c index 808be926ee..af7f20ff63 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc2_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc2_byte.c @@ -1,7 +1,7 @@ #include "PHY/sse_intrin.h" #define scalar_xor(a,b) ((a)^(b)) // generated code for Zc=2, byte encoding -static inline void ldpc_BG2_Zc2_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc2_byte(uint8_t *c,uint8_t *d) { uint8_t *csimd=(uint8_t *)c,*dsimd=(uint8_t *)d; uint8_t *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc320_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc320_byte.c index 2fcdf136fc..29a977a3de 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc320_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc320_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=320, byte encoding -static inline void ldpc_BG2_Zc320_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc320_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc32_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc32_byte.c index 6356cfb391..5b983af26c 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc32_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc32_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=32, byte encoding -static inline void ldpc_BG2_Zc32_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc32_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc352_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc352_byte.c index 7141d91aa9..4fc2acf610 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc352_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc352_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=352, byte encoding -static inline void ldpc_BG2_Zc352_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc352_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc384_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc384_byte.c index b61f7500a8..ea87348f28 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc384_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc384_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=384, byte encoding -static inline void ldpc_BG2_Zc384_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc384_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc4_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc4_byte.c index 06c0838b00..8938311339 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc4_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc4_byte.c @@ -1,7 +1,7 @@ #include "PHY/sse_intrin.h" #define scalar_xor(a,b) ((a)^(b)) // generated code for Zc=4, byte encoding -static inline void ldpc_BG2_Zc4_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc4_byte(uint8_t *c,uint8_t *d) { uint8_t *csimd=(uint8_t *)c,*dsimd=(uint8_t *)d; uint8_t *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc64_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc64_byte.c index 5ab2a77edb..0ae044b3a2 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc64_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc64_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=64, byte encoding -static inline void ldpc_BG2_Zc64_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc64_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc72_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc72_byte.c index e49f7afc19..4d2e586106 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc72_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc72_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=72, byte encoding -static inline void ldpc_BG2_Zc72_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc72_byte(uint8_t *c,uint8_t *d) { __m64 *csimd=(__m64 *)c,*dsimd=(__m64 *)d; __m64 *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc80_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc80_byte.c index 2df111360f..de7b5b06ef 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc80_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc80_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=80, byte encoding -static inline void ldpc_BG2_Zc80_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc80_byte(uint8_t *c,uint8_t *d) { __m128i *csimd=(__m128i *)c,*dsimd=(__m128i *)d; __m128i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc88_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc88_byte.c index 29f71426cc..8dfd2d92c6 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc88_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc88_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=88, byte encoding -static inline void ldpc_BG2_Zc88_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc88_byte(uint8_t *c,uint8_t *d) { __m64 *csimd=(__m64 *)c,*dsimd=(__m64 *)d; __m64 *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc8_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc8_byte.c index aba4440d2b..0a65a40334 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc8_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc8_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=8, byte encoding -static inline void ldpc_BG2_Zc8_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc8_byte(uint8_t *c,uint8_t *d) { __m64i *csimd=(__m64i *)c,*dsimd=(__m64i *)d; __m64i *c2,*d2; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc96_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc96_byte.c index a4d5a47ef4..5b40d902a2 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc96_byte.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_BG2_Zc96_byte.c @@ -1,6 +1,6 @@ #include "PHY/sse_intrin.h" // generated code for Zc=96, byte encoding -static inline void ldpc_BG2_Zc96_byte(uint8_t *c,uint8_t *d) { +static inline __attribute__ ((no_sanitize("address", "undefined"))) void ldpc_BG2_Zc96_byte(uint8_t *c,uint8_t *d) { __m256i *csimd=(__m256i *)c,*dsimd=(__m256i *)d; __m256i *c2,*d2; From 35b3a6d47825598139d1380b83456c2f340c34bb Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 19 Jun 2023 10:30:32 +0200 Subject: [PATCH 003/119] bugfix in ul rotation and formatting --- openair1/PHY/MODULATION/slot_fep_nr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 43d7be3fa3..a3224944ac 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -318,17 +318,16 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, int nsymb, int link_type) { - int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; + int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; - for (int symbol=first_symbol;symbolsymbol_rotation[link_type][symbol + symb_offset]; - rot2.i=-rot2.i; - LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,rot2.r,rot2.i); - + rot2.i = -rot2.i; + LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i); c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; - c16_t *this_symbol = &rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)]; + c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)]; if (frame_parms->N_RB_UL & 1) { rotate_cpx_vector(this_symbol, &rot2, this_symbol, From 74ae831cf978a3eaeb6e7b55aad8f373193b7c8b Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 20 Jun 2023 09:21:45 +0200 Subject: [PATCH 004/119] nr sib1: add mandatory fields for FDD --- openair2/RRC/NR/nr_rrc_config.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 2a817ff376..3623a13d99 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -1893,6 +1893,23 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const gNB_RrcConfigurationReq *configurati asn1cCallocOne(UL->frequencyInfoUL.p_Max, *frequencyInfoUL->p_Max); + frame_type_t frame_type = + get_frame_type((int)*configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], + *configuration->scc->ssbSubcarrierSpacing); + + if (frame_type == FDD) { + UL->frequencyInfoUL.absoluteFrequencyPointA = malloc(sizeof(*UL->frequencyInfoUL.absoluteFrequencyPointA)); + AssertFatal(UL->frequencyInfoUL.absoluteFrequencyPointA != NULL, "out of memory\n"); + *UL->frequencyInfoUL.absoluteFrequencyPointA = + *configuration->scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA; + UL->frequencyInfoUL.frequencyBandList = calloc(1, sizeof(*UL->frequencyInfoUL.frequencyBandList)); + AssertFatal(UL->frequencyInfoUL.frequencyBandList != NULL, "out of memory\n"); + for (int i = 0; i < frequencyInfoUL->frequencyBandList->list.count; i++) { + asn1cSequenceAdd(UL->frequencyInfoUL.frequencyBandList->list, struct NR_NR_MultiBandInfo, nrMultiBandInfo); + nrMultiBandInfo->freqBandIndicatorNR = frequencyInfoUL->frequencyBandList->list.array[i]; + } + } + UL->initialUplinkBWP.genericParameters = configuration->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; UL->initialUplinkBWP.rach_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; UL->initialUplinkBWP.pusch_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; From 1c3058e2d2a7f6c59f4542e6e06be647623bc892 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 19 Jun 2023 17:36:33 +0200 Subject: [PATCH 005/119] use of apply_rotation functions also at UE --- doc/SW-archi-graph.md | 4 +- doc/SW_archi.md | 4 +- executables/nr-gnb.c | 15 +++-- openair1/PHY/MODULATION/nr_modulation.h | 21 +++--- openair1/PHY/MODULATION/ofdm_mod.c | 28 ++++---- openair1/PHY/MODULATION/slot_fep_nr.c | 77 +++++++--------------- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 50 ++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 8 ++- openair1/SIMULATION/NR_PHY/pbchsim.c | 26 ++++---- openair1/SIMULATION/NR_PHY/ulsim.c | 7 +- 10 files changed, 102 insertions(+), 138 deletions(-) diff --git a/doc/SW-archi-graph.md b/doc/SW-archi-graph.md index d397d07f43..a3397ed297 100644 --- a/doc/SW-archi-graph.md +++ b/doc/SW-archi-graph.md @@ -14,7 +14,7 @@ rx_func_implem[rx_func] handle_nr_slot_ind --> rnti_to_remove-mgmt --> L1_nr_prach_procedures - --> apply_nr_rotation_ul + --> apply_nr_rotation_RX end subgraph phy_procedures_gNB_uespec_RX fill_ul_rb_mask @@ -58,7 +58,7 @@ subgraph tx_func subgraph phy_procedures_gNB_TX dcitop[nr_generate dci top] --> nr_generate_csi_rs - --> apply_nr_rotation + --> apply_nr_rotation_TX -- send_msg --> end_tx_func((L1_tx_out)) end subgraph tx_reorder_thread diff --git a/doc/SW_archi.md b/doc/SW_archi.md index cccead370b..7facfcb595 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -33,7 +33,7 @@ rx_func_implem[rx_func] handle_nr_slot_ind --> rnti_to_remove-mgmt --> L1_nr_prach_procedures - --> apply_nr_rotation_ul + --> apply_nr_rotation_RX end subgraph phy_procedures_gNB_uespec_RX fill_ul_rb_mask @@ -67,7 +67,7 @@ subgraph tx phy_procedures_gNB_TX --> dcitop[nr_generate dci top] --> nr_generate_csi_rs - --> apply_nr_rotation + --> apply_nr_rotation_TX -- send_msg --> end_tx_func((L1_tx_out)) end subgraph tx_reorder_thread diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index f0da3db241..fd5439ce74 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -231,13 +231,16 @@ void rx_func(void *param) //WA: comment rotation in tx/rx if((gNB->num_RU == 1) && (gNB->RU_list[0]->if_south != REMOTE_IF4p5)) { //apply the rx signal rotation here + int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { - apply_nr_rotation_ul(&gNB->frame_parms, - gNB->common_vars.rxdataF[aa], - slot_rx, - 0, - gNB->frame_parms.Ncp == EXTENDED ? 12 : 14, - link_type_ul); + apply_nr_rotation_RX(&gNB->frame_parms, + gNB->common_vars.rxdataF[aa], + gNB->frame_parms.symbol_rotation[1], + slot_rx, + gNB->frame_parms.N_RB_UL, + soffset, + 0, + gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); } } phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx); diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 09f6c94d2c..8c530676cd 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -108,23 +108,26 @@ int nr_beam_precoding(c16_t **txdataF, int offset ); -void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, - c16_t* txdata, - int slot, - int first_symbol, - int nsymb, - int link_type); +void apply_nr_rotation_TX(NR_DL_FRAME_PARMS *fp, + c16_t *txdataF, + c16_t *symbol_rotation, + int slot, + int nb_rb, + int first_symbol, + int nsymb); void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp); -void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, +void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms, c16_t *rxdataF, + c16_t *rot, int slot, + int nb_rb, + int soffset, int first_symbol, - int nsymb, - int link_type); + int nsymb); /*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5 @param[in] datatx_F_precoding, Pointer to n_layers*re data array diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 16238257d1..45261b1fdb 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -334,17 +334,17 @@ void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_s } -void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, - c16_t *txdataF, - int slot, - int first_symbol, - int nsymb, - int link_type) +void apply_nr_rotation_TX(NR_DL_FRAME_PARMS *fp, + c16_t *txdataF, + c16_t *symbol_rotation, + int slot, + int nb_rb, + int first_symbol, + int nsymb) { - int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot; + int symb_offset = (slot % fp->slots_per_subframe) * fp->symbols_per_slot; - c16_t *symbol_rotation = fp->symbol_rotation[link_type] + symb_offset; - int N_RB = (link_type == link_type_sl) ? fp->N_RB_SL : fp->N_RB_DL; + symbol_rotation += symb_offset; for (int sidx = first_symbol; sidx < first_symbol + nsymb; sidx++) { c16_t *this_rotation = symbol_rotation + sidx; @@ -357,20 +357,20 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, this_rotation->r, this_rotation->i); - if (N_RB & 1) { + if (nb_rb & 1) { rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - (N_RB + 1) * 6, 15); + (nb_rb + 1) * 6, 15); rotate_cpx_vector(this_symbol + fp->first_carrier_offset - 6, this_rotation, this_symbol + fp->first_carrier_offset - 6, - (N_RB + 1) * 6, 15); + (nb_rb + 1) * 6, 15); } else { rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - N_RB * 6, 15); + nb_rb * 6, 15); rotate_cpx_vector(this_symbol + fp->first_carrier_offset, this_rotation, this_symbol + fp->first_carrier_offset, - N_RB * 6, 15); + nb_rb * 6, 15); } } } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index a3224944ac..6a598582b0 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -96,46 +96,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, stop_meas(&ue->rx_dft_stats); - int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - c16_t rot2 = frame_parms->symbol_rotation[0][symbol+symb_offset]; - rot2.i=-rot2.i; - -#ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, - symbol+symb_offset,rot2.r,rot2.i); -#endif - - c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; - c16_t *this_symbol = &rxdataF[aa][frame_parms->ofdm_symbol_size*symbol]; - - if (frame_parms->N_RB_DL & 1) { - rotate_cpx_vector(this_symbol, &rot2, this_symbol, - (frame_parms->N_RB_DL + 1) * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, - &rot2, - this_symbol + frame_parms->first_carrier_offset - 6, - (frame_parms->N_RB_DL + 1) * 6, 15); - multadd_cpx_vector((int16_t *)this_symbol, (int16_t *)shift_rot, (int16_t *)this_symbol, - 1, (frame_parms->N_RB_DL + 1) * 6, 15); - multadd_cpx_vector((int16_t *)(this_symbol + frame_parms->first_carrier_offset - 6), - (int16_t *)(shift_rot + frame_parms->first_carrier_offset - 6), - (int16_t *)(this_symbol + frame_parms->first_carrier_offset - 6), - 1, (frame_parms->N_RB_DL + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, &rot2, this_symbol, - frame_parms->N_RB_DL * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, - &rot2, - this_symbol + frame_parms->first_carrier_offset, - frame_parms->N_RB_DL * 6, 15); - multadd_cpx_vector((int16_t *)this_symbol, (int16_t *)shift_rot, (int16_t *)this_symbol, - 1, frame_parms->N_RB_DL * 6, 15); - multadd_cpx_vector((int16_t *)(this_symbol + frame_parms->first_carrier_offset), - (int16_t *)(shift_rot + frame_parms->first_carrier_offset), - (int16_t *)(this_symbol + frame_parms->first_carrier_offset), - 1, frame_parms->N_RB_DL * 6, 15); - } + apply_nr_rotation_RX(frame_parms, + rxdataF[aa], + frame_parms->symbol_rotation[0], + Ns, + frame_parms->N_RB_DL, + 0, + symbol, + 1); } #ifdef DEBUG_FEP @@ -311,50 +279,51 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, return 0; } -void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, +void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms, c16_t *rxdataF, + c16_t *rot, int slot, + int nb_rb, + int soffset, int first_symbol, - int nsymb, - int link_type) + int nsymb) { int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; - int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; for (int symbol = first_symbol; symbol < first_symbol + nsymb; symbol++) { - c16_t rot2 = frame_parms->symbol_rotation[link_type][symbol + symb_offset]; + c16_t rot2 = rot[symbol + symb_offset]; rot2.i = -rot2.i; LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i); c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)]; - if (frame_parms->N_RB_UL & 1) { + if (nb_rb & 1) { rotate_cpx_vector(this_symbol, &rot2, this_symbol, - (frame_parms->N_RB_UL + 1) * 6, 15); + (nb_rb + 1) * 6, 15); rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, &rot2, this_symbol + frame_parms->first_carrier_offset - 6, - (frame_parms->N_RB_UL + 1) * 6, 15); + (nb_rb + 1) * 6, 15); multadd_cpx_vector((int16_t *)this_symbol, (int16_t *)shift_rot, (int16_t *)this_symbol, - 1, (frame_parms->N_RB_UL+1) * 6, 15); + 1, (nb_rb + 1) * 6, 15); multadd_cpx_vector((int16_t *)(this_symbol + frame_parms->first_carrier_offset - 6), (int16_t *)(shift_rot + frame_parms->first_carrier_offset - 6), (int16_t *)(this_symbol + frame_parms->first_carrier_offset - 6), - 1, (frame_parms->N_RB_UL+1) * 6, 15); + 1, (nb_rb + 1) * 6, 15); } else { rotate_cpx_vector(this_symbol, &rot2, this_symbol, - frame_parms->N_RB_UL * 6, 15); + nb_rb * 6, 15); rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, &rot2, this_symbol + frame_parms->first_carrier_offset, - frame_parms->N_RB_UL * 6, 15); + nb_rb * 6, 15); multadd_cpx_vector((int16_t *)this_symbol, (int16_t *)shift_rot, (int16_t *)this_symbol, - 1, frame_parms->N_RB_UL * 6, 15); + 1, nb_rb * 6, 15); multadd_cpx_vector((int16_t *)(this_symbol + frame_parms->first_carrier_offset), (int16_t *)(shift_rot + frame_parms->first_carrier_offset), (int16_t *)(this_symbol + frame_parms->first_carrier_offset), - 1, frame_parms->N_RB_UL * 6, 15); + 1, nb_rb * 6, 15); } } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 186ec58d4d..b27b738523 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -592,16 +592,12 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, uint8_t slot, NR_DL_FRAME_PARMS *frame_parms, - uint8_t n_antenna_ports) { - - int tx_offset, ap; - c16_t **txdata; - c16_t **txdataF; - + uint8_t n_antenna_ports) +{ /////////////////////////IFFT/////////////////////// /////////// - tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); + int tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); // clear the transmit data array for the current subframe /*for (int aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -610,38 +606,20 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, }*/ - txdata = UE->common_vars.txdata; - txdataF = UE->common_vars.txdataF; + c16_t **txdata = UE->common_vars.txdata; + c16_t **txdataF = UE->common_vars.txdataF; - int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - for(ap = 0; ap < n_antenna_ports; ap++) { - for (int s=0;sofdm_symbol_size * s]; - c16_t rot=frame_parms->symbol_rotation[link_type_ul][s + symb_offset]; - LOG_D(PHY,"rotating txdataF symbol %d (%d) => (%d.%d)\n", - s, - s + symb_offset, - rot.r, rot.i); - - if (frame_parms->N_RB_UL & 1) { - rotate_cpx_vector(this_symbol, &rot, this_symbol, - (frame_parms->N_RB_UL + 1) * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, - &rot, - this_symbol + frame_parms->first_carrier_offset - 6, - (frame_parms->N_RB_UL + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, &rot, this_symbol, - frame_parms->N_RB_UL * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, - &rot, - this_symbol + frame_parms->first_carrier_offset, - frame_parms->N_RB_UL * 6, 15); - } - } + for(int ap = 0; ap < n_antenna_ports; ap++) { + apply_nr_rotation_TX(frame_parms, + txdataF[ap], + frame_parms->symbol_rotation[1], + slot, + frame_parms->N_RB_UL, + 0, + NR_NUMBER_OF_SYMBOLS_PER_SLOT); } - for (ap = 0; ap < n_antenna_ports; ap++) { + for (int ap = 0; ap < n_antenna_ports; ap++) { if (frame_parms->Ncp == 1) { // extended cyclic prefix PHY_ofdm_mod((int *)txdataF[ap], (int *)&txdata[ap][tx_offset], diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index d7e9969065..d92c0124f1 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -222,7 +222,13 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, //apply the OFDM symbol rotation here for (aa=0; aacarrier_config.num_tx_ant.value; aa++) { - apply_nr_rotation(fp, &gNB->common_vars.txdataF[aa][txdataF_offset], slot, 0, fp->Ncp == EXTENDED ? 12 : 14, link_type_dl); + apply_nr_rotation_TX(fp, + &gNB->common_vars.txdataF[aa][txdataF_offset], + fp->symbol_rotation[0], + slot, + fp->N_RB_DL, + 0, + fp->Ncp == EXTENDED ? 12 : 14); T(T_GNB_PHY_DL_OUTPUT_SIGNAL, T_INT(0), T_INT(frame), T_INT(slot), diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index d5930c0c23..9299cd4073 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -648,12 +648,13 @@ int main(int argc, char **argv) for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (cyclic_prefix_type == 1) { - apply_nr_rotation(frame_parms, - gNB->common_vars.txdataF[aa], - slot, - 0, - 12, - link_type_dl); + apply_nr_rotation_TX(frame_parms, + gNB->common_vars.txdataF[aa], + frame_parms->symbol_rotation[0], + slot, + frame_parms->N_RB_DL, + 0, + 12); PHY_ofdm_mod((int *)gNB->common_vars.txdataF[aa], (int *)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], @@ -662,12 +663,13 @@ int main(int argc, char **argv) frame_parms->nb_prefix_samples, CYCLIC_PREFIX); } else { - apply_nr_rotation(frame_parms, - gNB->common_vars.txdataF[aa], - slot, - 0, - 14, - link_type_dl); + apply_nr_rotation_TX(frame_parms, + gNB->common_vars.txdataF[aa], + frame_parms->symbol_rotation[0], + slot, + frame_parms->N_RB_DL, + 0, + 14); /*nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], &txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index f686ce8201..41e80cc7d4 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1259,11 +1259,14 @@ int main(int argc, char **argv) slot, 0); } - + int offset = (slot & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { - apply_nr_rotation_ul(&gNB->frame_parms, + apply_nr_rotation_RX(&gNB->frame_parms, gNB->common_vars.rxdataF[aa], + gNB->frame_parms.symbol_rotation[1], slot, + gNB->frame_parms.N_RB_UL, + offset, 0, gNB->frame_parms.Ncp == EXTENDED ? 12 : 14, link_type_ul); From 6c6095fc06284a8e9d992401407e37ac0827ad43 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 20 Jun 2023 11:36:52 +0200 Subject: [PATCH 006/119] fixing a typo in band 41 sync raster matrix --- openair2/GNB_APP/gnb_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 1d4a14ad8d..f5ce7121cc 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -114,7 +114,7 @@ const sync_raster_t sync_raster[] = { {39, 0, 4706, 1, 4795}, {40, 0, 5756, 1, 5995}, {41, 0, 6246, 3, 6717}, - {41, 1, 6254, 3, 6714}, + {41, 1, 6252, 3, 6714}, {50, 0, 3584, 1, 3787}, {51, 0, 3572, 1, 3574}, {66, 0, 5279, 1, 5494}, @@ -1162,7 +1162,7 @@ void check_ssb_raster(uint64_t freq, int band, int scs) gscn, freq, band); int rel_gscn = gscn - start_gscn; AssertFatal(rel_gscn % step_gscn == 0, - "GSCN %d corresponding to SSB freqyency %lu not in accordance with GSCN step for band %d\n", + "GSCN %d corresponding to SSB frequency %lu not in accordance with GSCN step for band %d\n", gscn, freq, band); } From 7d08b0c06d179f9b8a245ec94aa9590f5e861ad1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 19 Jun 2023 17:45:11 +0200 Subject: [PATCH 007/119] add assertion in rotation function --- openair1/PHY/MODULATION/slot_fep_nr.c | 3 +++ openair1/SIMULATION/NR_PHY/ulsim.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 6a598582b0..c8ec74d61f 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -288,6 +288,9 @@ void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms, int first_symbol, int nsymb) { + AssertFatal(first_symbol + nsymb <= NR_NUMBER_OF_SYMBOLS_PER_SLOT, + "First symbol %d and number of symbol %d not compatible with number of symbols in a slot %d\n", + first_symbol, nsymb, NR_NUMBER_OF_SYMBOLS_PER_SLOT); int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; for (int symbol = first_symbol; symbol < first_symbol + nsymb; symbol++) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 41e80cc7d4..53c691afa3 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1268,8 +1268,7 @@ int main(int argc, char **argv) gNB->frame_parms.N_RB_UL, offset, 0, - gNB->frame_parms.Ncp == EXTENDED ? 12 : 14, - link_type_ul); + gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); } ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot); From ab1cff7220406b713c4b4349e6efb1042e12b9aa Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Tue, 20 Jun 2023 14:31:19 +0100 Subject: [PATCH 008/119] Tutorials: Update docker install to the latest instructions on the official website --- doc/NR_SA_Tutorial_OAI_CN5G.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/NR_SA_Tutorial_OAI_CN5G.md b/doc/NR_SA_Tutorial_OAI_CN5G.md index 8573391b67..5e6ad3fdbb 100644 --- a/doc/NR_SA_Tutorial_OAI_CN5G.md +++ b/doc/NR_SA_Tutorial_OAI_CN5G.md @@ -32,11 +32,14 @@ Minimum hardware requirements: ```bash sudo apt install -y git net-tools putty -sudo apt install -y apt-transport-https ca-certificates curl software-properties-common -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - -sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" +# https://docs.docker.com/engine/install/ubuntu/ +sudo apt install -y ca-certificates curl gnupg +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update -sudo apt install -y docker docker-ce +sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # Add your username to the docker group, otherwise you will have to run in sudo mode. sudo usermod -a -G docker $(whoami) From bdc445f766638bd30a349c6e790ef4009f4458fc Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 20 Jun 2023 18:50:50 +0200 Subject: [PATCH 009/119] bugfix in RAR time allocation at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 71bb875af4..da7207f7ed 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -4083,7 +4083,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id) // MCS rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); // time alloc - rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); + rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x0f); // frequency alloc rar_grant.Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); // frequency hopping From 2922ea5176d1ceb161f34cacd457473c6de02e68 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 21 Jun 2023 11:11:12 +0200 Subject: [PATCH 010/119] fix also on gnb side --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index d2b9f2331e..e0c5879e9c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2224,7 +2224,7 @@ static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfa int mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); // time alloc - int Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); + int Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x0f); // frequency alloc int Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); // frequency hopping From 93d6ae6d861d7faa3cace068292d5849bdc29ff9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 29 May 2023 11:27:48 +0200 Subject: [PATCH 011/119] making CSI-RS RRC configuration independent from UE --- openair2/RRC/NR/nr_rrc_config.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 2a817ff376..a9d10a885c 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -140,11 +140,12 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) return bitmap; } -static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int uid, int nb_slots_per_period, int nb_dl_slots_period) +static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int id, int nb_slots_per_period, int nb_dl_slots_period) { nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); - const int ideal_period = nb_slots_per_period * MAX_MOBILES_PER_GNB; - const int offset = nb_slots_per_period * uid; + // TODO ideal period to be set according to estimation by the gNB on how fast the channel changes + const int ideal_period = 320; + const int offset = nb_slots_per_period * id; if (ideal_period < 5) { nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots4; @@ -184,14 +185,13 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int uid, in } else { nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; - AssertFatal(offset / 320 < nb_dl_slots_period, "Cannot allocate %dth UE. Not enough resources for CSI-RS\n", uid); + AssertFatal(offset / 320 < nb_dl_slots_period, "Cannot allocate CSI-RS for BWP %d. Not enough resources for CSI-RS\n", id); nzpcsi0->periodicityAndOffset->choice.slots320 = (offset % 320) + (offset / 320); } } static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_CSI_MeasConfig_t *csi_MeasConfig, - int uid, int num_dl_antenna_ports, int curr_bwp, int do_csirs, @@ -266,7 +266,7 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco nzpcsi0->powerControlOffsetSS = calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; - set_csirs_periodicity(nzpcsi0, uid, nb_slots_per_period, nb_dl_slots_period); + set_csirs_periodicity(nzpcsi0, id, nb_slots_per_period, nb_dl_slots_period); nzpcsi0->qcl_InfoPeriodicCSI_RS = calloc(1,sizeof(*nzpcsi0->qcl_InfoPeriodicCSI_RS)); *nzpcsi0->qcl_InfoPeriodicCSI_RS = 0; asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); @@ -2226,7 +2226,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, bwp_id = bwp->bwp_Id; } - config_csirs(scc, csi_MeasConfig, uid, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, bwp_loop); + config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, bwp_loop); config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, bwp_loop); NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1)); @@ -2780,7 +2780,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]; int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - config_csirs(servingcellconfigcommon, csi_MeasConfig, uid, dl_antenna_ports, curr_bwp, do_csirs, bwp_loop); + config_csirs(servingcellconfigcommon, csi_MeasConfig, dl_antenna_ports, curr_bwp, do_csirs, bwp_loop); config_csiim(do_csirs, dl_antenna_ports, curr_bwp, csi_MeasConfig, bwp_loop); if (do_csirs) { From 7a4dc635755a3d3911b315feae1ab233e90017d7 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Fri, 23 Jun 2023 08:43:04 +0100 Subject: [PATCH 012/119] Avoid segmentation fault when optional IE nAS_PDU is NULL --- openair3/NGAP/ngap_gNB_handlers.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 64b29247aa..f548ed4b42 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -763,7 +763,9 @@ static int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, uint32_t s NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i]; msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID; - allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU); + if (item_p->nAS_PDU) { + allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU); + } allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer); } } From 0965e86aca07c3091eab8755f6c83f6c4d20b202 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 15 Jun 2023 16:49:11 +0200 Subject: [PATCH 013/119] schedule CSI-RS only once per BWP --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 18 ++++++++++++------ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 3f1ea001b3..0d213c6826 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -60,7 +60,7 @@ const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); // Use special TDA in case of CSI-RS - if(nrmac->UE_info.sched_csirs) + if(nrmac->UE_info.sched_csirs > 0) return 1; if (tdd && tdd->nrofDownlinkSymbols > 1) { // if there is a mixed slot where we can transmit DL diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f60e79dd11..68a44fa0cf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2552,18 +2552,23 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map; - UE_info->sched_csirs = false; + UE_info->sched_csirs = 0; UE_iterator(UE_info->list, UE) { + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + // CSI-RS is common to all UEs in a given BWP + // therefore we need to schedule only once per BWP + // the following condition verifies if CSI-RS + // has been already scheduled in this BWP + if (UE_info->sched_csirs & (1 << dl_bwp->bwp_id)) + continue; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; if (sched_ctrl->rrc_processing_timer > 0) { continue; } - NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; - NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - if (!ul_bwp->csi_MeasConfig) continue; NR_CSI_MeasConfig_t *csi_measconfig = ul_bwp->csi_MeasConfig; @@ -2598,8 +2603,9 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo if((frame*n_slots_frame+slot-offset)%period == 0) { - LOG_D(NR_MAC,"Scheduling CSI-RS in frame %d slot %d Resource ID %ld\n",frame,slot,nzpcsi->nzp_CSI_RS_ResourceId); - UE_info->sched_csirs = true; + LOG_D(NR_MAC,"Scheduling CSI-RS in frame %d slot %d Resource ID %ld\n", + frame, slot, nzpcsi->nzp_CSI_RS_ResourceId); + UE_info->sched_csirs |= (1 << dl_bwp->bwp_id); nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 7db2225da8..4e30c74a5c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -691,7 +691,8 @@ typedef struct { // last element always NULL pthread_mutex_t mutex; NR_UE_info_t *list[MAX_MOBILES_PER_GNB+1]; - bool sched_csirs; + // bitmap of CSI-RS already scheduled in current slot + int sched_csirs; uid_allocator_t uid_allocator; } NR_UEs_t; From aed0cfe2af9d7926d4dad08693ff20164439a12b Mon Sep 17 00:00:00 2001 From: Daniel Andrade Date: Fri, 23 Jun 2023 14:31:43 +0100 Subject: [PATCH 014/119] Bugfix for getting band and numerology from command line for OAI UE --- executables/nr-uesoftmodem.c | 2 +- executables/softmodem-common.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 7896e57145..f2420641fd 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -513,7 +513,7 @@ int main( int argc, char **argv ) { NR_UE_MAC_INST_t *mac = get_mac_inst(0); if (get_softmodem_params()->sa) { // set frame config to initial values from command line and assume that the SSB is centered on the grid - uint16_t nr_band = get_band(downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]); + uint16_t nr_band = get_softmodem_params()->band; mac->nr_band = nr_band; nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms, downlink_frequency[CC_id][0], diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 1f37c9bdea..9f792b158c 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -162,8 +162,8 @@ extern int usrp_tx_thread; {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, .uptr=&do_forms, .defintval=0, TYPE_UINT, 0}, \ {"dqt" , CONFIG_HLP_SOFTS_QT, PARAMFLAG_BOOL, .uptr=&do_forms_qt, .defintval=0, TYPE_UINT, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, .iptr=&opp_enabled, .defintval=0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, .iptr=&NUMEROLOGY, .defintval=1, TYPE_INT, 0}, \ - {"band" , CONFIG_HLP_BAND, PARAMFLAG_BOOL, .iptr=&BAND, .defintval=78, TYPE_INT, 0}, \ + {"numerology" , CONFIG_HLP_NUMEROLOGY, 0, .iptr=&NUMEROLOGY, .defintval=1, TYPE_INT, 0}, \ + {"band" , CONFIG_HLP_BAND, 0, .iptr=&BAND, .defintval=78, TYPE_INT, 0}, \ {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, .iptr=&EMULATE_RF, .defintval=0, TYPE_INT, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, .strptr=¶llel_config, .defstrval=NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, .strptr=&worker_config, .defstrval=NULL, TYPE_STRING, 0}, \ From 26a69234b2d3efc443c5c74853a6327e61574791 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 13 Jun 2023 11:04:38 +0200 Subject: [PATCH 015/119] Fix UB problems in F1: right TEID conversion, which is unsigned --- openair2/F1AP/f1ap_common.c | 2 +- openair2/F1AP/f1ap_cu_ue_context_management.c | 4 ++-- openair2/F1AP/f1ap_du_rrc_message_transfer.c | 2 +- openair2/F1AP/f1ap_du_ue_context_management.c | 4 ++-- openair3/UTILS/conversions.h | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openair2/F1AP/f1ap_common.c b/openair2/F1AP/f1ap_common.c index 862e701b6d..f417a1c337 100644 --- a/openair2/F1AP/f1ap_common.c +++ b/openair2/F1AP/f1ap_common.c @@ -36,7 +36,7 @@ static f1ap_cudu_inst_t *f1_du_inst[NUMBER_OF_gNB_MAX]= {0}; static f1ap_cudu_inst_t *f1_cu_inst[NUMBER_OF_gNB_MAX]= {0}; uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_mod_idP) { - static uint8_t transaction_identifier[NUMBER_OF_gNB_MAX]; + static uint8_t transaction_identifier[NUMBER_OF_gNB_MAX] = {0}; transaction_identifier[mod_idP+cu_mod_idP] = (transaction_identifier[mod_idP+cu_mod_idP] + 1) % F1AP_TRANSACTION_IDENTIFIER_NUMBER; return transaction_identifier[mod_idP+cu_mod_idP]; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index a38dd7c68f..8fdee52abb 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -693,7 +693,7 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); + OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(CUtype, instance)->gtpInst, f1ap_ue_context_setup_resp->rnti, (ebi_t)drbs_setup_item_p->dRBID, @@ -1654,7 +1654,7 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); + OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(CUtype, instance)->gtpInst, f1ap_ue_context_modification_resp->rnti, (ebi_t)drbs_setupmod_item_p->dRBID, diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 997105d92a..5fc8daef3f 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -219,7 +219,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instanceP, ie6->id = F1AP_ProtocolIE_ID_id_TransactionID; ie6->criticality = F1AP_Criticality_ignore; ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID; - ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(f1ap_req(false, instanceP)->gNB_DU_id, f1ap_req(false, instanceP)->gNB_DU_id); + ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index ccd3381e95..05833e3fad 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -161,7 +161,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); + OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); // 3GPP assumes GTP-U is on port 2152, but OAI is configurable drb_p->up_ul_tnl[0].port=getCxt(false,instance)->setupReq.CUport; @@ -877,7 +877,7 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, uint32_t asso F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); + OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); // 3GPP assumes GTP-U is on port 2152, but OAI is configurable drb_p->up_ul_tnl[0].port=getCxt(false,instance)->setupReq.CUport; diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index 2c544c94e0..bf24c9f4ee 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -119,10 +119,10 @@ do { \ /* Convert an array of char containing vALUE to x */ #define BUFFER_TO_UINT32(buf, x) \ do { \ - x = (((uint32_t)(buf)[0] << 24) | \ - (uint32_t)((buf)[1] << 16) | \ - (uint32_t)((buf)[2] << 8) | \ - (uint32_t)((buf)[3]); \ + x = (((uint32_t)((buf)[0])) << 24) | \ + (((uint32_t)((buf)[1])) << 16) | \ + (((uint32_t)((buf)[2])) << 8) | \ + (((uint32_t)((buf)[3]))); \ } while (0) /* Convert an integer on 32 bits to an octet string from aSN1c tool */ From 7d9b4db58036c25470601657863a44e62d3a22bd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 26 Jun 2023 11:23:52 +0200 Subject: [PATCH 016/119] Correctly copy in_addr for GTP F1 tunnel update --- openair2/RRC/NR/cucp_cuup_direct.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index 4591537304..347e9fbff5 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -85,16 +85,13 @@ void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t insta for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) { DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j; - transport_layer_addr_t newRemoteAddr; - newRemoteAddr.length = 32; // IPv4 - memcpy(newRemoteAddr.buffer, - &drb_p->DlUpParamList[0].tlAddress, - sizeof(in_addr_t)); + in_addr_t addr = {0}; + memcpy(&addr, &drb_p->DlUpParamList[0].tlAddress, sizeof(in_addr_t)); GtpuUpdateTunnelOutgoingAddressAndTeid(instance, (ue_id & 0xFFFF), (ebi_t)drb_p->id, - *(in_addr_t*)&newRemoteAddr.buffer, + addr, drb_p->DlUpParamList[0].teId); } } From dcae67c375fac792d68135180b27a7cdb7b30cff Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 23 Jun 2023 14:22:53 +0100 Subject: [PATCH 017/119] Bugfix for PDCCH monitoring occasions tables and SFN computation for FR2 --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 8 +------ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 22 +++++++++---------- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 +- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 9465d69e8b..c15a5cd194 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -483,19 +483,13 @@ typedef enum nr_ssb_and_cset_mux_pattern_type_e { NR_SSB_AND_CSET_MUX_PATTERN_TYPE3 } nr_ssb_and_cset_mux_pattern_type_t; -typedef enum { - SFN_C_MOD_2_EQ_0, - SFN_C_MOD_2_EQ_1, - SFN_C_IMPOSSIBLE -} SFN_C_TYPE; - typedef struct Type0_PDCCH_CSS_config_s { int32_t num_rbs; int32_t num_symbols; int32_t rb_offset; // Offset from SSB RB0 uint32_t type0_pdcch_ss_mux_pattern; uint16_t frame; - SFN_C_TYPE sfn_c; + int sfn_c; uint32_t n_c; uint32_t n_0; uint32_t number_of_search_space_per_slot; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 67d1e4fc5f..e9fa641a07 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -164,12 +164,12 @@ const int32_t table_38213_13_10_c4[16] = { 0, 8, 0, 8,-41, 25,-41, 49, reserv const float table_38213_13_11_c1[16] = { 0, 0, 2, 2, 5, 5, 7, 7, 0, 5, 0, 0, 2, 2, 5, 5}; // O const int32_t table_38213_13_11_c2[16] = { 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1}; -const float table_38213_13_11_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 1, 0.5f, 1, 1, 1, 1, 1, 1, 1, 1}; // M +const float table_38213_13_11_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 1, 0.5f, 2, 2, 1, 1, 1, 1, 1, 1}; // M const int32_t table_38213_13_11_c4[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2}; // i is even as default const float table_38213_13_12_c1[16] = { 0, 0, 2.5f, 2.5f, 5, 5, 0, 2.5f, 5, 7.5f, 7.5f, 7.5f, 0, 5, reserved, reserved}; // O, index 14-15 reserved const int32_t table_38213_13_12_c2[16] = { 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, reserved, reserved}; // index 14-15 reserved -const float table_38213_13_12_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 0.5f, 0.5f, 0.5f, 1, 0.5f, 0.5f, 1, 1, reserved, reserved}; // M, index 14-15 reserved +const float table_38213_13_12_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 0.5f, 0.5f, 0.5f, 1, 0.5f, 0.5f, 2, 2, reserved, reserved}; // M, index 14-15 reserved const int32_t table_38213_10_1_1_c2[5] = { 0, 0, 4, 2, 1 }; @@ -4301,7 +4301,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD // type0-pdcch search space float big_o = 0.0f; float big_m = 0.0f; - type0_PDCCH_CSS_config->sfn_c = SFN_C_IMPOSSIBLE; // only valid for mux=1 + type0_PDCCH_CSS_config->sfn_c = -1; // only valid for mux=1 type0_PDCCH_CSS_config->n_c = UINT_MAX; type0_PDCCH_CSS_config->number_of_search_space_per_slot = UINT_MAX; type0_PDCCH_CSS_config->first_symbol_index = UINT_MAX; @@ -4316,11 +4316,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD uint32_t temp = (uint32_t)(big_o*(1<ssb_index*big_m); type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame; - if((temp/num_slot_per_frame) & 0x1){ - type0_PDCCH_CSS_config->sfn_c = SFN_C_MOD_2_EQ_1; - }else{ - type0_PDCCH_CSS_config->sfn_c = SFN_C_MOD_2_EQ_0; - } + type0_PDCCH_CSS_config->sfn_c = type0_PDCCH_CSS_config->n_c % 2; if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (type0_PDCCH_CSS_config->ssb_index&1)){ type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols; @@ -4335,9 +4331,13 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ big_o = table_38213_13_12_c1[index_4lsb]; - type0_PDCCH_CSS_config->number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; + type0_PDCCH_CSS_config->number_of_search_space_per_slot = table_38213_13_12_c2[index_4lsb]; big_m = table_38213_13_12_c3[index_4lsb]; + uint32_t temp = (uint32_t)(big_o*(1<ssb_index*big_m); + type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame; + type0_PDCCH_CSS_config->sfn_c = type0_PDCCH_CSS_config->n_c % 2; + if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (type0_PDCCH_CSS_config->ssb_index&1)){ type0_PDCCH_CSS_config->first_symbol_index = 7; }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (type0_PDCCH_CSS_config->ssb_index&1)){ @@ -4461,8 +4461,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD // AssertFatal(first_symbol_index!=UINT_MAX,""); // mac->type0_pdcch_dci_config.monitoring_symbols_within_slot = (0x3fff << first_symbol_index) & (0x3fff >> (14-coreset_duration-first_symbol_index)) & 0x3fff; - AssertFatal(type0_PDCCH_CSS_config->sfn_c!=SFN_C_IMPOSSIBLE,""); - AssertFatal(type0_PDCCH_CSS_config->n_c!=UINT_MAX,""); + AssertFatal(type0_PDCCH_CSS_config->sfn_c >= 0, ""); + AssertFatal(type0_PDCCH_CSS_config->n_c != UINT_MAX, ""); type0_PDCCH_CSS_config->n_0 = ((uint32_t)(big_o*(1<ssb_index*big_m))%num_slot_per_frame; type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 99c7ba6dcd..4eee1bb3fe 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -420,7 +420,7 @@ typedef struct { /// Type0-PDCCH seach space fapi_nr_dl_config_dci_dl_pdu_rel15_t type0_pdcch_dci_config; uint32_t type0_pdcch_ss_mux_pattern; - SFN_C_TYPE type0_pdcch_ss_sfn_c; + int type0_pdcch_ss_sfn_c; uint32_t type0_pdcch_ss_n_c; uint32_t type0_pdcch_consecutive_slots; From 659d52931514f63fc691c2c653e16d9c69e20575 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Tue, 13 Jun 2023 14:25:26 +0100 Subject: [PATCH 018/119] Enable T304 --- openair2/RRC/NR_UE/rrc_UE.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 69efec94ce..27f53b673c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1208,7 +1208,9 @@ void nr_rrc_ue_process_masterCellGroup(const protocol_ctxt_t *const ctxt_pP, set_default_timers_and_constants(&rrc->timers_and_constants); LOG_A(NR_RRC, "Received the reconfigurationWithSync in %s\n", __FUNCTION__); NR_ReconfigurationWithSync_t *reconfigurationWithSync = cellGroupConfig->spCellConfig->reconfigurationWithSync; + rrc->timers_and_constants.T304_active = true; nr_rrc_set_T304(&rrc->timers_and_constants, reconfigurationWithSync); + // TODO: Implementation of the remaining procedures regarding the reception of the reconfigurationWithSync, TS 38.331 - Section 5.3.5.5.2 } if (rrc->cell_group_config && @@ -2287,7 +2289,7 @@ void *rrc_nrue_task(void *args_p) break; case NRRRC_SLOT_PROCESS: - LOG_D(NR_RRC, "[UE %d] Receided %s: frame %d slot %d\n", + LOG_D(NR_RRC, "[UE %d] Received %s: frame %d slot %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NRRRC_SLOT_PROCESS (msg_p).frame, NRRRC_SLOT_PROCESS (msg_p).slot); NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants; nr_rrc_handle_timers(timers); From 8fffe50a115b7ebc131de1aed3bfb8b047c30005 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Fri, 17 Mar 2023 14:18:39 +0000 Subject: [PATCH 019/119] Fix rho computation --- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 84baea9844..070968760b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1100,8 +1100,10 @@ void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, if (n_rx > 1) { #if defined(__x86_64__) || defined(__i386__) - for (int aatx=0; aatxnb_antennas_rx][(symbol*(nb_re + off))]; ul_ch_mag128[0] = (__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; @@ -1123,6 +1125,20 @@ void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, //rxdataF_comp128[0][i] = _mm_add_epi16(rxdataF_comp128_0[i],(*(__m128i *)&jitterc[0])); } } + + if (rho) { + __m128i *rho128[2]; + for (int aatx2 = 0; aatx2 < nrOfLayers; aatx2++) { + rho128[0] = (__m128i *) &rho[0][aatx * nrOfLayers + aatx2][(symbol * (nb_re + off))]; + for (int aa = 1; aa < n_rx; aa++) { + rho128[1] = (__m128i *) &rho[aa][aatx * nrOfLayers + aatx2][(symbol * (nb_re + off))]; + for (i = 0; i < nb_rb_0 * 3; i++) { + rho128[0][i] = _mm_adds_epi16(rho128[0][i], rho128[1][i]); + } + } + } + } + } #elif defined(__arm__) || defined(__aarch64__) rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12]; From e21a09967dfc32c5fc0f85a3fb0b4f036dc5fe59 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 15 Mar 2023 15:52:06 +0000 Subject: [PATCH 020/119] Compute LLR for QPSK for ML --- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 12 + .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 65 +++-- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 264 ++++++++++++++++++ 3 files changed, 325 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 0509ce7acf..306d44f8f5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -292,6 +292,18 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, void reset_active_stats(PHY_VARS_gNB *gNB, int frame); void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); +void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, + int32_t ***rho, + int16_t **llr_layers, + uint8_t nb_antennas_rx, + uint32_t rb_size, + uint32_t nb_re, + uint8_t symbol, + uint32_t rxdataF_ext_offset, + uint8_t mod_order); + +void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift); + void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 070968760b..56e4575f7a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -12,6 +12,7 @@ //#define DEBUG_CH_COMP //#define DEBUG_RB_EXT //#define DEBUG_CH_MAG +//#define ML_DEBUG #define INVALID_VALUE 255 @@ -636,7 +637,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, QAM_amp128 = _mm_set1_epi16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = _mm_setzero_si128(); QAM_amp128c = _mm_setzero_si128(); - } + } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); // QAM_amp128b = _mm_set1_epi16(QAM64_n2); @@ -1081,7 +1082,7 @@ void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t **ul_ch_mag, int32_t **ul_ch_magb, int32_t **ul_ch_magc, - int32_t ***rho, + int32_t ***rho, uint8_t nrOfLayers, uint8_t symbol, uint16_t nb_rb, @@ -1115,7 +1116,7 @@ void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, ul_ch_mag128[1] = (__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; ul_ch_mag128b[1] = (__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; ul_ch_mag128c[1] = (__m128i *)&ul_ch_magc[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) for (i=0; inrOfLayers == 1) { ad_shift = 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); - } else { - ad_shift = -3; // For 2-layers, we are already doing a bit shift in the nr_ulsch_zero_forcing_rx_2layers() function, so we can use more bits + } else if (ml_rx == false) { + ad_shift = -3; // For 2-layers, we are already doing a bit shift in the nr_ulsch_mmse_2layers() function, so we can use more bits } for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { @@ -2108,7 +2112,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, nb_re_pusch); // Apply MMSE for 2 Tx layers - if (rel15_ul->nrOfLayers == 2) { + if (ml_rx == false && rel15_ul->nrOfLayers == 2) { nr_ulsch_mmse_2layers(frame_parms, pusch_vars->rxdataF_comp, pusch_vars->ul_ch_mag0, @@ -2159,16 +2163,45 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, /*-------------------- LLRs computation -------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------------*/ start_meas(&gNB->ulsch_llr_stats); - for (aatx=0; aatx < rel15_ul->nrOfLayers; aatx++) { - nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx*frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], - pusch_vars->ul_ch_mag0[aatx*frame_parms->nb_antennas_rx], - pusch_vars->ul_ch_magb0[aatx*frame_parms->nb_antennas_rx], - pusch_vars->ul_ch_magc0[aatx*frame_parms->nb_antennas_rx], - &pusch_vars->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order], - rel15_ul->rb_size, - pusch_vars->ul_valid_re_per_slot[symbol], - symbol, - rel15_ul->qam_mod_order); + if (ml_rx == false || rel15_ul->nrOfLayers == 1) { + for (aatx=0; aatx < rel15_ul->nrOfLayers; aatx++) { + nr_ulsch_compute_llr(&pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], + pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx], + pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx], + pusch_vars->ul_ch_magc0[aatx * frame_parms->nb_antennas_rx], + &pusch_vars->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order], + rel15_ul->rb_size, + pusch_vars->ul_valid_re_per_slot[symbol], + symbol, + rel15_ul->qam_mod_order); + } + } else { + nr_ulsch_compute_ML_llr(pusch_vars->rxdataF_comp, + pusch_vars->rho, + pusch_vars->llr_layers, + frame_parms->nb_antennas_rx, + rel15_ul->rb_size, + nb_re_pusch, + symbol, + rxdataF_ext_offset, + rel15_ul->qam_mod_order); + + if (rel15_ul->qam_mod_order == 2) { + nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re_pusch, rxdataF_ext_offset, rel15_ul->qam_mod_order, 4); + } + +#ifdef ML_DEBUG + c16_t *llr_layers0 = (c16_t *)&pusch_vars->llr_layers[0][rxdataF_ext_offset * rel15_ul->qam_mod_order]; + c16_t *llr_layers1 = (c16_t *)&pusch_vars->llr_layers[1][rxdataF_ext_offset * rel15_ul->qam_mod_order]; + printf("===============================\n"); + printf("AFTER nr_ulsch_compute_ML_llr()\n"); + printf("===============================\n"); + for (int k = 0; k < nb_re_pusch; k++) { + printf("[%3i] llr_layers0 = (%6i, %6i), llr_layers1 = (%6i, %6i)\n", + k, llr_layers0[k].r, llr_layers0[k].i, llr_layers1[k].r, llr_layers1[k].i); + } + printf("\n"); +#endif } stop_meas(&gNB->ulsch_llr_stats); rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol]; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 4d4c81a986..dc5e117267 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -509,3 +509,267 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, break; } } + +/* + * This function computes the LLRs of stream 0 (s_0) in presence of the interfering stream 1 (s_1) assuming that both symbols are + * QPSK. It can be used for both MU-MIMO interference-aware receiver or for SU-MIMO receivers. + * + * Input: + * stream0_in: MF filter output for 1st stream, i.e., y0' = h0'*y0 + * stream1_in: MF filter output for 2nd stream, i.e., y1' = h1'*y0 + * rho01: Channel cross correlation, i.e., rho01 = h0'*h1 + * length: Number of resource elements + * + * Output: + * stream0_out: Output LLRs for 1st stream + */ +void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, c16_t *stream1_in, c16_t *stream0_out, c16_t *rho01, uint32_t length) +{ + __m128i *rho01_128i = (__m128i *)rho01; + __m128i *stream0_128i_in = (__m128i *)stream0_in; + __m128i *stream1_128i_in = (__m128i *)stream1_in; + __m128i *stream0_128i_out = (__m128i *)stream0_out; + __m128i ONE_OVER_2_SQRT_2 = _mm_set1_epi16(23170); // round(2 ^ 16 / (2 * sqrt(2))) + + // In each iteration, we take 8 complex symbols + for (int i = 0; i < length >> 2; i += 2) { + + /// Compute real and imaginary parts of MF output for stream 0 (desired stream) + + // Put xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + __m128i xmm0 = stream0_128i_in[i]; // 4 symbols + xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + __m128i xmm1 = stream0_128i_in[i + 1]; // 4 symbols + xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + __m128i y0r = simde_mm_unpacklo_epi64(xmm0, xmm1); // y0r = Re(y0) + __m128i y0i = simde_mm_unpackhi_epi64(xmm0, xmm1); // y0i = Im(y0) + + __m128i y0r_over2 = simde_mm_mulhi_epi16(y0r, ONE_OVER_2_SQRT_2); + y0r_over2 = _mm_slli_epi16(y0r_over2, 1); // y0r_over2 = Re(y0) / sqrt(2) + __m128i y0i_over2 = simde_mm_mulhi_epi16(y0i, ONE_OVER_2_SQRT_2); + y0i_over2 = _mm_slli_epi16(y0i_over2, 1); // y0i_over2 = Im(y0) / sqrt(2) + + /// Compute real and imaginary parts of MF output for stream 1 (interference stream) + + // Put xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + xmm0 = stream1_128i_in[i]; // 4 symbols + xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + xmm1 = stream1_128i_in[i + 1]; // 4 symbols + xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + __m128i y1r = simde_mm_unpacklo_epi64(xmm0, xmm1); // y1r = Re(y1) + __m128i y1i = simde_mm_unpackhi_epi64(xmm0, xmm1); // y1i = Im(y1) + __m128i y1r_over2 = simde_mm_srai_epi16(y1r, 1); // y1r_over2 = Re(y1) / 2 + __m128i y1i_over2 = simde_mm_srai_epi16(y1i, 1); // y1i_over2 = Im(y1) / 2 + + /// Get real and imaginary parts of rho + + // Put xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + xmm0 = rho01_128i[i]; // 4 symbols + xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + xmm1 = rho01_128i[i + 1]; // 4 symbols + xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + __m128i rhor = simde_mm_unpacklo_epi64(xmm0, xmm1); // rhor = Re(rho) + __m128i rhoi = simde_mm_unpackhi_epi64(xmm0, xmm1); // rhoi = Im(rho) + + /// Compute |psi_r| and |psi_i| + + // psi_r = rhor * xR + rhoi * xI + // psi_i = rhor * xI - rhoi * xR + + // Put (rho_r + rho_i)/(2*sqrt(2)) in rho_p + // rhor * xR + rhoi * xI --> xR = 1/sqrt(2) and xI = 1/sqrt(2) + // rhor * xI - rhoi * xR --> xR = -1/sqrt(2) and xI = 1/sqrt(2) + __m128i rho_p = simde_mm_adds_epi16(rhor, rhoi); // rho_p = Re(rho) + Im(rho) + rho_p = simde_mm_mulhi_epi16(rho_p, ONE_OVER_2_SQRT_2); // rho_p = rho_p / (2*sqrt(2)) + + // Put (rho_r - rho_i)/(2*sqrt(2)) in rho_m + // rhor * xR + rhoi * xI --> xR = 1/sqrt(2) and xI = -1/sqrt(2) + // rhor * xI - rhoi * xR --> xR = 1/sqrt(2) and xI = 1/sqrt(2) + __m128i rho_m = simde_mm_subs_epi16(rhor, rhoi); // rho_m = Re(rho) - Im(rho) + rho_m = simde_mm_mulhi_epi16(rho_m, ONE_OVER_2_SQRT_2); // rho_m = rho_m / (2*sqrt(2)) + + // xR = 1/sqrt(2) and xI = 1/sqrt(2) + __m128i abs_psi_rpm = simde_mm_subs_epi16(rho_p, y1r_over2); // psi_rpm = rho_p - y1r/2 + abs_psi_rpm = simde_mm_abs_epi16(abs_psi_rpm); // abs_psi_rpm = |psi_rpm| + + // xR = 1/sqrt(2) and xI = 1/sqrt(2) + __m128i abs_psi_imm = simde_mm_subs_epi16(rho_m, y1i_over2); // psi_imm = rho_m - y1i/2 + abs_psi_imm = simde_mm_abs_epi16(abs_psi_imm); // abs_psi_imm = |psi_imm| + + // xR = 1/sqrt(2) and xI = -1/sqrt(2) + __m128i abs_psi_rmm = simde_mm_subs_epi16(rho_m, y1r_over2); // psi_rmm = rho_m - y1r/2 + abs_psi_rmm = simde_mm_abs_epi16(abs_psi_rmm); // abs_psi_rmm = |psi_rmm| + + // xR = -1/sqrt(2) and xI = 1/sqrt(2) + __m128i abs_psi_ipm = simde_mm_subs_epi16(rho_p, y1i_over2); // psi_ipm = rho_p - y1i/2 + abs_psi_ipm = simde_mm_abs_epi16(abs_psi_ipm); // abs_psi_ipm = |psi_ipm| + + // xR = -1/sqrt(2) and xI = -1/sqrt(2) + __m128i abs_psi_rpp = simde_mm_adds_epi16(rho_p, y1r_over2); // psi_rpp = rho_p + y1r/2 + abs_psi_rpp = simde_mm_abs_epi16(abs_psi_rpp); // abs_psi_rpp = |psi_rpp| + + // xR = -1/sqrt(2) and xI = -1/sqrt(2) + __m128i abs_psi_imp = simde_mm_adds_epi16(rho_m, y1i_over2); // psi_imp = rho_m + y1i/2 + abs_psi_imp = simde_mm_abs_epi16(abs_psi_imp); // abs_psi_imp = |psi_imp| + + // xR = -1/sqrt(2) and xI = 1/sqrt(2) + __m128i abs_psi_rmp = simde_mm_adds_epi16(rho_m, y1r_over2); // psi_rmp = rho_m + y1r/2 + abs_psi_rmp = simde_mm_abs_epi16(abs_psi_rmp); // abs_psi_rmp = |psi_rmp| + + // xR = 1/sqrt(2) and xI = -1/sqrt(2) + __m128i abs_psi_ipp = simde_mm_adds_epi16(rho_p, y1i_over2); // psi_ipm = rho_p + y1i/2 + abs_psi_ipp = simde_mm_abs_epi16(abs_psi_ipp); // abs_psi_ipp = |psi_ipm| + + /// Compute bit metrics (lambda) + + // lambda = max { |psi_r - y1r| * |x2R| + |psi_i - y1i| * |x2I| + y0r * xR + y0i * xI} + + // xR = 1/sqrt(2) and xI = 1/sqrt(2) + // For numerator: bit_met_num_re_p = abs_psi_rpm + abs_psi_imm + y0r/sqrt(2) + y0i/sqrt(2) + __m128i bit_met_num_re_p = simde_mm_adds_epi16(abs_psi_rpm, abs_psi_imm); + bit_met_num_re_p = simde_mm_adds_epi16(bit_met_num_re_p, y0r_over2); + bit_met_num_re_p = simde_mm_adds_epi16(bit_met_num_re_p, y0i_over2); + + // xR = 1/sqrt(2) and xI = -1/sqrt(2) + // For numerator: bit_met_num_re_m = abs_psi_rmm + abs_psi_ipp + y0r/sqrt(2) - y0i/sqrt(2) + __m128i bit_met_num_re_m = simde_mm_adds_epi16(abs_psi_rmm, abs_psi_ipp); + bit_met_num_re_m = simde_mm_adds_epi16(bit_met_num_re_m, y0r_over2); + bit_met_num_re_m = simde_mm_subs_epi16(bit_met_num_re_m, y0i_over2); + + // xR = -1/sqrt(2) and xI = 1/sqrt(2) + // For denominator: bit_met_den_re_p = abs_psi_rmp + abs_psi_ipm - y0r/sqrt(2) + y0i/sqrt(2) + __m128i bit_met_den_re_p = simde_mm_adds_epi16(abs_psi_rmp, abs_psi_ipm); + bit_met_den_re_p = simde_mm_subs_epi16(bit_met_den_re_p, y0r_over2); + bit_met_den_re_p = simde_mm_adds_epi16(bit_met_den_re_p, y0i_over2); + + // xR = -1/sqrt(2) and xI = -1/sqrt(2) + // For denominator: bit_met_den_re_m = abs_psi_rpp + abs_psi_imp - y0r/sqrt(2) - y0i/sqrt(2) + __m128i bit_met_den_re_m = simde_mm_adds_epi16(abs_psi_rpp, abs_psi_imp); + bit_met_den_re_m = simde_mm_subs_epi16(bit_met_den_re_m, y0r_over2); + bit_met_den_re_m = simde_mm_subs_epi16(bit_met_den_re_m, y0i_over2); + + // xR = 1/sqrt(2) and xI = 1/sqrt(2) + // For numerator: bit_met_num_im_p = abs_psi_rpm + abs_psi_imm + y0r/sqrt(2) + y0i/sqrt(2) + __m128i bit_met_num_im_p = simde_mm_adds_epi16(abs_psi_rpm, abs_psi_imm); + bit_met_num_im_p = simde_mm_adds_epi16(bit_met_num_im_p, y0r_over2); + bit_met_num_im_p = simde_mm_adds_epi16(bit_met_num_im_p, y0i_over2); + + // xR = -1/sqrt(2) and xI = 1/sqrt(2) + // For numerator: bit_met_num_im_m = abs_psi_rmp + abs_psi_ipm - y0r/sqrt(2) + y0i/sqrt(2) + __m128i bit_met_num_im_m = simde_mm_adds_epi16(abs_psi_rmp, abs_psi_ipm); + bit_met_num_im_m = simde_mm_subs_epi16(bit_met_num_im_m, y0r_over2); + bit_met_num_im_m = simde_mm_adds_epi16(bit_met_num_im_m, y0i_over2); + + // xR = 1/sqrt(2) and xI = -1/sqrt(2) + // For denominator: bit_met_den_im_p = abs_psi_rmm + abs_psi_ipp + y0r/sqrt(2) - y0i/sqrt(2) + __m128i bit_met_den_im_p = simde_mm_adds_epi16(abs_psi_rmm, abs_psi_ipp); + bit_met_den_im_p = simde_mm_adds_epi16(bit_met_den_im_p, y0r_over2); + bit_met_den_im_p = simde_mm_subs_epi16(bit_met_den_im_p, y0i_over2); + + // xR = -1/sqrt(2) and xI = -1/sqrt(2) + // For denominator: bit_met_den_im_m = abs_psi_rpp + abs_psi_imp - y0r/sqrt(2)- y0i/sqrt(2) + __m128i bit_met_den_im_m = simde_mm_adds_epi16(abs_psi_rpp, abs_psi_imp); + bit_met_den_im_m = simde_mm_subs_epi16(bit_met_den_im_m, y0r_over2); + bit_met_den_im_m = simde_mm_subs_epi16(bit_met_den_im_m, y0i_over2); + + /// Compute the LLRs + + // LLR = lambda(c==1) - lambda(c==0) + + __m128i logmax_num_re0 = simde_mm_max_epi16(bit_met_num_re_p, bit_met_num_re_m); // LLR of the first bit: Bit = 1 + __m128i logmax_den_re0 = simde_mm_max_epi16(bit_met_den_re_p, bit_met_den_re_m); // LLR of the first bit: Bit = 0 + __m128i logmax_num_im0 = simde_mm_max_epi16(bit_met_num_im_p, bit_met_num_im_m); // LLR of the second bit: Bit = 1 + __m128i logmax_den_im0 = simde_mm_max_epi16(bit_met_den_im_p, bit_met_den_im_m); // LLR of the second bit: Bit = 0 + + y0r = simde_mm_subs_epi16(logmax_num_re0, logmax_den_re0); // LLR of first bit [L1(1), L1(2), L1(3), L1(4)] + y0i = simde_mm_subs_epi16(logmax_num_im0, logmax_den_im0); // LLR of second bit [L2(1), L2(2), L2(3), L2(4)] + + // [L1(1), L2(1), L1(2), L2(2)] + simde_mm_storeu_si128(&stream0_128i_out[i], simde_mm_unpacklo_epi16(y0r, y0i)); + + // false if only 2 REs remain + if (i < ((length >> 1) - 1)) { + simde_mm_storeu_si128(&stream0_128i_out[i + 1], simde_mm_unpackhi_epi16(y0r, y0i)); + } + } + + _mm_empty(); + _m_empty(); +} + + +void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, + int32_t ***rho, + int16_t **llr_layers, + uint8_t nb_antennas_rx, + uint32_t rb_size, + uint32_t nb_re, + uint8_t symbol, + uint32_t rxdataF_ext_offset, + uint8_t mod_order) +{ + int off = ((rb_size & 1) == 1) ? 4 : 0; + c16_t *rxdataF_comp0 = (c16_t *)&rxdataF_comp[0][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; + c16_t *rxdataF_comp1 = (c16_t *)&rxdataF_comp[nb_antennas_rx][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; + c16_t *llr_layers0 = (c16_t *)&llr_layers[0][rxdataF_ext_offset * mod_order]; + c16_t *llr_layers1 = (c16_t *)&llr_layers[1][rxdataF_ext_offset * mod_order]; + c16_t *rho0 = (c16_t *)&rho[0][1][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; + c16_t *rho1 = (c16_t *)&rho[0][2][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; + + switch (mod_order) { + case 2: + nr_ulsch_qpsk_qpsk(rxdataF_comp0, rxdataF_comp1, llr_layers0, rho0, nb_re); + nr_ulsch_qpsk_qpsk(rxdataF_comp1, rxdataF_comp0, llr_layers1, rho1, nb_re); + break; + case 4: + case 6: + AssertFatal(1 == 0, "LLR computation is not implemented yet for ML with Qm = %d\n", mod_order); + default: + AssertFatal(1 == 0, "nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d\n", symbol, mod_order); + } +} + +void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift) +{ + __m128i *llr_layers0 = (__m128i *)&llr_layers[0][rxdataF_ext_offset * mod_order]; + __m128i *llr_layers1 = (__m128i *)&llr_layers[1][rxdataF_ext_offset * mod_order]; + + uint8_t mem_offset = ((16 - ((long)llr_layers0)) & 0xF) >> 2; + + if (mem_offset > 0) { + c16_t *llr_layers0_c16 = (c16_t *)&llr_layers[0][rxdataF_ext_offset * mod_order]; + c16_t *llr_layers1_c16 = (c16_t *)&llr_layers[1][rxdataF_ext_offset * mod_order]; + for (int i = 0; i < mem_offset; i++) { + llr_layers0_c16[i] = c16Shift(llr_layers0_c16[i], shift); + llr_layers1_c16[i] = c16Shift(llr_layers1_c16[i], shift); + } + llr_layers0 = (__m128i *)&llr_layers[0][rxdataF_ext_offset * mod_order + (mem_offset << 1)]; + llr_layers1 = (__m128i *)&llr_layers[1][rxdataF_ext_offset * mod_order + (mem_offset << 1)]; + } + + for (int i = 0; i < nb_re >> 2; i++) { + llr_layers0[i] = simde_mm_srai_epi16(llr_layers0[i], shift); + llr_layers1[i] = simde_mm_srai_epi16(llr_layers1[i], shift); + } +} \ No newline at end of file From 46dca7a111282d6c46bdb8f8f06eb9b8213da37d Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 23 Mar 2023 11:00:52 +0000 Subject: [PATCH 021/119] Compute LLR for 16QAM for ML --- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 1 + .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 1 + .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 663 ++++++++++++++++++ 3 files changed, 665 insertions(+) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 306d44f8f5..2478748688 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -293,6 +293,7 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame); void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, + int32_t **ul_ch_mag, int32_t ***rho, int16_t **llr_layers, uint8_t nb_antennas_rx, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 56e4575f7a..405a73a5fd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -2177,6 +2177,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, } } else { nr_ulsch_compute_ML_llr(pusch_vars->rxdataF_comp, + pusch_vars->ul_ch_mag0, pusch_vars->rho, pusch_vars->llr_layers, frame_parms->nb_antennas_rx, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index dc5e117267..924c68a1f4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -718,8 +718,666 @@ void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, c16_t *stream1_in, c16_t *stream0_out _m_empty(); } +int16_t ones[8] __attribute__((aligned(16))) = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; + +// Calculates psi_a = psi_r * a_r + psi_i * a_i +#define prodsum_psi_a_epi16(psi_r, a_r, psi_i, a_i, psi_a) \ + tmp_result = simde_mm_mulhi_epi16(psi_r, a_r); \ + tmp_result = simde_mm_slli_epi16(tmp_result, 1); \ + tmp_result2 = simde_mm_mulhi_epi16(psi_i, a_i); \ + tmp_result2 = simde_mm_slli_epi16(tmp_result2, 1); \ + psi_a = simde_mm_adds_epi16(tmp_result, tmp_result2); + +// Calculate interference magnitude +#define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ + tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); \ + tmp_result2 = simde_mm_xor_si128(tmp_result, (*(__m128i *)&ones[0])); \ + tmp_result = simde_mm_and_si128(tmp_result, c1); \ + tmp_result2 = simde_mm_and_si128(tmp_result2, c2); \ + int_mag = simde_mm_or_si128(tmp_result, tmp_result2); + +// Calculates a_sq = int_ch_mag * (a_r^2 + a_i^2) * scale_factor +#define square_a_epi16(a_r, a_i, int_ch_mag, scale_factor, a_sq) \ + tmp_result = simde_mm_mulhi_epi16(a_r, a_r); \ + tmp_result = simde_mm_slli_epi16(tmp_result, 1); \ + tmp_result = simde_mm_mulhi_epi16(tmp_result, scale_factor); \ + tmp_result = simde_mm_slli_epi16(tmp_result, 1); \ + tmp_result = simde_mm_mulhi_epi16(tmp_result, int_ch_mag); \ + tmp_result = simde_mm_slli_epi16(tmp_result, 1); \ + tmp_result2 = simde_mm_mulhi_epi16(a_i, a_i); \ + tmp_result2 = simde_mm_slli_epi16(tmp_result2, 1); \ + tmp_result2 = simde_mm_mulhi_epi16(tmp_result2, scale_factor); \ + tmp_result2 = simde_mm_slli_epi16(tmp_result2, 1); \ + tmp_result2 = simde_mm_mulhi_epi16(tmp_result2, int_ch_mag); \ + tmp_result2 = simde_mm_slli_epi16(tmp_result2, 1); \ + a_sq = simde_mm_adds_epi16(tmp_result, tmp_result2); + +__m128i max_epi16(__m128i m0, __m128i m1, __m128i m2, __m128i m3, __m128i m4, __m128i m5, __m128i m6, __m128i m7) +{ + __m128i a0 = simde_mm_max_epi16(m0, m1); + __m128i a1 = simde_mm_max_epi16(m2, m3); + __m128i a2 = simde_mm_max_epi16(m4, m5); + __m128i a3 = simde_mm_max_epi16(m6, m7); + __m128i b0 = simde_mm_max_epi16(a0, a1); + __m128i b1 = simde_mm_max_epi16(a2, a3); + return simde_mm_max_epi16(b0, b1); +} + +/* + * This function computes the LLRs of stream 0 (s_0) in presence of the interfering stream 1 (s_1) assuming that both symbols are + * 16QAM. It can be used for both MU-MIMO interference-aware receiver or for SU-MIMO receivers. + * + * Input: + * stream0_in: MF filter output for 1st stream, i.e., y0' = h0'*y0 + * stream1_in: MF filter output for 2nd stream, i.e., y1' = h1'*y0 + * ch_mag: 2*h0/sqrt(10), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + * ch_mag_i: 2*h1/sqrt(10), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + * rho01: Channel cross correlation, i.e., rho01 = h0'*h1 + * length: Number of resource elements + * + * Output: + * stream0_out: Output LLRs for 1st stream + */ +void nr_ulsch_qam16_qam16(c16_t *stream0_in, + c16_t *stream1_in, + c16_t *ch_mag, + c16_t *ch_mag_i, + c16_t *stream0_out, + c16_t *rho01, + uint32_t length) +{ + __m128i *rho01_128i = (__m128i *)rho01; + __m128i *stream0_128i_in = (__m128i *)stream0_in; + __m128i *stream1_128i_in = (__m128i *)stream1_in; + __m128i *stream0_128i_out = (__m128i *)stream0_out; + __m128i *ch_mag_128i = (__m128i *)ch_mag; + __m128i *ch_mag_128i_i = (__m128i *)ch_mag_i; + + __m128i ONE_OVER_SQRT_10 = simde_mm_set1_epi16(20724); // round(1/sqrt(10)*2^16) + __m128i ONE_OVER_SQRT_10_Q15 = simde_mm_set1_epi16(10362); // round(1/sqrt(10)*2^15) + __m128i THREE_OVER_SQRT_10 = simde_mm_set1_epi16(31086); // round(3/sqrt(10)*2^15) + __m128i SQRT_10_OVER_FOUR = simde_mm_set1_epi16(25905); // round(sqrt(10)/4*2^15) + __m128i ONE_OVER_TWO_SQRT_10 = simde_mm_set1_epi16(10362); // round(1/2/sqrt(10)*2^16) + __m128i NINE_OVER_TWO_SQRT_10 = simde_mm_set1_epi16(23315); // round(9/2/sqrt(10)*2^14) + __m128i ch_mag_des, ch_mag_int; + __m128i y0r_over_sqrt10; + __m128i y0i_over_sqrt10; + __m128i y0r_three_over_sqrt10; + __m128i y0i_three_over_sqrt10; + __m128i ch_mag_over_10; + __m128i ch_mag_over_2; + __m128i ch_mag_9_over_10; + + __m128i xmm0 __attribute__((aligned(16))); + __m128i xmm1 __attribute__((aligned(16))); + __m128i xmm2 __attribute__((aligned(16))); + __m128i xmm3 __attribute__((aligned(16))); + __m128i xmm4 __attribute__((aligned(16))); + __m128i xmm5 __attribute__((aligned(16))); + __m128i xmm6 __attribute__((aligned(16))); + __m128i xmm7 __attribute__((aligned(16))); + + __m128i rho_rpi __attribute__((aligned(16))); + __m128i rho_rmi __attribute__((aligned(16))); + __m128i rho_rpi_1_1 __attribute__((aligned(16))); + __m128i rho_rpi_1_3 __attribute__((aligned(16))); + __m128i rho_rpi_3_1 __attribute__((aligned(16))); + __m128i rho_rpi_3_3 __attribute__((aligned(16))); + __m128i rho_rmi_1_1 __attribute__((aligned(16))); + __m128i rho_rmi_1_3 __attribute__((aligned(16))); + __m128i rho_rmi_3_1 __attribute__((aligned(16))); + __m128i rho_rmi_3_3 __attribute__((aligned(16))); + + __m128i psi_r_m3_m3 __attribute__((aligned(16))); + __m128i psi_r_m3_m1 __attribute__((aligned(16))); + __m128i psi_r_m3_p1 __attribute__((aligned(16))); + __m128i psi_r_m3_p3 __attribute__((aligned(16))); + __m128i psi_r_m1_m3 __attribute__((aligned(16))); + __m128i psi_r_m1_m1 __attribute__((aligned(16))); + __m128i psi_r_m1_p1 __attribute__((aligned(16))); + __m128i psi_r_m1_p3 __attribute__((aligned(16))); + __m128i psi_r_p1_m3 __attribute__((aligned(16))); + __m128i psi_r_p1_m1 __attribute__((aligned(16))); + __m128i psi_r_p1_p1 __attribute__((aligned(16))); + __m128i psi_r_p1_p3 __attribute__((aligned(16))); + __m128i psi_r_p3_m3 __attribute__((aligned(16))); + __m128i psi_r_p3_m1 __attribute__((aligned(16))); + __m128i psi_r_p3_p1 __attribute__((aligned(16))); + __m128i psi_r_p3_p3 __attribute__((aligned(16))); + + __m128i psi_i_m3_m3 __attribute__((aligned(16))); + __m128i psi_i_m3_m1 __attribute__((aligned(16))); + __m128i psi_i_m3_p1 __attribute__((aligned(16))); + __m128i psi_i_m3_p3 __attribute__((aligned(16))); + __m128i psi_i_m1_m3 __attribute__((aligned(16))); + __m128i psi_i_m1_m1 __attribute__((aligned(16))); + __m128i psi_i_m1_p1 __attribute__((aligned(16))); + __m128i psi_i_m1_p3 __attribute__((aligned(16))); + __m128i psi_i_p1_m3 __attribute__((aligned(16))); + __m128i psi_i_p1_m1 __attribute__((aligned(16))); + __m128i psi_i_p1_p1 __attribute__((aligned(16))); + __m128i psi_i_p1_p3 __attribute__((aligned(16))); + __m128i psi_i_p3_m3 __attribute__((aligned(16))); + __m128i psi_i_p3_m1 __attribute__((aligned(16))); + __m128i psi_i_p3_p1 __attribute__((aligned(16))); + __m128i psi_i_p3_p3 __attribute__((aligned(16))); + + __m128i a_r_m3_m3 __attribute__((aligned(16))); + __m128i a_r_m3_m1 __attribute__((aligned(16))); + __m128i a_r_m3_p1 __attribute__((aligned(16))); + __m128i a_r_m3_p3 __attribute__((aligned(16))); + __m128i a_r_m1_m3 __attribute__((aligned(16))); + __m128i a_r_m1_m1 __attribute__((aligned(16))); + __m128i a_r_m1_p1 __attribute__((aligned(16))); + __m128i a_r_m1_p3 __attribute__((aligned(16))); + __m128i a_r_p1_m3 __attribute__((aligned(16))); + __m128i a_r_p1_m1 __attribute__((aligned(16))); + __m128i a_r_p1_p1 __attribute__((aligned(16))); + __m128i a_r_p1_p3 __attribute__((aligned(16))); + __m128i a_r_p3_m3 __attribute__((aligned(16))); + __m128i a_r_p3_m1 __attribute__((aligned(16))); + __m128i a_r_p3_p1 __attribute__((aligned(16))); + __m128i a_r_p3_p3 __attribute__((aligned(16))); + + __m128i a_i_m3_m3 __attribute__((aligned(16))); + __m128i a_i_m3_m1 __attribute__((aligned(16))); + __m128i a_i_m3_p1 __attribute__((aligned(16))); + __m128i a_i_m3_p3 __attribute__((aligned(16))); + __m128i a_i_m1_m3 __attribute__((aligned(16))); + __m128i a_i_m1_m1 __attribute__((aligned(16))); + __m128i a_i_m1_p1 __attribute__((aligned(16))); + __m128i a_i_m1_p3 __attribute__((aligned(16))); + __m128i a_i_p1_m3 __attribute__((aligned(16))); + __m128i a_i_p1_m1 __attribute__((aligned(16))); + __m128i a_i_p1_p1 __attribute__((aligned(16))); + __m128i a_i_p1_p3 __attribute__((aligned(16))); + __m128i a_i_p3_m3 __attribute__((aligned(16))); + __m128i a_i_p3_m1 __attribute__((aligned(16))); + __m128i a_i_p3_p1 __attribute__((aligned(16))); + __m128i a_i_p3_p3 __attribute__((aligned(16))); + + __m128i psi_a_m3_m3 __attribute__((aligned(16))); + __m128i psi_a_m3_m1 __attribute__((aligned(16))); + __m128i psi_a_m3_p1 __attribute__((aligned(16))); + __m128i psi_a_m3_p3 __attribute__((aligned(16))); + __m128i psi_a_m1_m3 __attribute__((aligned(16))); + __m128i psi_a_m1_m1 __attribute__((aligned(16))); + __m128i psi_a_m1_p1 __attribute__((aligned(16))); + __m128i psi_a_m1_p3 __attribute__((aligned(16))); + __m128i psi_a_p1_m3 __attribute__((aligned(16))); + __m128i psi_a_p1_m1 __attribute__((aligned(16))); + __m128i psi_a_p1_p1 __attribute__((aligned(16))); + __m128i psi_a_p1_p3 __attribute__((aligned(16))); + __m128i psi_a_p3_m3 __attribute__((aligned(16))); + __m128i psi_a_p3_m1 __attribute__((aligned(16))); + __m128i psi_a_p3_p1 __attribute__((aligned(16))); + __m128i psi_a_p3_p3 __attribute__((aligned(16))); + + __m128i a_sq_m3_m3 __attribute__((aligned(16))); + __m128i a_sq_m3_m1 __attribute__((aligned(16))); + __m128i a_sq_m3_p1 __attribute__((aligned(16))); + __m128i a_sq_m3_p3 __attribute__((aligned(16))); + __m128i a_sq_m1_m3 __attribute__((aligned(16))); + __m128i a_sq_m1_m1 __attribute__((aligned(16))); + __m128i a_sq_m1_p1 __attribute__((aligned(16))); + __m128i a_sq_m1_p3 __attribute__((aligned(16))); + __m128i a_sq_p1_m3 __attribute__((aligned(16))); + __m128i a_sq_p1_m1 __attribute__((aligned(16))); + __m128i a_sq_p1_p1 __attribute__((aligned(16))); + __m128i a_sq_p1_p3 __attribute__((aligned(16))); + __m128i a_sq_p3_m3 __attribute__((aligned(16))); + __m128i a_sq_p3_m1 __attribute__((aligned(16))); + __m128i a_sq_p3_p1 __attribute__((aligned(16))); + __m128i a_sq_p3_p3 __attribute__((aligned(16))); + + __m128i y0_p_1_1 __attribute__((aligned(16))); + __m128i y0_p_1_3 __attribute__((aligned(16))); + __m128i y0_p_3_1 __attribute__((aligned(16))); + __m128i y0_p_3_3 __attribute__((aligned(16))); + __m128i y0_m_1_1 __attribute__((aligned(16))); + __m128i y0_m_1_3 __attribute__((aligned(16))); + __m128i y0_m_3_1 __attribute__((aligned(16))); + __m128i y0_m_3_3 __attribute__((aligned(16))); + + __m128i y0r __attribute__((aligned(16))); + __m128i y0i __attribute__((aligned(16))); + __m128i y1r __attribute__((aligned(16))); + __m128i y1i __attribute__((aligned(16))); + + __m128i tmp_result __attribute__((aligned(16))); + __m128i tmp_result2 __attribute__((aligned(16))); + + // In one iteration, we deal with 8 REs + for (int i = 0; i < length >> 2; i += 2) { + + // Get rho + xmm0 = rho01_128i[i]; + xmm1 = rho01_128i[i + 1]; + xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + // xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + // xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + xmm2 = simde_mm_unpacklo_epi64(xmm0, xmm1); // Re(rho) + xmm3 = simde_mm_unpackhi_epi64(xmm0, xmm1); // Im(rho) + rho_rpi = simde_mm_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho) + rho_rmi = simde_mm_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho) + + // Compute the different rhos + rho_rpi_1_1 = simde_mm_mulhi_epi16(rho_rpi, ONE_OVER_SQRT_10); + rho_rmi_1_1 = simde_mm_mulhi_epi16(rho_rmi, ONE_OVER_SQRT_10); + rho_rpi_3_3 = simde_mm_mulhi_epi16(rho_rpi, THREE_OVER_SQRT_10); + rho_rmi_3_3 = simde_mm_mulhi_epi16(rho_rmi, THREE_OVER_SQRT_10); + rho_rpi_3_3 = simde_mm_slli_epi16(rho_rpi_3_3, 1); + rho_rmi_3_3 = simde_mm_slli_epi16(rho_rmi_3_3, 1); + + xmm4 = simde_mm_mulhi_epi16(xmm2, ONE_OVER_SQRT_10); // Re(rho) + xmm5 = simde_mm_mulhi_epi16(xmm3, THREE_OVER_SQRT_10); // Im(rho) + xmm5 = simde_mm_slli_epi16(xmm5, 1); + + rho_rpi_1_3 = simde_mm_adds_epi16(xmm4, xmm5); + rho_rmi_1_3 = simde_mm_subs_epi16(xmm4, xmm5); + + xmm6 = simde_mm_mulhi_epi16(xmm2, THREE_OVER_SQRT_10); // Re(rho) + xmm7 = simde_mm_mulhi_epi16(xmm3, ONE_OVER_SQRT_10); // Im(rho) + xmm6 = simde_mm_slli_epi16(xmm6, 1); + + rho_rpi_3_1 = simde_mm_adds_epi16(xmm6, xmm7); + rho_rmi_3_1 = simde_mm_subs_epi16(xmm6, xmm7); + + // Rearrange interfering MF output + xmm0 = stream1_128i_in[i]; + xmm1 = stream1_128i_in[i + 1]; + xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + // xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + // xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + y1r = simde_mm_unpacklo_epi64(xmm0, xmm1); //[y1r(1),y1r(2),y1r(3),y1r(4)] + y1i = simde_mm_unpackhi_epi64(xmm0, xmm1); //[y1i(1),y1i(2),y1i(3),y1i(4)] + + xmm0 = simde_mm_setzero_si128(); // ZERO + xmm2 = simde_mm_subs_epi16(rho_rpi_1_1, y1r); // = [Re(rho)+ Im(rho)]/sqrt(10) - y1r + psi_r_p1_p1 = simde_mm_abs_epi16(xmm2); // = |[Re(rho)+ Im(rho)]/sqrt(10) - y1r| + + xmm2 = simde_mm_subs_epi16(rho_rmi_1_1, y1r); + psi_r_p1_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_1_1, y1i); + psi_i_p1_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_1_3, y1r); + psi_r_p1_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_1_3, y1r); + psi_r_p1_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_3_1, y1i); + psi_i_p1_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_3_1, y1r); + psi_r_p3_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_3_1, y1r); + psi_r_p3_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_1_3, y1i); + psi_i_p3_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_3_3, y1r); + psi_r_p3_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_3_3, y1r); + psi_r_p3_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rmi_3_3, y1i); + psi_i_p3_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_1_1, y1i); + psi_i_m1_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_3_1, y1i); + psi_i_m1_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_1_3, y1i); + psi_i_m3_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_subs_epi16(rho_rpi_3_3, y1i); + psi_i_m3_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_1_1, y1i); + psi_i_p1_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_3_1, y1i); + psi_i_p1_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_1_3, y1i); + psi_i_p3_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_3_3, y1i); + psi_i_p3_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_1_1, y1r); + psi_r_m1_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_1_3, y1r); + psi_r_m1_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_3_1, y1r); + psi_r_m3_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(rho_rpi_3_3, y1r); + psi_r_m3_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1r, rho_rmi_1_1); + psi_r_m1_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1r, rho_rmi_1_3); + psi_r_m1_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1i, rho_rmi_1_1); + psi_i_m1_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1i, rho_rmi_3_1); + psi_i_m1_m3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1r, rho_rmi_3_1); + psi_r_m3_p1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1r, rho_rmi_3_3); + psi_r_m3_p3 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1i, rho_rmi_1_3); + psi_i_m3_m1 = simde_mm_abs_epi16(xmm2); + xmm2 = simde_mm_adds_epi16(y1i, rho_rmi_3_3); + psi_i_m3_m3 = simde_mm_abs_epi16(xmm2); + + // Rearrange desired MF output + xmm0 = stream0_128i_in[i]; + xmm1 = stream0_128i_in[i + 1]; + xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + // xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + // xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + y0r = simde_mm_unpacklo_epi64(xmm0, xmm1); // = [y0r(1),y0r(2),y0r(3),y0r(4)] + y0i = simde_mm_unpackhi_epi64(xmm0, xmm1); + + // Rearrange desired channel magnitudes + xmm2 = ch_mag_128i[i]; // = [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2)]*(2/sqrt(10)) + xmm3 = ch_mag_128i[i + 1]; // = [|h|^2(3),|h|^2(3),|h|^2(4),|h|^2(4)]*(2/sqrt(10)) + xmm2 = simde_mm_shufflelo_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = simde_mm_shufflehi_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = simde_mm_shuffle_epi32(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = simde_mm_shufflelo_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = simde_mm_shufflehi_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = simde_mm_shuffle_epi32(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + ch_mag_des = simde_mm_unpacklo_epi64(xmm2, xmm3); // = [|h|^2(1),|h|^2(2),|h|^2(3),|h|^2(4)]*(2/sqrt(10)) + + // Rearrange interfering channel magnitudes + xmm2 = ch_mag_128i_i[i]; + xmm3 = ch_mag_128i_i[i + 1]; + + xmm2 = simde_mm_shufflelo_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = simde_mm_shufflehi_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = simde_mm_shuffle_epi32(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = simde_mm_shufflelo_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = simde_mm_shufflehi_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = simde_mm_shuffle_epi32(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + ch_mag_int = simde_mm_unpacklo_epi64(xmm2, xmm3); + + // Scale MF output of desired signal + y0r_over_sqrt10 = simde_mm_mulhi_epi16(y0r, ONE_OVER_SQRT_10); + y0i_over_sqrt10 = simde_mm_mulhi_epi16(y0i, ONE_OVER_SQRT_10); + y0r_three_over_sqrt10 = simde_mm_mulhi_epi16(y0r, THREE_OVER_SQRT_10); + y0i_three_over_sqrt10 = simde_mm_mulhi_epi16(y0i, THREE_OVER_SQRT_10); + y0r_three_over_sqrt10 = simde_mm_slli_epi16(y0r_three_over_sqrt10, 1); + y0i_three_over_sqrt10 = simde_mm_slli_epi16(y0i_three_over_sqrt10, 1); + + // Compute necessary combination of required terms + y0_p_1_1 = simde_mm_adds_epi16(y0r_over_sqrt10, y0i_over_sqrt10); + y0_m_1_1 = simde_mm_subs_epi16(y0r_over_sqrt10, y0i_over_sqrt10); + + y0_p_1_3 = simde_mm_adds_epi16(y0r_over_sqrt10, y0i_three_over_sqrt10); + y0_m_1_3 = simde_mm_subs_epi16(y0r_over_sqrt10, y0i_three_over_sqrt10); + + y0_p_3_1 = simde_mm_adds_epi16(y0r_three_over_sqrt10, y0i_over_sqrt10); + y0_m_3_1 = simde_mm_subs_epi16(y0r_three_over_sqrt10, y0i_over_sqrt10); + + y0_p_3_3 = simde_mm_adds_epi16(y0r_three_over_sqrt10, y0i_three_over_sqrt10); + y0_m_3_3 = simde_mm_subs_epi16(y0r_three_over_sqrt10, y0i_three_over_sqrt10); + + // Compute optimal interfering symbol magnitude + interference_abs_epi16(psi_r_p1_p1, ch_mag_int, a_r_p1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_p1, ch_mag_int, a_i_p1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_p3, ch_mag_int, a_r_p1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_p3, ch_mag_int, a_i_p1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_m1, ch_mag_int, a_r_p1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_m1, ch_mag_int, a_i_p1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_m3, ch_mag_int, a_r_p1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_m3, ch_mag_int, a_i_p1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_p1, ch_mag_int, a_r_p3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_p1, ch_mag_int, a_i_p3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_p3, ch_mag_int, a_r_p3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_p3, ch_mag_int, a_i_p3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_m1, ch_mag_int, a_r_p3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_m1, ch_mag_int, a_i_p3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_m3, ch_mag_int, a_r_p3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_m3, ch_mag_int, a_i_p3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_p1, ch_mag_int, a_r_m1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_p1, ch_mag_int, a_i_m1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_p3, ch_mag_int, a_r_m1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_p3, ch_mag_int, a_i_m1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_m1, ch_mag_int, a_r_m1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_m1, ch_mag_int, a_i_m1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_m3, ch_mag_int, a_r_m1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_m3, ch_mag_int, a_i_m1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_p1, ch_mag_int, a_r_m3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_p1, ch_mag_int, a_i_m3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_p3, ch_mag_int, a_r_m3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_p3, ch_mag_int, a_i_m3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_m1, ch_mag_int, a_r_m3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_m1, ch_mag_int, a_i_m3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_m3, ch_mag_int, a_r_m3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_m3, ch_mag_int, a_i_m3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + + // Calculation of groups of two terms in the bit metric involving product of psi and interference magnitude + prodsum_psi_a_epi16(psi_r_p1_p1, a_r_p1_p1, psi_i_p1_p1, a_i_p1_p1, psi_a_p1_p1); + prodsum_psi_a_epi16(psi_r_p1_p3, a_r_p1_p3, psi_i_p1_p3, a_i_p1_p3, psi_a_p1_p3); + prodsum_psi_a_epi16(psi_r_p3_p1, a_r_p3_p1, psi_i_p3_p1, a_i_p3_p1, psi_a_p3_p1); + prodsum_psi_a_epi16(psi_r_p3_p3, a_r_p3_p3, psi_i_p3_p3, a_i_p3_p3, psi_a_p3_p3); + prodsum_psi_a_epi16(psi_r_p1_m1, a_r_p1_m1, psi_i_p1_m1, a_i_p1_m1, psi_a_p1_m1); + prodsum_psi_a_epi16(psi_r_p1_m3, a_r_p1_m3, psi_i_p1_m3, a_i_p1_m3, psi_a_p1_m3); + prodsum_psi_a_epi16(psi_r_p3_m1, a_r_p3_m1, psi_i_p3_m1, a_i_p3_m1, psi_a_p3_m1); + prodsum_psi_a_epi16(psi_r_p3_m3, a_r_p3_m3, psi_i_p3_m3, a_i_p3_m3, psi_a_p3_m3); + prodsum_psi_a_epi16(psi_r_m1_p1, a_r_m1_p1, psi_i_m1_p1, a_i_m1_p1, psi_a_m1_p1); + prodsum_psi_a_epi16(psi_r_m1_p3, a_r_m1_p3, psi_i_m1_p3, a_i_m1_p3, psi_a_m1_p3); + prodsum_psi_a_epi16(psi_r_m3_p1, a_r_m3_p1, psi_i_m3_p1, a_i_m3_p1, psi_a_m3_p1); + prodsum_psi_a_epi16(psi_r_m3_p3, a_r_m3_p3, psi_i_m3_p3, a_i_m3_p3, psi_a_m3_p3); + prodsum_psi_a_epi16(psi_r_m1_m1, a_r_m1_m1, psi_i_m1_m1, a_i_m1_m1, psi_a_m1_m1); + prodsum_psi_a_epi16(psi_r_m1_m3, a_r_m1_m3, psi_i_m1_m3, a_i_m1_m3, psi_a_m1_m3); + prodsum_psi_a_epi16(psi_r_m3_m1, a_r_m3_m1, psi_i_m3_m1, a_i_m3_m1, psi_a_m3_m1); + prodsum_psi_a_epi16(psi_r_m3_m3, a_r_m3_m3, psi_i_m3_m3, a_i_m3_m3, psi_a_m3_m3); + + // squared interference magnitude times int. ch. power + square_a_epi16(a_r_p1_p1, a_i_p1_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_p1); + square_a_epi16(a_r_p1_p3, a_i_p1_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_p3); + square_a_epi16(a_r_p3_p1, a_i_p3_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_p1); + square_a_epi16(a_r_p3_p3, a_i_p3_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_p3); + square_a_epi16(a_r_p1_m1, a_i_p1_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_m1); + square_a_epi16(a_r_p1_m3, a_i_p1_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_m3); + square_a_epi16(a_r_p3_m1, a_i_p3_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_m1); + square_a_epi16(a_r_p3_m3, a_i_p3_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_m3); + square_a_epi16(a_r_m1_p1, a_i_m1_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_p1); + square_a_epi16(a_r_m1_p3, a_i_m1_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_p3); + square_a_epi16(a_r_m3_p1, a_i_m3_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_p1); + square_a_epi16(a_r_m3_p3, a_i_m3_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_p3); + square_a_epi16(a_r_m1_m1, a_i_m1_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_m1); + square_a_epi16(a_r_m1_m3, a_i_m1_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_m3); + square_a_epi16(a_r_m3_m1, a_i_m3_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_m1); + square_a_epi16(a_r_m3_m3, a_i_m3_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_m3); + + // Computing different multiples of channel norms + ch_mag_over_10 = simde_mm_mulhi_epi16(ch_mag_des, ONE_OVER_TWO_SQRT_10); + ch_mag_over_2 = simde_mm_mulhi_epi16(ch_mag_des, SQRT_10_OVER_FOUR); + ch_mag_over_2 = simde_mm_slli_epi16(ch_mag_over_2, 1); + ch_mag_9_over_10 = simde_mm_mulhi_epi16(ch_mag_des, NINE_OVER_TWO_SQRT_10); + ch_mag_9_over_10 = simde_mm_slli_epi16(ch_mag_9_over_10, 2); + + /// Compute bit metrics (lambda) + + __m128i bit_met_p1_p1 = simde_mm_subs_epi16(psi_a_p1_p1, a_sq_p1_p1); + bit_met_p1_p1 = simde_mm_adds_epi16(bit_met_p1_p1, y0_p_1_1); + bit_met_p1_p1 = simde_mm_subs_epi16(bit_met_p1_p1, ch_mag_over_10); + + __m128i bit_met_p1_p3 = simde_mm_subs_epi16(psi_a_p1_p3, a_sq_p1_p3); + bit_met_p1_p3 = simde_mm_adds_epi16(bit_met_p1_p3, y0_p_1_3); + bit_met_p1_p3 = simde_mm_subs_epi16(bit_met_p1_p3, ch_mag_over_2); + + __m128i bit_met_p1_m1 = simde_mm_subs_epi16(psi_a_p1_m1, a_sq_p1_m1); + bit_met_p1_m1 = simde_mm_adds_epi16(bit_met_p1_m1, y0_m_1_1); + bit_met_p1_m1 = simde_mm_subs_epi16(bit_met_p1_m1, ch_mag_over_10); + + __m128i bit_met_p1_m3 = simde_mm_subs_epi16(psi_a_p1_m3, a_sq_p1_m3); + bit_met_p1_m3 = simde_mm_adds_epi16(bit_met_p1_m3, y0_m_1_3); + bit_met_p1_m3 = simde_mm_subs_epi16(bit_met_p1_m3, ch_mag_over_2); + + __m128i bit_met_p3_p1 = simde_mm_subs_epi16(psi_a_p3_p1, a_sq_p3_p1); + bit_met_p3_p1 = simde_mm_adds_epi16(bit_met_p3_p1, y0_p_3_1); + bit_met_p3_p1 = simde_mm_subs_epi16(bit_met_p3_p1, ch_mag_over_2); + + __m128i bit_met_p3_p3 = simde_mm_subs_epi16(psi_a_p3_p3, a_sq_p3_p3); + bit_met_p3_p3 = simde_mm_adds_epi16(bit_met_p3_p3, y0_p_3_3); + bit_met_p3_p3 = simde_mm_subs_epi16(bit_met_p3_p3, ch_mag_9_over_10); + + __m128i bit_met_p3_m1 = simde_mm_subs_epi16(psi_a_p3_m1, a_sq_p3_m1); + bit_met_p3_m1 = simde_mm_adds_epi16(bit_met_p3_m1, y0_m_3_1); + bit_met_p3_m1 = simde_mm_subs_epi16(bit_met_p3_m1, ch_mag_over_2); + + __m128i bit_met_p3_m3 = simde_mm_subs_epi16(psi_a_p3_m3, a_sq_p3_m3); + bit_met_p3_m3 = simde_mm_adds_epi16(bit_met_p3_m3, y0_m_3_3); + bit_met_p3_m3 = simde_mm_subs_epi16(bit_met_p3_m3, ch_mag_9_over_10); + + __m128i bit_met_m1_p1 = simde_mm_subs_epi16(psi_a_m1_p1, a_sq_m1_p1); + bit_met_m1_p1 = simde_mm_subs_epi16(bit_met_m1_p1, y0_m_1_1); + bit_met_m1_p1 = simde_mm_subs_epi16(bit_met_m1_p1, ch_mag_over_10); + + __m128i bit_met_m1_p3 = simde_mm_subs_epi16(psi_a_m1_p3, a_sq_m1_p3); + bit_met_m1_p3 = simde_mm_subs_epi16(bit_met_m1_p3, y0_m_1_3); + bit_met_m1_p3 = simde_mm_subs_epi16(bit_met_m1_p3, ch_mag_over_2); + + __m128i bit_met_m1_m1 = simde_mm_subs_epi16(psi_a_m1_m1, a_sq_m1_m1); + bit_met_m1_m1 = simde_mm_subs_epi16(bit_met_m1_m1, y0_p_1_1); + bit_met_m1_m1 = simde_mm_subs_epi16(bit_met_m1_m1, ch_mag_over_10); + + __m128i bit_met_m1_m3 = simde_mm_subs_epi16(psi_a_m1_m3, a_sq_m1_m3); + bit_met_m1_m3 = simde_mm_subs_epi16(bit_met_m1_m3, y0_p_1_3); + bit_met_m1_m3 = simde_mm_subs_epi16(bit_met_m1_m3, ch_mag_over_2); + + __m128i bit_met_m3_p1 = simde_mm_subs_epi16(psi_a_m3_p1, a_sq_m3_p1); + bit_met_m3_p1 = simde_mm_subs_epi16(bit_met_m3_p1, y0_m_3_1); + bit_met_m3_p1 = simde_mm_subs_epi16(bit_met_m3_p1, ch_mag_over_2); + + __m128i bit_met_m3_p3 = simde_mm_subs_epi16(psi_a_m3_p3, a_sq_m3_p3); + bit_met_m3_p3 = simde_mm_subs_epi16(bit_met_m3_p3, y0_m_3_3); + bit_met_m3_p3 = simde_mm_subs_epi16(bit_met_m3_p3, ch_mag_9_over_10); + + __m128i bit_met_m3_m1 = simde_mm_subs_epi16(psi_a_m3_m1, a_sq_m3_m1); + bit_met_m3_m1 = simde_mm_subs_epi16(bit_met_m3_m1, y0_p_3_1); + bit_met_m3_m1 = simde_mm_subs_epi16(bit_met_m3_m1, ch_mag_over_2); + + __m128i bit_met_m3_m3 = simde_mm_subs_epi16(psi_a_m3_m3, a_sq_m3_m3); + bit_met_m3_m3 = simde_mm_subs_epi16(bit_met_m3_m3, y0_p_3_3); + bit_met_m3_m3 = simde_mm_subs_epi16(bit_met_m3_m3, ch_mag_9_over_10); + + /// Compute the LLRs + + // LLR = lambda(c==1) - lambda(c==0) + + // LLR of the first bit: Bit = 1 + __m128i logmax_num_re0 = max_epi16(bit_met_m1_p1, + bit_met_m1_p3, + bit_met_m1_m1, + bit_met_m1_m3, + bit_met_m3_p1, + bit_met_m3_p3, + bit_met_m3_m1, + bit_met_m3_m3); + + // LLR of the first bit: Bit = 0 + __m128i logmax_den_re0 = max_epi16(bit_met_p1_p1, + bit_met_p1_p3, + bit_met_p1_m1, + bit_met_p1_m3, + bit_met_p3_p1, + bit_met_p3_p3, + bit_met_p3_m1, + bit_met_p3_m3); + + // LLR of the second bit: Bit = 1 + __m128i logmax_num_re1 = max_epi16(bit_met_p1_m1, + bit_met_p3_m1, + bit_met_m1_m1, + bit_met_m3_m1, + bit_met_p1_m3, + bit_met_p3_m3, + bit_met_m1_m3, + bit_met_m3_m3); + + // LLR of the second bit: Bit = 0 + __m128i logmax_den_re1 = max_epi16(bit_met_p1_p1, + bit_met_p3_p1, + bit_met_m1_p1, + bit_met_m3_p1, + bit_met_p1_p3, + bit_met_p3_p3, + bit_met_m1_p3, + bit_met_m3_p3); + + // LLR of the third bit: Bit = 1 + __m128i logmax_num_im0 = max_epi16(bit_met_m3_p1, + bit_met_m3_p3, + bit_met_m3_m1, + bit_met_m3_m3, + bit_met_p3_p1, + bit_met_p3_p3, + bit_met_p3_m1, + bit_met_p3_m3); + + // LLR of the third bit: Bit = 0 + __m128i logmax_den_im0 = max_epi16(bit_met_m1_p1, + bit_met_m1_p3, + bit_met_m1_m1, + bit_met_m1_m3, + bit_met_p1_p1, + bit_met_p1_p3, + bit_met_p1_m1, + bit_met_p1_m3); + + // LLR of the fourth bit: Bit = 1 + __m128i logmax_num_im1 = max_epi16(bit_met_p1_m3, + bit_met_p3_m3, + bit_met_m1_m3, + bit_met_m3_m3, + bit_met_p1_p3, + bit_met_p3_p3, + bit_met_m1_p3, + bit_met_m3_p3); + + // LLR of the fourth bit: Bit = 0 + __m128i logmax_den_im1 = max_epi16(bit_met_p1_m1, + bit_met_p3_m1, + bit_met_m1_m1, + bit_met_m3_m1, + bit_met_p1_p1, + bit_met_p3_p1, + bit_met_m1_p1, + bit_met_m3_p1); + + y0r = simde_mm_subs_epi16(logmax_den_re0, logmax_num_re0); // LLR of first bit [L1(1), L1(2), L1(3), L1(4), L1(5), L1(6), L1(7), L1(8)] + y1r = simde_mm_subs_epi16(logmax_den_re1, logmax_num_re1); // LLR of second bit [L2(1), L2(2), L2(3), L2(4), L2(5), L2(6), L2(7), L2(8)] + y0i = simde_mm_subs_epi16(logmax_den_im0, logmax_num_im0); // LLR of third bit [L3(1), L3(2), L3(3), L3(4), L3(5), L3(6), L3(7), L3(8)] + y1i = simde_mm_subs_epi16(logmax_den_im1, logmax_num_im1); // LLR of fourth bit [L4(1), L4(2), L4(3), L4(4), L4(5), L4(6), L4(7), L4(8)] + + // Pack LLRs in output + xmm0 = simde_mm_unpacklo_epi16(y0r, y1r); // [L1(1), L2(1), L1(2), L2(2), L1(3), L2(3), L1(4), L2(4)] + xmm1 = simde_mm_unpackhi_epi16(y0r, y1r); // [L1(5), L2(5), L1(6), L2(6), L1(7), L2(7), L1(8), L2(8)] + xmm2 = simde_mm_unpacklo_epi16(y0i, y1i); // [L3(1), L4(1), L3(2), L4(2), L3(3), L4(3), L3(4), L4(4)] + xmm3 = simde_mm_unpackhi_epi16(y0i, y1i); // [L3(5), L4(5), L3(6), L4(6), L3(7), L4(7), L3(8), L4(8)] + stream0_128i_out[2 * i + 0] = simde_mm_unpacklo_epi32(xmm0, xmm2); // 8 LLRs, 2 REs + stream0_128i_out[2 * i + 1] = simde_mm_unpackhi_epi32(xmm0, xmm2); // 8 LLRs, 2 REs + stream0_128i_out[2 * i + 2] = simde_mm_unpacklo_epi32(xmm1, xmm3); // 8 LLRs, 2 REs + stream0_128i_out[2 * i + 3] = simde_mm_unpackhi_epi32(xmm1, xmm3); // 8 LLRs, 2 REs + } + + _mm_empty(); + _m_empty(); +} void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, + int32_t **ul_ch_mag, int32_t ***rho, int16_t **llr_layers, uint8_t nb_antennas_rx, @@ -732,6 +1390,8 @@ void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, int off = ((rb_size & 1) == 1) ? 4 : 0; c16_t *rxdataF_comp0 = (c16_t *)&rxdataF_comp[0][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; c16_t *rxdataF_comp1 = (c16_t *)&rxdataF_comp[nb_antennas_rx][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; + c16_t *ul_ch_mag0 = (c16_t *)&ul_ch_mag[0][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; + c16_t *ul_ch_mag1 = (c16_t *)&ul_ch_mag[nb_antennas_rx][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; c16_t *llr_layers0 = (c16_t *)&llr_layers[0][rxdataF_ext_offset * mod_order]; c16_t *llr_layers1 = (c16_t *)&llr_layers[1][rxdataF_ext_offset * mod_order]; c16_t *rho0 = (c16_t *)&rho[0][1][symbol * (off + (rb_size * NR_NB_SC_PER_RB))]; @@ -743,6 +1403,9 @@ void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, nr_ulsch_qpsk_qpsk(rxdataF_comp1, rxdataF_comp0, llr_layers1, rho1, nb_re); break; case 4: + nr_ulsch_qam16_qam16(rxdataF_comp0, rxdataF_comp1, ul_ch_mag0, ul_ch_mag1, llr_layers0, rho0, nb_re); + nr_ulsch_qam16_qam16(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); + break; case 6: AssertFatal(1 == 0, "LLR computation is not implemented yet for ML with Qm = %d\n", mod_order); default: From 8a820db22f449ef6ca6fc6d613fba2a68368dffd Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 20 Apr 2023 19:06:22 +0100 Subject: [PATCH 022/119] Compute LLR for 64QAM for ML --- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 2628 ++++++++++++++++- 1 file changed, 2627 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 924c68a1f4..0ecadd6646 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -1376,6 +1376,2630 @@ void nr_ulsch_qam16_qam16(c16_t *stream0_in, _m_empty(); } +static const int16_t ones256[16] __attribute__((aligned(32))) = {0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff}; + +/// Auxiliary Makros + +// calculate interference magnitude +// tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 +#define interference_abs_64qam_epi16_256(psi, int_ch_mag, int_two_ch_mag, int_three_ch_mag, a, c1, c3, c5, c7) \ + tmp_result = simde_mm256_cmpgt_epi16(int_two_ch_mag, psi); \ + tmp_result3 = simde_mm256_xor_si256(tmp_result, (*(__m256i *)&ones256[0])); \ + tmp_result2 = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ + tmp_result = simde_mm256_xor_si256(tmp_result, tmp_result2); \ + tmp_result4 = simde_mm256_cmpgt_epi16(psi, int_three_ch_mag); \ + tmp_result3 = simde_mm256_xor_si256(tmp_result3, tmp_result4); \ + tmp_result = simde_mm256_and_si256(tmp_result, c3); \ + tmp_result2 = simde_mm256_and_si256(tmp_result2, c1); \ + tmp_result3 = simde_mm256_and_si256(tmp_result3, c5); \ + tmp_result4 = simde_mm256_and_si256(tmp_result4, c7); \ + tmp_result = simde_mm256_or_si256(tmp_result, tmp_result2); \ + tmp_result3 = simde_mm256_or_si256(tmp_result3, tmp_result4); \ + const simde__m256i a = simde_mm256_or_si256(tmp_result, tmp_result3); + +// calculates psi_a = psi_r*a_r + psi_i*a_i +#define prodsum_psi_a_epi16_256(psi_r, a_r, psi_i, a_i, psi_a) \ + tmp_result = simde_mm256_mulhi_epi16(psi_r, a_r); \ + tmp_result = simde_mm256_slli_epi16(tmp_result, 1); \ + tmp_result2 = simde_mm256_mulhi_epi16(psi_i, a_i); \ + tmp_result2 = simde_mm256_slli_epi16(tmp_result2, 1); \ + simde__m256i psi_a = simde_mm256_adds_epi16(tmp_result, tmp_result2); + +// calculates a_sq = int_ch_mag*(a_r^2 + a_i^2)*scale_factor for 64-QAM +#define square_a_64qam_epi16_256(a_r, a_i, int_ch_mag, scale_factor, a_sq) \ + tmp_result = simde_mm256_mulhi_epi16(a_r, a_r); \ + tmp_result = simde_mm256_slli_epi16(tmp_result, 1); \ + tmp_result = simde_mm256_mulhi_epi16(tmp_result, scale_factor); \ + tmp_result = simde_mm256_slli_epi16(tmp_result, 3); \ + tmp_result = simde_mm256_mulhi_epi16(tmp_result, int_ch_mag); \ + tmp_result = simde_mm256_slli_epi16(tmp_result, 1); \ + tmp_result2 = simde_mm256_mulhi_epi16(a_i, a_i); \ + tmp_result2 = simde_mm256_slli_epi16(tmp_result2, 1); \ + tmp_result2 = simde_mm256_mulhi_epi16(tmp_result2, scale_factor); \ + tmp_result2 = simde_mm256_slli_epi16(tmp_result2, 3); \ + tmp_result2 = simde_mm256_mulhi_epi16(tmp_result2, int_ch_mag); \ + tmp_result2 = simde_mm256_slli_epi16(tmp_result2, 1); \ + const simde__m256i a_sq = simde_mm256_adds_epi16(tmp_result, tmp_result2); + +void separate_real_imag_parts(__m256i *out_re, __m256i *out_im, __m256i in0, __m256i in1) +{ + in0 = simde_mm256_shufflelo_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = simde_mm256_shufflehi_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = simde_mm256_shuffle_epi32(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + in1 = simde_mm256_shufflelo_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = simde_mm256_shufflehi_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = simde_mm256_shuffle_epi32(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // in0 = [Re(0,1,2,3) Im(0,1,2,3) Re(4,5,6,7) Im(4,5,6,7)] + // in0 = [Re(8,9,10,11) Im(8,9,10,11) Re(12,13,14,15) Im(12,13,14,15)] + + __m256i tmp0 = simde_mm256_unpacklo_epi64(in0, in1); + // axmm2 = [Re(0,1,2,3) Re(8,9,10,11) Re(4,5,6,7) Re(12,13,14,15)] + tmp0 = simde_mm256_permute4x64_epi64(tmp0, 0xd8); // Re(rho) + + __m256i tmp1 = simde_mm256_unpackhi_epi64(in0, in1); + // axmm3 = [Im(0,1,2,3) Im(8,9,10,11) Im(4,5,6,7) Im(12,13,14,15)] + tmp1 = simde_mm256_permute4x64_epi64(tmp1, 0xd8); // Im(rho) + + *out_re = tmp0; + *out_im = tmp1; +} + +/* + * This function computes the LLRs of stream 0 (s_0) in presence of the interfering stream 1 (s_1) assuming that both symbols are + * 64QAM. It can be used for both MU-MIMO interference-aware receiver or for SU-MIMO receivers. + * + * Input: + * stream0_in: MF filter output for 1st stream, i.e., y0' = h0'*y0 + * stream1_in: MF filter output for 2nd stream, i.e., y1' = h1'*y0 + * ch_mag: 4*h0/sqrt(42), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + * ch_mag_i: 4*h0/sqrt(42), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + * rho01: Channel cross correlation, i.e., rho01 = h0'*h1 + * length: Number of resource elements + * + * Output: + * stream0_out: Output LLRs for 1st stream + */ +void nr_ulsch_qam64_qam64(c16_t *stream0_in, + c16_t *stream1_in, + c16_t *ch_mag, + c16_t *ch_mag_i, + c16_t *stream0_out, + c16_t *rho01, + uint32_t length) +{ + __m256i *rho01_256i = (__m256i *)rho01; + __m256i *stream0_256i_in = (__m256i *)stream0_in; + __m256i *stream1_256i_in = (__m256i *)stream1_in; + __m256i *ch_mag_256i = (__m256i *)ch_mag; + __m256i *ch_mag_256i_i = (__m256i *)ch_mag_i; + + __m256i ONE_OVER_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(10112)); // round(1/sqrt(42)*2^16) + __m256i THREE_OVER_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(30337)); // round(3/sqrt(42)*2^16) + __m256i FIVE_OVER_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(25281)); // round(5/sqrt(42)*2^15) + __m256i SEVEN_OVER_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(17697)); // round(7/sqrt(42)*2^14) Q2.14 + __m256i ONE_OVER_SQRT_2 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(23170)); // round(1/sqrt(2)*2^15) + __m256i ONE_OVER_SQRT_2_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(3575)); // round(1/sqrt(2*42)*2^15) + __m256i THREE_OVER_SQRT_2_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(10726)); // round(3/sqrt(2*42)*2^15) + __m256i FIVE_OVER_SQRT_2_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(17876)); // round(5/sqrt(2*42)*2^15) + __m256i SEVEN_OVER_SQRT_2_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(25027)); // round(7/sqrt(2*42)*2^15) + __m256i FORTYNINE_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(30969)); // round(49/(4*sqrt(42))*2^14), Q2.14 + __m256i THIRTYSEVEN_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(23385)); // round(37/(4*sqrt(42))*2^14), Q2.14 + __m256i TWENTYFIVE_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(31601)); // round(25/(4*sqrt(42))*2^15) + __m256i TWENTYNINE_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(18329)); // round(29/(4*sqrt(42))*2^15), Q2.14 + __m256i SEVENTEEN_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(21489)); // round(17/(4*sqrt(42))*2^15) + __m256i NINE_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(11376)); // round(9/(4*sqrt(42))*2^15) + __m256i THIRTEEN_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(16433)); // round(13/(4*sqrt(42))*2^15) + __m256i FIVE_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(6320)); // round(5/(4*sqrt(42))*2^15) + __m256i ONE_OVER_FOUR_SQRT_42 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(1264)); // round(1/(4*sqrt(42))*2^15) + __m256i SQRT_42_OVER_FOUR = simde_mm256_broadcastw_epi16(_mm_set1_epi16(13272)); // round(sqrt(42)/4*2^13), Q3.12 + + __m256i ch_mag_des; + __m256i ch_mag_int; + __m256i ch_mag_98_over_42_with_sigma2; + __m256i ch_mag_74_over_42_with_sigma2; + __m256i ch_mag_58_over_42_with_sigma2; + __m256i ch_mag_50_over_42_with_sigma2; + __m256i ch_mag_34_over_42_with_sigma2; + __m256i ch_mag_18_over_42_with_sigma2; + __m256i ch_mag_26_over_42_with_sigma2; + __m256i ch_mag_10_over_42_with_sigma2; + __m256i ch_mag_2_over_42_with_sigma2; + __m256i y0r_one_over_sqrt_21; + __m256i y0r_three_over_sqrt_21; + __m256i y0r_five_over_sqrt_21; + __m256i y0r_seven_over_sqrt_21; + __m256i y0i_one_over_sqrt_21; + __m256i y0i_three_over_sqrt_21; + __m256i y0i_five_over_sqrt_21; + __m256i y0i_seven_over_sqrt_21; + __m256i ch_mag_int_with_sigma2; + __m256i two_ch_mag_int_with_sigma2; + __m256i three_ch_mag_int_with_sigma2; + + uint32_t len256 = length >> 3; + + for (int i = 0; i < len256; i += 2) { + + // Get rho + simde__m256i xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + separate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i + 1]); + + simde__m256i rho_rpi = simde_mm256_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho) + simde__m256i rho_rmi = simde_mm256_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho) + + // Compute the different rhos + simde__m256i rho_rpi_1_1 = simde_mm256_mulhi_epi16(rho_rpi, ONE_OVER_SQRT_42); + simde__m256i rho_rmi_1_1 = simde_mm256_mulhi_epi16(rho_rmi, ONE_OVER_SQRT_42); + simde__m256i rho_rpi_3_3 = simde_mm256_mulhi_epi16(rho_rpi, THREE_OVER_SQRT_42); + simde__m256i rho_rmi_3_3 = simde_mm256_mulhi_epi16(rho_rmi, THREE_OVER_SQRT_42); + simde__m256i rho_rpi_5_5 = simde_mm256_mulhi_epi16(rho_rpi, FIVE_OVER_SQRT_42); + simde__m256i rho_rmi_5_5 = simde_mm256_mulhi_epi16(rho_rmi, FIVE_OVER_SQRT_42); + simde__m256i rho_rpi_7_7 = simde_mm256_mulhi_epi16(rho_rpi, SEVEN_OVER_SQRT_42); + simde__m256i rho_rmi_7_7 = simde_mm256_mulhi_epi16(rho_rmi, SEVEN_OVER_SQRT_42); + + rho_rpi_5_5 = simde_mm256_slli_epi16(rho_rpi_5_5, 1); + rho_rmi_5_5 = simde_mm256_slli_epi16(rho_rmi_5_5, 1); + rho_rpi_7_7 = simde_mm256_slli_epi16(rho_rpi_7_7, 2); + rho_rmi_7_7 = simde_mm256_slli_epi16(rho_rmi_7_7, 2); + + xmm4 = simde_mm256_mulhi_epi16(xmm2, ONE_OVER_SQRT_42); + xmm5 = simde_mm256_mulhi_epi16(xmm3, ONE_OVER_SQRT_42); + xmm6 = simde_mm256_mulhi_epi16(xmm3, THREE_OVER_SQRT_42); + xmm7 = simde_mm256_mulhi_epi16(xmm3, FIVE_OVER_SQRT_42); + xmm8 = simde_mm256_mulhi_epi16(xmm3, SEVEN_OVER_SQRT_42); + xmm7 = simde_mm256_slli_epi16(xmm7, 1); + xmm8 = simde_mm256_slli_epi16(xmm8, 2); + + simde__m256i rho_rpi_1_3 = simde_mm256_adds_epi16(xmm4, xmm6); + simde__m256i rho_rmi_1_3 = simde_mm256_subs_epi16(xmm4, xmm6); + simde__m256i rho_rpi_1_5 = simde_mm256_adds_epi16(xmm4, xmm7); + simde__m256i rho_rmi_1_5 = simde_mm256_subs_epi16(xmm4, xmm7); + simde__m256i rho_rpi_1_7 = simde_mm256_adds_epi16(xmm4, xmm8); + simde__m256i rho_rmi_1_7 = simde_mm256_subs_epi16(xmm4, xmm8); + + xmm4 = simde_mm256_mulhi_epi16(xmm2, THREE_OVER_SQRT_42); + simde__m256i rho_rpi_3_1 = simde_mm256_adds_epi16(xmm4, xmm5); + simde__m256i rho_rmi_3_1 = simde_mm256_subs_epi16(xmm4, xmm5); + simde__m256i rho_rpi_3_5 = simde_mm256_adds_epi16(xmm4, xmm7); + simde__m256i rho_rmi_3_5 = simde_mm256_subs_epi16(xmm4, xmm7); + simde__m256i rho_rpi_3_7 = simde_mm256_adds_epi16(xmm4, xmm8); + simde__m256i rho_rmi_3_7 = simde_mm256_subs_epi16(xmm4, xmm8); + + xmm4 = simde_mm256_mulhi_epi16(xmm2, FIVE_OVER_SQRT_42); + xmm4 = simde_mm256_slli_epi16(xmm4, 1); + simde__m256i rho_rpi_5_1 = simde_mm256_adds_epi16(xmm4, xmm5); + simde__m256i rho_rmi_5_1 = simde_mm256_subs_epi16(xmm4, xmm5); + simde__m256i rho_rpi_5_3 = simde_mm256_adds_epi16(xmm4, xmm6); + simde__m256i rho_rmi_5_3 = simde_mm256_subs_epi16(xmm4, xmm6); + simde__m256i rho_rpi_5_7 = simde_mm256_adds_epi16(xmm4, xmm8); + simde__m256i rho_rmi_5_7 = simde_mm256_subs_epi16(xmm4, xmm8); + + xmm4 = simde_mm256_mulhi_epi16(xmm2, SEVEN_OVER_SQRT_42); + xmm4 = simde_mm256_slli_epi16(xmm4, 2); + simde__m256i rho_rpi_7_1 = simde_mm256_adds_epi16(xmm4, xmm5); + simde__m256i rho_rmi_7_1 = simde_mm256_subs_epi16(xmm4, xmm5); + simde__m256i rho_rpi_7_3 = simde_mm256_adds_epi16(xmm4, xmm6); + simde__m256i rho_rmi_7_3 = simde_mm256_subs_epi16(xmm4, xmm6); + simde__m256i rho_rpi_7_5 = simde_mm256_adds_epi16(xmm4, xmm7); + simde__m256i rho_rmi_7_5 = simde_mm256_subs_epi16(xmm4, xmm7); + + // Rearrange interfering MF output + simde__m256i y1r, y1i, xmm0; + separate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i + 1]); + + // Psi_r calculation from rho_rpi or rho_rmi + xmm0 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(0)); // ZERO for abs_pi16 + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_7, y1r); + + simde__m256i psi_r_p7_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_5, y1r); + simde__m256i psi_r_p7_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_3, y1r); + simde__m256i psi_r_p7_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_1, y1r); + simde__m256i psi_r_p7_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_1, y1r); + simde__m256i psi_r_p7_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_3, y1r); + simde__m256i psi_r_p7_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_5, y1r); + simde__m256i psi_r_p7_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_7, y1r); + simde__m256i psi_r_p7_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_7, y1r); + simde__m256i psi_r_p5_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_5, y1r); + simde__m256i psi_r_p5_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_3, y1r); + simde__m256i psi_r_p5_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_1, y1r); + simde__m256i psi_r_p5_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_1, y1r); + simde__m256i psi_r_p5_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_3, y1r); + simde__m256i psi_r_p5_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_5, y1r); + simde__m256i psi_r_p5_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_7, y1r); + simde__m256i psi_r_p5_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_7, y1r); + simde__m256i psi_r_p3_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_5, y1r); + simde__m256i psi_r_p3_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_3, y1r); + simde__m256i psi_r_p3_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_1, y1r); + simde__m256i psi_r_p3_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_1, y1r); + simde__m256i psi_r_p3_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_3, y1r); + simde__m256i psi_r_p3_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_5, y1r); + simde__m256i psi_r_p3_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_7, y1r); + simde__m256i psi_r_p3_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_7, y1r); + simde__m256i psi_r_p1_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_5, y1r); + simde__m256i psi_r_p1_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_3, y1r); + simde__m256i psi_r_p1_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_1, y1r); + simde__m256i psi_r_p1_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_1, y1r); + simde__m256i psi_r_p1_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_3, y1r); + simde__m256i psi_r_p1_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_5, y1r); + simde__m256i psi_r_p1_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_7, y1r); + simde__m256i psi_r_p1_m7 = simde_mm256_abs_epi16(xmm2); + + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_7, y1r); + simde__m256i psi_r_m1_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_5, y1r); + simde__m256i psi_r_m1_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_3, y1r); + simde__m256i psi_r_m1_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_1, y1r); + simde__m256i psi_r_m1_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_1, y1r); + simde__m256i psi_r_m1_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_3, y1r); + simde__m256i psi_r_m1_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_5, y1r); + simde__m256i psi_r_m1_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_7, y1r); + simde__m256i psi_r_m1_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_7, y1r); + simde__m256i psi_r_m3_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_5, y1r); + simde__m256i psi_r_m3_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_3, y1r); + simde__m256i psi_r_m3_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_1, y1r); + simde__m256i psi_r_m3_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_1, y1r); + simde__m256i psi_r_m3_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_3, y1r); + simde__m256i psi_r_m3_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_5, y1r); + simde__m256i psi_r_m3_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_7, y1r); + simde__m256i psi_r_m3_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_7, y1r); + simde__m256i psi_r_m5_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_5, y1r); + simde__m256i psi_r_m5_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_3, y1r); + simde__m256i psi_r_m5_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_1, y1r); + simde__m256i psi_r_m5_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_1, y1r); + simde__m256i psi_r_m5_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_3, y1r); + simde__m256i psi_r_m5_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_5, y1r); + simde__m256i psi_r_m5_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_7, y1r); + simde__m256i psi_r_m5_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_7, y1r); + simde__m256i psi_r_m7_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_5, y1r); + simde__m256i psi_r_m7_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_3, y1r); + simde__m256i psi_r_m7_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_1, y1r); + simde__m256i psi_r_m7_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_1, y1r); + simde__m256i psi_r_m7_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_3, y1r); + simde__m256i psi_r_m7_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_5, y1r); + simde__m256i psi_r_m7_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_7, y1r); + simde__m256i psi_r_m7_m7 = simde_mm256_abs_epi16(xmm2); + + // Simde__M256i Psi_i calculation from rho_rpi or rho_rmi + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_7, y1i); + simde__m256i psi_i_p7_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_7, y1i); + simde__m256i psi_i_p7_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_7, y1i); + simde__m256i psi_i_p7_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_7, y1i); + simde__m256i psi_i_p7_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_7, y1i); + simde__m256i psi_i_p7_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_7, y1i); + simde__m256i psi_i_p7_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_7, y1i); + simde__m256i psi_i_p7_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_7, y1i); + simde__m256i psi_i_p7_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_5, y1i); + simde__m256i psi_i_p5_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_5, y1i); + simde__m256i psi_i_p5_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_5, y1i); + simde__m256i psi_i_p5_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_5, y1i); + simde__m256i psi_i_p5_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_5, y1i); + simde__m256i psi_i_p5_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_5, y1i); + simde__m256i psi_i_p5_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_5, y1i); + simde__m256i psi_i_p5_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_5, y1i); + simde__m256i psi_i_p5_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_3, y1i); + simde__m256i psi_i_p3_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_3, y1i); + simde__m256i psi_i_p3_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_3, y1i); + simde__m256i psi_i_p3_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_3, y1i); + simde__m256i psi_i_p3_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_3, y1i); + simde__m256i psi_i_p3_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_3, y1i); + simde__m256i psi_i_p3_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_3, y1i); + simde__m256i psi_i_p3_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_3, y1i); + simde__m256i psi_i_p3_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_7_1, y1i); + simde__m256i psi_i_p1_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_5_1, y1i); + simde__m256i psi_i_p1_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_3_1, y1i); + simde__m256i psi_i_p1_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rmi_1_1, y1i); + simde__m256i psi_i_p1_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_1_1, y1i); + simde__m256i psi_i_p1_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_3_1, y1i); + simde__m256i psi_i_p1_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_5_1, y1i); + simde__m256i psi_i_p1_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rpi_7_1, y1i); + simde__m256i psi_i_p1_m7 = simde_mm256_abs_epi16(xmm2); + + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_1, y1i); + simde__m256i psi_i_m1_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_1, y1i); + simde__m256i psi_i_m1_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_1, y1i); + simde__m256i psi_i_m1_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_1, y1i); + simde__m256i psi_i_m1_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_1, y1i); + simde__m256i psi_i_m1_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_1, y1i); + simde__m256i psi_i_m1_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_1, y1i); + simde__m256i psi_i_m1_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_1, y1i); + simde__m256i psi_i_m1_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_3, y1i); + simde__m256i psi_i_m3_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_3, y1i); + simde__m256i psi_i_m3_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_3, y1i); + simde__m256i psi_i_m3_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_3, y1i); + simde__m256i psi_i_m3_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_3, y1i); + simde__m256i psi_i_m3_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_3, y1i); + simde__m256i psi_i_m3_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_3, y1i); + simde__m256i psi_i_m3_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_3, y1i); + simde__m256i psi_i_m3_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_5, y1i); + simde__m256i psi_i_m5_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_5, y1i); + simde__m256i psi_i_m5_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_5, y1i); + simde__m256i psi_i_m5_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_5, y1i); + simde__m256i psi_i_m5_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_5, y1i); + simde__m256i psi_i_m5_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_5, y1i); + simde__m256i psi_i_m5_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_5, y1i); + simde__m256i psi_i_m5_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_5, y1i); + simde__m256i psi_i_m5_m7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_7_7, y1i); + simde__m256i psi_i_m7_p7 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_5_7, y1i); + simde__m256i psi_i_m7_p5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_3_7, y1i); + simde__m256i psi_i_m7_p3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_subs_epi16(rho_rpi_1_7, y1i); + simde__m256i psi_i_m7_p1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_1_7, y1i); + simde__m256i psi_i_m7_m1 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_3_7, y1i); + simde__m256i psi_i_m7_m3 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_5_7, y1i); + simde__m256i psi_i_m7_m5 = simde_mm256_abs_epi16(xmm2); + xmm2 = simde_mm256_adds_epi16(rho_rmi_7_7, y1i); + simde__m256i psi_i_m7_m7 = simde_mm256_abs_epi16(xmm2); + + // Rearrange desired MF output + simde__m256i y0r, y0i; + separate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i + 1]); + + // Rearrange desired channel magnitudes + // [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2),...,,|h|^2(7),|h|^2(7)]*(2/sqrt(10)) + // xmm2 is dummy variable that contains the same values as ch_mag_des + separate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i + 1]); + + // Rearrange interfering channel magnitudes + separate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i + 1]); + + y0r_one_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, ONE_OVER_SQRT_42); + y0r_three_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, THREE_OVER_SQRT_42); + y0r_five_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, FIVE_OVER_SQRT_42); + y0r_five_over_sqrt_21 = simde_mm256_slli_epi16(y0r_five_over_sqrt_21, 1); + y0r_seven_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, SEVEN_OVER_SQRT_42); + y0r_seven_over_sqrt_21 = simde_mm256_slli_epi16(y0r_seven_over_sqrt_21, 2); // Q2.14 + + y0i_one_over_sqrt_21 = simde_mm256_mulhi_epi16(y0i, ONE_OVER_SQRT_42); + y0i_three_over_sqrt_21 = simde_mm256_mulhi_epi16(y0i, THREE_OVER_SQRT_42); + y0i_five_over_sqrt_21 = simde_mm256_mulhi_epi16(y0i, FIVE_OVER_SQRT_42); + y0i_five_over_sqrt_21 = simde_mm256_slli_epi16(y0i_five_over_sqrt_21, 1); + y0i_seven_over_sqrt_21 = simde_mm256_mulhi_epi16(y0i, SEVEN_OVER_SQRT_42); + y0i_seven_over_sqrt_21 = simde_mm256_slli_epi16(y0i_seven_over_sqrt_21, 2); // Q2.14 + + simde__m256i y0_p_7_1 = simde_mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_p_7_3 = simde_mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_p_7_5 = simde_mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_p_7_7 = simde_mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); + simde__m256i y0_p_5_1 = simde_mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_p_5_3 = simde_mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_p_5_5 = simde_mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_p_5_7 = simde_mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_seven_over_sqrt_21); + simde__m256i y0_p_3_1 = simde_mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_p_3_3 = simde_mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_p_3_5 = simde_mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_p_3_7 = simde_mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_seven_over_sqrt_21); + simde__m256i y0_p_1_1 = simde_mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_p_1_3 = simde_mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_p_1_5 = simde_mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_p_1_7 = simde_mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_seven_over_sqrt_21); + + simde__m256i y0_m_1_1 = simde_mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_m_1_3 = simde_mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_m_1_5 = simde_mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_m_1_7 = simde_mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_seven_over_sqrt_21); + simde__m256i y0_m_3_1 = simde_mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_m_3_3 = simde_mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_m_3_5 = simde_mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_m_3_7 = simde_mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_seven_over_sqrt_21); + simde__m256i y0_m_5_1 = simde_mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_m_5_3 = simde_mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_m_5_5 = simde_mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_m_5_7 = simde_mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_seven_over_sqrt_21); + simde__m256i y0_m_7_1 = simde_mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_one_over_sqrt_21); + simde__m256i y0_m_7_3 = simde_mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_three_over_sqrt_21); + simde__m256i y0_m_7_5 = simde_mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); + simde__m256i y0_m_7_7 = simde_mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); + + // Detection of interference term + ch_mag_int_with_sigma2 = simde_mm256_srai_epi16(ch_mag_int, 1); // *2 + two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 + three_ch_mag_int_with_sigma2 = simde_mm256_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 + simde__m256i tmp_result, tmp_result2, tmp_result3, tmp_result4; + interference_abs_64qam_epi16_256(psi_r_p7_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p7_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p7_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p5_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p5_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p3_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p3_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_p1_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_p1_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m1_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m1_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m3_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m3_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m5_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m5_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_r_m7_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_r_m7_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + + interference_abs_64qam_epi16_256(psi_i_p7_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p7_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p7_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p5_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p5_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p3_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p3_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_p1_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_p1_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m1_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m1_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m3_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m3_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m5_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m5_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_p7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_p7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_p5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_p5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_p3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_p3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_p1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_p1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_m1, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_m1, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_m3, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_m3, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_m5, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_m5, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16_256(psi_i_m7_m7, + ch_mag_int_with_sigma2, + two_ch_mag_int_with_sigma2, + three_ch_mag_int_with_sigma2, + a_i_m7_m7, + ONE_OVER_SQRT_2_42, + THREE_OVER_SQRT_2_42, + FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + + // Calculation of a group of two terms in the bit metric involving product of psi and interference + prodsum_psi_a_epi16_256(psi_r_p7_p7, a_r_p7_p7, psi_i_p7_p7, a_i_p7_p7, psi_a_p7_p7); + prodsum_psi_a_epi16_256(psi_r_p7_p5, a_r_p7_p5, psi_i_p7_p5, a_i_p7_p5, psi_a_p7_p5); + prodsum_psi_a_epi16_256(psi_r_p7_p3, a_r_p7_p3, psi_i_p7_p3, a_i_p7_p3, psi_a_p7_p3); + prodsum_psi_a_epi16_256(psi_r_p7_p1, a_r_p7_p1, psi_i_p7_p1, a_i_p7_p1, psi_a_p7_p1); + prodsum_psi_a_epi16_256(psi_r_p7_m1, a_r_p7_m1, psi_i_p7_m1, a_i_p7_m1, psi_a_p7_m1); + prodsum_psi_a_epi16_256(psi_r_p7_m3, a_r_p7_m3, psi_i_p7_m3, a_i_p7_m3, psi_a_p7_m3); + prodsum_psi_a_epi16_256(psi_r_p7_m5, a_r_p7_m5, psi_i_p7_m5, a_i_p7_m5, psi_a_p7_m5); + prodsum_psi_a_epi16_256(psi_r_p7_m7, a_r_p7_m7, psi_i_p7_m7, a_i_p7_m7, psi_a_p7_m7); + prodsum_psi_a_epi16_256(psi_r_p5_p7, a_r_p5_p7, psi_i_p5_p7, a_i_p5_p7, psi_a_p5_p7); + prodsum_psi_a_epi16_256(psi_r_p5_p5, a_r_p5_p5, psi_i_p5_p5, a_i_p5_p5, psi_a_p5_p5); + prodsum_psi_a_epi16_256(psi_r_p5_p3, a_r_p5_p3, psi_i_p5_p3, a_i_p5_p3, psi_a_p5_p3); + prodsum_psi_a_epi16_256(psi_r_p5_p1, a_r_p5_p1, psi_i_p5_p1, a_i_p5_p1, psi_a_p5_p1); + prodsum_psi_a_epi16_256(psi_r_p5_m1, a_r_p5_m1, psi_i_p5_m1, a_i_p5_m1, psi_a_p5_m1); + prodsum_psi_a_epi16_256(psi_r_p5_m3, a_r_p5_m3, psi_i_p5_m3, a_i_p5_m3, psi_a_p5_m3); + prodsum_psi_a_epi16_256(psi_r_p5_m5, a_r_p5_m5, psi_i_p5_m5, a_i_p5_m5, psi_a_p5_m5); + prodsum_psi_a_epi16_256(psi_r_p5_m7, a_r_p5_m7, psi_i_p5_m7, a_i_p5_m7, psi_a_p5_m7); + prodsum_psi_a_epi16_256(psi_r_p3_p7, a_r_p3_p7, psi_i_p3_p7, a_i_p3_p7, psi_a_p3_p7); + prodsum_psi_a_epi16_256(psi_r_p3_p5, a_r_p3_p5, psi_i_p3_p5, a_i_p3_p5, psi_a_p3_p5); + prodsum_psi_a_epi16_256(psi_r_p3_p3, a_r_p3_p3, psi_i_p3_p3, a_i_p3_p3, psi_a_p3_p3); + prodsum_psi_a_epi16_256(psi_r_p3_p1, a_r_p3_p1, psi_i_p3_p1, a_i_p3_p1, psi_a_p3_p1); + prodsum_psi_a_epi16_256(psi_r_p3_m1, a_r_p3_m1, psi_i_p3_m1, a_i_p3_m1, psi_a_p3_m1); + prodsum_psi_a_epi16_256(psi_r_p3_m3, a_r_p3_m3, psi_i_p3_m3, a_i_p3_m3, psi_a_p3_m3); + prodsum_psi_a_epi16_256(psi_r_p3_m5, a_r_p3_m5, psi_i_p3_m5, a_i_p3_m5, psi_a_p3_m5); + prodsum_psi_a_epi16_256(psi_r_p3_m7, a_r_p3_m7, psi_i_p3_m7, a_i_p3_m7, psi_a_p3_m7); + prodsum_psi_a_epi16_256(psi_r_p1_p7, a_r_p1_p7, psi_i_p1_p7, a_i_p1_p7, psi_a_p1_p7); + prodsum_psi_a_epi16_256(psi_r_p1_p5, a_r_p1_p5, psi_i_p1_p5, a_i_p1_p5, psi_a_p1_p5); + prodsum_psi_a_epi16_256(psi_r_p1_p3, a_r_p1_p3, psi_i_p1_p3, a_i_p1_p3, psi_a_p1_p3); + prodsum_psi_a_epi16_256(psi_r_p1_p1, a_r_p1_p1, psi_i_p1_p1, a_i_p1_p1, psi_a_p1_p1); + prodsum_psi_a_epi16_256(psi_r_p1_m1, a_r_p1_m1, psi_i_p1_m1, a_i_p1_m1, psi_a_p1_m1); + prodsum_psi_a_epi16_256(psi_r_p1_m3, a_r_p1_m3, psi_i_p1_m3, a_i_p1_m3, psi_a_p1_m3); + prodsum_psi_a_epi16_256(psi_r_p1_m5, a_r_p1_m5, psi_i_p1_m5, a_i_p1_m5, psi_a_p1_m5); + prodsum_psi_a_epi16_256(psi_r_p1_m7, a_r_p1_m7, psi_i_p1_m7, a_i_p1_m7, psi_a_p1_m7); + prodsum_psi_a_epi16_256(psi_r_m1_p7, a_r_m1_p7, psi_i_m1_p7, a_i_m1_p7, psi_a_m1_p7); + prodsum_psi_a_epi16_256(psi_r_m1_p5, a_r_m1_p5, psi_i_m1_p5, a_i_m1_p5, psi_a_m1_p5); + prodsum_psi_a_epi16_256(psi_r_m1_p3, a_r_m1_p3, psi_i_m1_p3, a_i_m1_p3, psi_a_m1_p3); + prodsum_psi_a_epi16_256(psi_r_m1_p1, a_r_m1_p1, psi_i_m1_p1, a_i_m1_p1, psi_a_m1_p1); + prodsum_psi_a_epi16_256(psi_r_m1_m1, a_r_m1_m1, psi_i_m1_m1, a_i_m1_m1, psi_a_m1_m1); + prodsum_psi_a_epi16_256(psi_r_m1_m3, a_r_m1_m3, psi_i_m1_m3, a_i_m1_m3, psi_a_m1_m3); + prodsum_psi_a_epi16_256(psi_r_m1_m5, a_r_m1_m5, psi_i_m1_m5, a_i_m1_m5, psi_a_m1_m5); + prodsum_psi_a_epi16_256(psi_r_m1_m7, a_r_m1_m7, psi_i_m1_m7, a_i_m1_m7, psi_a_m1_m7); + prodsum_psi_a_epi16_256(psi_r_m3_p7, a_r_m3_p7, psi_i_m3_p7, a_i_m3_p7, psi_a_m3_p7); + prodsum_psi_a_epi16_256(psi_r_m3_p5, a_r_m3_p5, psi_i_m3_p5, a_i_m3_p5, psi_a_m3_p5); + prodsum_psi_a_epi16_256(psi_r_m3_p3, a_r_m3_p3, psi_i_m3_p3, a_i_m3_p3, psi_a_m3_p3); + prodsum_psi_a_epi16_256(psi_r_m3_p1, a_r_m3_p1, psi_i_m3_p1, a_i_m3_p1, psi_a_m3_p1); + prodsum_psi_a_epi16_256(psi_r_m3_m1, a_r_m3_m1, psi_i_m3_m1, a_i_m3_m1, psi_a_m3_m1); + prodsum_psi_a_epi16_256(psi_r_m3_m3, a_r_m3_m3, psi_i_m3_m3, a_i_m3_m3, psi_a_m3_m3); + prodsum_psi_a_epi16_256(psi_r_m3_m5, a_r_m3_m5, psi_i_m3_m5, a_i_m3_m5, psi_a_m3_m5); + prodsum_psi_a_epi16_256(psi_r_m3_m7, a_r_m3_m7, psi_i_m3_m7, a_i_m3_m7, psi_a_m3_m7); + prodsum_psi_a_epi16_256(psi_r_m5_p7, a_r_m5_p7, psi_i_m5_p7, a_i_m5_p7, psi_a_m5_p7); + prodsum_psi_a_epi16_256(psi_r_m5_p5, a_r_m5_p5, psi_i_m5_p5, a_i_m5_p5, psi_a_m5_p5); + prodsum_psi_a_epi16_256(psi_r_m5_p3, a_r_m5_p3, psi_i_m5_p3, a_i_m5_p3, psi_a_m5_p3); + prodsum_psi_a_epi16_256(psi_r_m5_p1, a_r_m5_p1, psi_i_m5_p1, a_i_m5_p1, psi_a_m5_p1); + prodsum_psi_a_epi16_256(psi_r_m5_m1, a_r_m5_m1, psi_i_m5_m1, a_i_m5_m1, psi_a_m5_m1); + prodsum_psi_a_epi16_256(psi_r_m5_m3, a_r_m5_m3, psi_i_m5_m3, a_i_m5_m3, psi_a_m5_m3); + prodsum_psi_a_epi16_256(psi_r_m5_m5, a_r_m5_m5, psi_i_m5_m5, a_i_m5_m5, psi_a_m5_m5); + prodsum_psi_a_epi16_256(psi_r_m5_m7, a_r_m5_m7, psi_i_m5_m7, a_i_m5_m7, psi_a_m5_m7); + prodsum_psi_a_epi16_256(psi_r_m7_p7, a_r_m7_p7, psi_i_m7_p7, a_i_m7_p7, psi_a_m7_p7); + prodsum_psi_a_epi16_256(psi_r_m7_p5, a_r_m7_p5, psi_i_m7_p5, a_i_m7_p5, psi_a_m7_p5); + prodsum_psi_a_epi16_256(psi_r_m7_p3, a_r_m7_p3, psi_i_m7_p3, a_i_m7_p3, psi_a_m7_p3); + prodsum_psi_a_epi16_256(psi_r_m7_p1, a_r_m7_p1, psi_i_m7_p1, a_i_m7_p1, psi_a_m7_p1); + prodsum_psi_a_epi16_256(psi_r_m7_m1, a_r_m7_m1, psi_i_m7_m1, a_i_m7_m1, psi_a_m7_m1); + prodsum_psi_a_epi16_256(psi_r_m7_m3, a_r_m7_m3, psi_i_m7_m3, a_i_m7_m3, psi_a_m7_m3); + prodsum_psi_a_epi16_256(psi_r_m7_m5, a_r_m7_m5, psi_i_m7_m5, a_i_m7_m5, psi_a_m7_m5); + prodsum_psi_a_epi16_256(psi_r_m7_m7, a_r_m7_m7, psi_i_m7_m7, a_i_m7_m7, psi_a_m7_m7); + + // Multiply by sqrt(2) + psi_a_p7_p7 = simde_mm256_mulhi_epi16(psi_a_p7_p7, ONE_OVER_SQRT_2); + psi_a_p7_p7 = simde_mm256_slli_epi16(psi_a_p7_p7, 2); + psi_a_p7_p5 = simde_mm256_mulhi_epi16(psi_a_p7_p5, ONE_OVER_SQRT_2); + psi_a_p7_p5 = simde_mm256_slli_epi16(psi_a_p7_p5, 2); + psi_a_p7_p3 = simde_mm256_mulhi_epi16(psi_a_p7_p3, ONE_OVER_SQRT_2); + psi_a_p7_p3 = simde_mm256_slli_epi16(psi_a_p7_p3, 2); + psi_a_p7_p1 = simde_mm256_mulhi_epi16(psi_a_p7_p1, ONE_OVER_SQRT_2); + psi_a_p7_p1 = simde_mm256_slli_epi16(psi_a_p7_p1, 2); + psi_a_p7_m1 = simde_mm256_mulhi_epi16(psi_a_p7_m1, ONE_OVER_SQRT_2); + psi_a_p7_m1 = simde_mm256_slli_epi16(psi_a_p7_m1, 2); + psi_a_p7_m3 = simde_mm256_mulhi_epi16(psi_a_p7_m3, ONE_OVER_SQRT_2); + psi_a_p7_m3 = simde_mm256_slli_epi16(psi_a_p7_m3, 2); + psi_a_p7_m5 = simde_mm256_mulhi_epi16(psi_a_p7_m5, ONE_OVER_SQRT_2); + psi_a_p7_m5 = simde_mm256_slli_epi16(psi_a_p7_m5, 2); + psi_a_p7_m7 = simde_mm256_mulhi_epi16(psi_a_p7_m7, ONE_OVER_SQRT_2); + psi_a_p7_m7 = simde_mm256_slli_epi16(psi_a_p7_m7, 2); + psi_a_p5_p7 = simde_mm256_mulhi_epi16(psi_a_p5_p7, ONE_OVER_SQRT_2); + psi_a_p5_p7 = simde_mm256_slli_epi16(psi_a_p5_p7, 2); + psi_a_p5_p5 = simde_mm256_mulhi_epi16(psi_a_p5_p5, ONE_OVER_SQRT_2); + psi_a_p5_p5 = simde_mm256_slli_epi16(psi_a_p5_p5, 2); + psi_a_p5_p3 = simde_mm256_mulhi_epi16(psi_a_p5_p3, ONE_OVER_SQRT_2); + psi_a_p5_p3 = simde_mm256_slli_epi16(psi_a_p5_p3, 2); + psi_a_p5_p1 = simde_mm256_mulhi_epi16(psi_a_p5_p1, ONE_OVER_SQRT_2); + psi_a_p5_p1 = simde_mm256_slli_epi16(psi_a_p5_p1, 2); + psi_a_p5_m1 = simde_mm256_mulhi_epi16(psi_a_p5_m1, ONE_OVER_SQRT_2); + psi_a_p5_m1 = simde_mm256_slli_epi16(psi_a_p5_m1, 2); + psi_a_p5_m3 = simde_mm256_mulhi_epi16(psi_a_p5_m3, ONE_OVER_SQRT_2); + psi_a_p5_m3 = simde_mm256_slli_epi16(psi_a_p5_m3, 2); + psi_a_p5_m5 = simde_mm256_mulhi_epi16(psi_a_p5_m5, ONE_OVER_SQRT_2); + psi_a_p5_m5 = simde_mm256_slli_epi16(psi_a_p5_m5, 2); + psi_a_p5_m7 = simde_mm256_mulhi_epi16(psi_a_p5_m7, ONE_OVER_SQRT_2); + psi_a_p5_m7 = simde_mm256_slli_epi16(psi_a_p5_m7, 2); + psi_a_p3_p7 = simde_mm256_mulhi_epi16(psi_a_p3_p7, ONE_OVER_SQRT_2); + psi_a_p3_p7 = simde_mm256_slli_epi16(psi_a_p3_p7, 2); + psi_a_p3_p5 = simde_mm256_mulhi_epi16(psi_a_p3_p5, ONE_OVER_SQRT_2); + psi_a_p3_p5 = simde_mm256_slli_epi16(psi_a_p3_p5, 2); + psi_a_p3_p3 = simde_mm256_mulhi_epi16(psi_a_p3_p3, ONE_OVER_SQRT_2); + psi_a_p3_p3 = simde_mm256_slli_epi16(psi_a_p3_p3, 2); + psi_a_p3_p1 = simde_mm256_mulhi_epi16(psi_a_p3_p1, ONE_OVER_SQRT_2); + psi_a_p3_p1 = simde_mm256_slli_epi16(psi_a_p3_p1, 2); + psi_a_p3_m1 = simde_mm256_mulhi_epi16(psi_a_p3_m1, ONE_OVER_SQRT_2); + psi_a_p3_m1 = simde_mm256_slli_epi16(psi_a_p3_m1, 2); + psi_a_p3_m3 = simde_mm256_mulhi_epi16(psi_a_p3_m3, ONE_OVER_SQRT_2); + psi_a_p3_m3 = simde_mm256_slli_epi16(psi_a_p3_m3, 2); + psi_a_p3_m5 = simde_mm256_mulhi_epi16(psi_a_p3_m5, ONE_OVER_SQRT_2); + psi_a_p3_m5 = simde_mm256_slli_epi16(psi_a_p3_m5, 2); + psi_a_p3_m7 = simde_mm256_mulhi_epi16(psi_a_p3_m7, ONE_OVER_SQRT_2); + psi_a_p3_m7 = simde_mm256_slli_epi16(psi_a_p3_m7, 2); + psi_a_p1_p7 = simde_mm256_mulhi_epi16(psi_a_p1_p7, ONE_OVER_SQRT_2); + psi_a_p1_p7 = simde_mm256_slli_epi16(psi_a_p1_p7, 2); + psi_a_p1_p5 = simde_mm256_mulhi_epi16(psi_a_p1_p5, ONE_OVER_SQRT_2); + psi_a_p1_p5 = simde_mm256_slli_epi16(psi_a_p1_p5, 2); + psi_a_p1_p3 = simde_mm256_mulhi_epi16(psi_a_p1_p3, ONE_OVER_SQRT_2); + psi_a_p1_p3 = simde_mm256_slli_epi16(psi_a_p1_p3, 2); + psi_a_p1_p1 = simde_mm256_mulhi_epi16(psi_a_p1_p1, ONE_OVER_SQRT_2); + psi_a_p1_p1 = simde_mm256_slli_epi16(psi_a_p1_p1, 2); + psi_a_p1_m1 = simde_mm256_mulhi_epi16(psi_a_p1_m1, ONE_OVER_SQRT_2); + psi_a_p1_m1 = simde_mm256_slli_epi16(psi_a_p1_m1, 2); + psi_a_p1_m3 = simde_mm256_mulhi_epi16(psi_a_p1_m3, ONE_OVER_SQRT_2); + psi_a_p1_m3 = simde_mm256_slli_epi16(psi_a_p1_m3, 2); + psi_a_p1_m5 = simde_mm256_mulhi_epi16(psi_a_p1_m5, ONE_OVER_SQRT_2); + psi_a_p1_m5 = simde_mm256_slli_epi16(psi_a_p1_m5, 2); + psi_a_p1_m7 = simde_mm256_mulhi_epi16(psi_a_p1_m7, ONE_OVER_SQRT_2); + psi_a_p1_m7 = simde_mm256_slli_epi16(psi_a_p1_m7, 2); + psi_a_m1_p7 = simde_mm256_mulhi_epi16(psi_a_m1_p7, ONE_OVER_SQRT_2); + psi_a_m1_p7 = simde_mm256_slli_epi16(psi_a_m1_p7, 2); + psi_a_m1_p5 = simde_mm256_mulhi_epi16(psi_a_m1_p5, ONE_OVER_SQRT_2); + psi_a_m1_p5 = simde_mm256_slli_epi16(psi_a_m1_p5, 2); + psi_a_m1_p3 = simde_mm256_mulhi_epi16(psi_a_m1_p3, ONE_OVER_SQRT_2); + psi_a_m1_p3 = simde_mm256_slli_epi16(psi_a_m1_p3, 2); + psi_a_m1_p1 = simde_mm256_mulhi_epi16(psi_a_m1_p1, ONE_OVER_SQRT_2); + psi_a_m1_p1 = simde_mm256_slli_epi16(psi_a_m1_p1, 2); + psi_a_m1_m1 = simde_mm256_mulhi_epi16(psi_a_m1_m1, ONE_OVER_SQRT_2); + psi_a_m1_m1 = simde_mm256_slli_epi16(psi_a_m1_m1, 2); + psi_a_m1_m3 = simde_mm256_mulhi_epi16(psi_a_m1_m3, ONE_OVER_SQRT_2); + psi_a_m1_m3 = simde_mm256_slli_epi16(psi_a_m1_m3, 2); + psi_a_m1_m5 = simde_mm256_mulhi_epi16(psi_a_m1_m5, ONE_OVER_SQRT_2); + psi_a_m1_m5 = simde_mm256_slli_epi16(psi_a_m1_m5, 2); + psi_a_m1_m7 = simde_mm256_mulhi_epi16(psi_a_m1_m7, ONE_OVER_SQRT_2); + psi_a_m1_m7 = simde_mm256_slli_epi16(psi_a_m1_m7, 2); + psi_a_m3_p7 = simde_mm256_mulhi_epi16(psi_a_m3_p7, ONE_OVER_SQRT_2); + psi_a_m3_p7 = simde_mm256_slli_epi16(psi_a_m3_p7, 2); + psi_a_m3_p5 = simde_mm256_mulhi_epi16(psi_a_m3_p5, ONE_OVER_SQRT_2); + psi_a_m3_p5 = simde_mm256_slli_epi16(psi_a_m3_p5, 2); + psi_a_m3_p3 = simde_mm256_mulhi_epi16(psi_a_m3_p3, ONE_OVER_SQRT_2); + psi_a_m3_p3 = simde_mm256_slli_epi16(psi_a_m3_p3, 2); + psi_a_m3_p1 = simde_mm256_mulhi_epi16(psi_a_m3_p1, ONE_OVER_SQRT_2); + psi_a_m3_p1 = simde_mm256_slli_epi16(psi_a_m3_p1, 2); + psi_a_m3_m1 = simde_mm256_mulhi_epi16(psi_a_m3_m1, ONE_OVER_SQRT_2); + psi_a_m3_m1 = simde_mm256_slli_epi16(psi_a_m3_m1, 2); + psi_a_m3_m3 = simde_mm256_mulhi_epi16(psi_a_m3_m3, ONE_OVER_SQRT_2); + psi_a_m3_m3 = simde_mm256_slli_epi16(psi_a_m3_m3, 2); + psi_a_m3_m5 = simde_mm256_mulhi_epi16(psi_a_m3_m5, ONE_OVER_SQRT_2); + psi_a_m3_m5 = simde_mm256_slli_epi16(psi_a_m3_m5, 2); + psi_a_m3_m7 = simde_mm256_mulhi_epi16(psi_a_m3_m7, ONE_OVER_SQRT_2); + psi_a_m3_m7 = simde_mm256_slli_epi16(psi_a_m3_m7, 2); + psi_a_m5_p7 = simde_mm256_mulhi_epi16(psi_a_m5_p7, ONE_OVER_SQRT_2); + psi_a_m5_p7 = simde_mm256_slli_epi16(psi_a_m5_p7, 2); + psi_a_m5_p5 = simde_mm256_mulhi_epi16(psi_a_m5_p5, ONE_OVER_SQRT_2); + psi_a_m5_p5 = simde_mm256_slli_epi16(psi_a_m5_p5, 2); + psi_a_m5_p3 = simde_mm256_mulhi_epi16(psi_a_m5_p3, ONE_OVER_SQRT_2); + psi_a_m5_p3 = simde_mm256_slli_epi16(psi_a_m5_p3, 2); + psi_a_m5_p1 = simde_mm256_mulhi_epi16(psi_a_m5_p1, ONE_OVER_SQRT_2); + psi_a_m5_p1 = simde_mm256_slli_epi16(psi_a_m5_p1, 2); + psi_a_m5_m1 = simde_mm256_mulhi_epi16(psi_a_m5_m1, ONE_OVER_SQRT_2); + psi_a_m5_m1 = simde_mm256_slli_epi16(psi_a_m5_m1, 2); + psi_a_m5_m3 = simde_mm256_mulhi_epi16(psi_a_m5_m3, ONE_OVER_SQRT_2); + psi_a_m5_m3 = simde_mm256_slli_epi16(psi_a_m5_m3, 2); + psi_a_m5_m5 = simde_mm256_mulhi_epi16(psi_a_m5_m5, ONE_OVER_SQRT_2); + psi_a_m5_m5 = simde_mm256_slli_epi16(psi_a_m5_m5, 2); + psi_a_m5_m7 = simde_mm256_mulhi_epi16(psi_a_m5_m7, ONE_OVER_SQRT_2); + psi_a_m5_m7 = simde_mm256_slli_epi16(psi_a_m5_m7, 2); + psi_a_m7_p7 = simde_mm256_mulhi_epi16(psi_a_m7_p7, ONE_OVER_SQRT_2); + psi_a_m7_p7 = simde_mm256_slli_epi16(psi_a_m7_p7, 2); + psi_a_m7_p5 = simde_mm256_mulhi_epi16(psi_a_m7_p5, ONE_OVER_SQRT_2); + psi_a_m7_p5 = simde_mm256_slli_epi16(psi_a_m7_p5, 2); + psi_a_m7_p3 = simde_mm256_mulhi_epi16(psi_a_m7_p3, ONE_OVER_SQRT_2); + psi_a_m7_p3 = simde_mm256_slli_epi16(psi_a_m7_p3, 2); + psi_a_m7_p1 = simde_mm256_mulhi_epi16(psi_a_m7_p1, ONE_OVER_SQRT_2); + psi_a_m7_p1 = simde_mm256_slli_epi16(psi_a_m7_p1, 2); + psi_a_m7_m1 = simde_mm256_mulhi_epi16(psi_a_m7_m1, ONE_OVER_SQRT_2); + psi_a_m7_m1 = simde_mm256_slli_epi16(psi_a_m7_m1, 2); + psi_a_m7_m3 = simde_mm256_mulhi_epi16(psi_a_m7_m3, ONE_OVER_SQRT_2); + psi_a_m7_m3 = simde_mm256_slli_epi16(psi_a_m7_m3, 2); + psi_a_m7_m5 = simde_mm256_mulhi_epi16(psi_a_m7_m5, ONE_OVER_SQRT_2); + psi_a_m7_m5 = simde_mm256_slli_epi16(psi_a_m7_m5, 2); + psi_a_m7_m7 = simde_mm256_mulhi_epi16(psi_a_m7_m7, ONE_OVER_SQRT_2); + psi_a_m7_m7 = simde_mm256_slli_epi16(psi_a_m7_m7, 2); + + // Calculation of a group of two terms in the bit metric involving squares of interference + square_a_64qam_epi16_256(a_r_p7_p7, a_i_p7_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p7); + square_a_64qam_epi16_256(a_r_p7_p5, a_i_p7_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p5); + square_a_64qam_epi16_256(a_r_p7_p3, a_i_p7_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p3); + square_a_64qam_epi16_256(a_r_p7_p1, a_i_p7_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p1); + square_a_64qam_epi16_256(a_r_p7_m1, a_i_p7_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m1); + square_a_64qam_epi16_256(a_r_p7_m3, a_i_p7_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m3); + square_a_64qam_epi16_256(a_r_p7_m5, a_i_p7_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m5); + square_a_64qam_epi16_256(a_r_p7_m7, a_i_p7_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m7); + square_a_64qam_epi16_256(a_r_p5_p7, a_i_p5_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p7); + square_a_64qam_epi16_256(a_r_p5_p5, a_i_p5_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p5); + square_a_64qam_epi16_256(a_r_p5_p3, a_i_p5_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p3); + square_a_64qam_epi16_256(a_r_p5_p1, a_i_p5_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p1); + square_a_64qam_epi16_256(a_r_p5_m1, a_i_p5_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m1); + square_a_64qam_epi16_256(a_r_p5_m3, a_i_p5_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m3); + square_a_64qam_epi16_256(a_r_p5_m5, a_i_p5_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m5); + square_a_64qam_epi16_256(a_r_p5_m7, a_i_p5_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m7); + square_a_64qam_epi16_256(a_r_p3_p7, a_i_p3_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p7); + square_a_64qam_epi16_256(a_r_p3_p5, a_i_p3_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p5); + square_a_64qam_epi16_256(a_r_p3_p3, a_i_p3_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p3); + square_a_64qam_epi16_256(a_r_p3_p1, a_i_p3_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p1); + square_a_64qam_epi16_256(a_r_p3_m1, a_i_p3_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m1); + square_a_64qam_epi16_256(a_r_p3_m3, a_i_p3_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m3); + square_a_64qam_epi16_256(a_r_p3_m5, a_i_p3_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m5); + square_a_64qam_epi16_256(a_r_p3_m7, a_i_p3_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m7); + square_a_64qam_epi16_256(a_r_p1_p7, a_i_p1_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p7); + square_a_64qam_epi16_256(a_r_p1_p5, a_i_p1_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p5); + square_a_64qam_epi16_256(a_r_p1_p3, a_i_p1_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p3); + square_a_64qam_epi16_256(a_r_p1_p1, a_i_p1_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p1); + square_a_64qam_epi16_256(a_r_p1_m1, a_i_p1_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m1); + square_a_64qam_epi16_256(a_r_p1_m3, a_i_p1_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m3); + square_a_64qam_epi16_256(a_r_p1_m5, a_i_p1_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m5); + square_a_64qam_epi16_256(a_r_p1_m7, a_i_p1_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m7); + square_a_64qam_epi16_256(a_r_m1_p7, a_i_m1_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p7); + square_a_64qam_epi16_256(a_r_m1_p5, a_i_m1_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p5); + square_a_64qam_epi16_256(a_r_m1_p3, a_i_m1_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p3); + square_a_64qam_epi16_256(a_r_m1_p1, a_i_m1_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p1); + square_a_64qam_epi16_256(a_r_m1_m1, a_i_m1_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m1); + square_a_64qam_epi16_256(a_r_m1_m3, a_i_m1_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m3); + square_a_64qam_epi16_256(a_r_m1_m5, a_i_m1_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m5); + square_a_64qam_epi16_256(a_r_m1_m7, a_i_m1_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m7); + square_a_64qam_epi16_256(a_r_m3_p7, a_i_m3_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p7); + square_a_64qam_epi16_256(a_r_m3_p5, a_i_m3_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p5); + square_a_64qam_epi16_256(a_r_m3_p3, a_i_m3_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p3); + square_a_64qam_epi16_256(a_r_m3_p1, a_i_m3_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p1); + square_a_64qam_epi16_256(a_r_m3_m1, a_i_m3_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m1); + square_a_64qam_epi16_256(a_r_m3_m3, a_i_m3_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m3); + square_a_64qam_epi16_256(a_r_m3_m5, a_i_m3_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m5); + square_a_64qam_epi16_256(a_r_m3_m7, a_i_m3_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m7); + square_a_64qam_epi16_256(a_r_m5_p7, a_i_m5_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p7); + square_a_64qam_epi16_256(a_r_m5_p5, a_i_m5_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p5); + square_a_64qam_epi16_256(a_r_m5_p3, a_i_m5_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p3); + square_a_64qam_epi16_256(a_r_m5_p1, a_i_m5_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p1); + square_a_64qam_epi16_256(a_r_m5_m1, a_i_m5_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m1); + square_a_64qam_epi16_256(a_r_m5_m3, a_i_m5_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m3); + square_a_64qam_epi16_256(a_r_m5_m5, a_i_m5_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m5); + square_a_64qam_epi16_256(a_r_m5_m7, a_i_m5_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m7); + square_a_64qam_epi16_256(a_r_m7_p7, a_i_m7_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p7); + square_a_64qam_epi16_256(a_r_m7_p5, a_i_m7_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p5); + square_a_64qam_epi16_256(a_r_m7_p3, a_i_m7_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p3); + square_a_64qam_epi16_256(a_r_m7_p1, a_i_m7_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p1); + square_a_64qam_epi16_256(a_r_m7_m1, a_i_m7_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m1); + square_a_64qam_epi16_256(a_r_m7_m3, a_i_m7_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m3); + square_a_64qam_epi16_256(a_r_m7_m5, a_i_m7_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m5); + square_a_64qam_epi16_256(a_r_m7_m7, a_i_m7_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m7); + + // Computing different multiples of ||h0||^2 + // x=1, y=1 + ch_mag_2_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, ONE_OVER_FOUR_SQRT_42); + ch_mag_2_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_2_over_42_with_sigma2, 1); + // x=1, y=3 + ch_mag_10_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, FIVE_OVER_FOUR_SQRT_42); + ch_mag_10_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_10_over_42_with_sigma2, 1); + // x=1, x=5 + ch_mag_26_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, THIRTEEN_OVER_FOUR_SQRT_42); + ch_mag_26_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_26_over_42_with_sigma2, 1); + // x=1, y=7 + ch_mag_50_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, TWENTYFIVE_OVER_FOUR_SQRT_42); + ch_mag_50_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_50_over_42_with_sigma2, 1); + // x=3, y=3 + ch_mag_18_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, NINE_OVER_FOUR_SQRT_42); + ch_mag_18_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_18_over_42_with_sigma2, 1); + // x=3, y=5 + ch_mag_34_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, SEVENTEEN_OVER_FOUR_SQRT_42); + ch_mag_34_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_34_over_42_with_sigma2, 1); + // x=3, y=7 + ch_mag_58_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, TWENTYNINE_OVER_FOUR_SQRT_42); + ch_mag_58_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_58_over_42_with_sigma2, 2); + // x=5, y=5 + ch_mag_50_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, TWENTYFIVE_OVER_FOUR_SQRT_42); + ch_mag_50_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_50_over_42_with_sigma2, 1); + // x=5, y=7 + ch_mag_74_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, THIRTYSEVEN_OVER_FOUR_SQRT_42); + ch_mag_74_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_74_over_42_with_sigma2, 2); + // x=7, y=7 + ch_mag_98_over_42_with_sigma2 = simde_mm256_mulhi_epi16(ch_mag_des, FORTYNINE_OVER_FOUR_SQRT_42); + ch_mag_98_over_42_with_sigma2 = simde_mm256_slli_epi16(ch_mag_98_over_42_with_sigma2, 2); + + // Computing Metrics + xmm0 = simde_mm256_subs_epi16(psi_a_p7_p7, a_sq_p7_p7); + simde__m256i xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_7_7); + simde__m256i bit_met_p7_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_p5, a_sq_p7_p5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_7_5); + simde__m256i bit_met_p7_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_p3, a_sq_p7_p3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_7_3); + simde__m256i bit_met_p7_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_p1, a_sq_p7_p1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_7_1); + simde__m256i bit_met_p7_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_m1, a_sq_p7_m1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_7_1); + simde__m256i bit_met_p7_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_m3, a_sq_p7_m3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_7_3); + simde__m256i bit_met_p7_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_m5, a_sq_p7_m5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_7_5); + simde__m256i bit_met_p7_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p7_m7, a_sq_p7_m7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_7_7); + simde__m256i bit_met_p7_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_p7, a_sq_p5_p7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_5_7); + simde__m256i bit_met_p5_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_p5, a_sq_p5_p5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_5_5); + simde__m256i bit_met_p5_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_p3, a_sq_p5_p3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_5_3); + simde__m256i bit_met_p5_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_p1, a_sq_p5_p1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_5_1); + simde__m256i bit_met_p5_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_m1, a_sq_p5_m1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_5_1); + simde__m256i bit_met_p5_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_m3, a_sq_p5_m3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_5_3); + simde__m256i bit_met_p5_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_m5, a_sq_p5_m5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_5_5); + simde__m256i bit_met_p5_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p5_m7, a_sq_p5_m7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_5_7); + simde__m256i bit_met_p5_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_p7, a_sq_p3_p7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_3_7); + simde__m256i bit_met_p3_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_p5, a_sq_p3_p5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_3_5); + simde__m256i bit_met_p3_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_p3, a_sq_p3_p3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_3_3); + simde__m256i bit_met_p3_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_p1, a_sq_p3_p1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_3_1); + simde__m256i bit_met_p3_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_m1, a_sq_p3_m1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_3_1); + simde__m256i bit_met_p3_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_m3, a_sq_p3_m3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_3_3); + simde__m256i bit_met_p3_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_m5, a_sq_p3_m5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_3_5); + simde__m256i bit_met_p3_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p3_m7, a_sq_p3_m7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_3_7); + simde__m256i bit_met_p3_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_p7, a_sq_p1_p7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_1_7); + simde__m256i bit_met_p1_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_p5, a_sq_p1_p5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_1_5); + simde__m256i bit_met_p1_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_p3, a_sq_p1_p3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_1_3); + simde__m256i bit_met_p1_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_p1, a_sq_p1_p1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_p_1_1); + simde__m256i bit_met_p1_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_m1, a_sq_p1_m1); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_1_1); + simde__m256i bit_met_p1_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_m3, a_sq_p1_m3); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_1_3); + simde__m256i bit_met_p1_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_m5, a_sq_p1_m5); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_1_5); + simde__m256i bit_met_p1_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_p1_m7, a_sq_p1_m7); + xmm1 = simde_mm256_adds_epi16(xmm0, y0_m_1_7); + simde__m256i bit_met_p1_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + + xmm0 = simde_mm256_subs_epi16(psi_a_m1_p7, a_sq_m1_p7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_1_7); + simde__m256i bit_met_m1_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_p5, a_sq_m1_p5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_1_5); + simde__m256i bit_met_m1_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_p3, a_sq_m1_p3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_1_3); + simde__m256i bit_met_m1_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_p1, a_sq_m1_p1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_1_1); + simde__m256i bit_met_m1_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_m1, a_sq_m1_m1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_1_1); + simde__m256i bit_met_m1_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_m3, a_sq_m1_m3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_1_3); + simde__m256i bit_met_m1_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_m5, a_sq_m1_m5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_1_5); + simde__m256i bit_met_m1_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m1_m7, a_sq_m1_m7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_1_7); + simde__m256i bit_met_m1_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_p7, a_sq_m3_p7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_3_7); + simde__m256i bit_met_m3_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_p5, a_sq_m3_p5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_3_5); + simde__m256i bit_met_m3_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_p3, a_sq_m3_p3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_3_3); + simde__m256i bit_met_m3_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_p1, a_sq_m3_p1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_3_1); + simde__m256i bit_met_m3_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_m1, a_sq_m3_m1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_3_1); + simde__m256i bit_met_m3_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_m3, a_sq_m3_m3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_3_3); + simde__m256i bit_met_m3_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_m5, a_sq_m3_m5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_3_5); + simde__m256i bit_met_m3_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m3_m7, a_sq_m3_m7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_3_7); + simde__m256i bit_met_m3_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_p7, a_sq_m5_p7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_5_7); + simde__m256i bit_met_m5_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_p5, a_sq_m5_p5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_5_5); + simde__m256i bit_met_m5_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_p3, a_sq_m5_p3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_5_3); + simde__m256i bit_met_m5_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_p1, a_sq_m5_p1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_5_1); + simde__m256i bit_met_m5_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_m1, a_sq_m5_m1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_5_1); + simde__m256i bit_met_m5_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_m3, a_sq_m5_m3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_5_3); + simde__m256i bit_met_m5_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_m5, a_sq_m5_m5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_5_5); + simde__m256i bit_met_m5_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m5_m7, a_sq_m5_m7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_5_7); + simde__m256i bit_met_m5_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_p7, a_sq_m7_p7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_7_7); + simde__m256i bit_met_m7_p7 = simde_mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_p5, a_sq_m7_p5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_7_5); + simde__m256i bit_met_m7_p5 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_p3, a_sq_m7_p3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_7_3); + simde__m256i bit_met_m7_p3 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_p1, a_sq_m7_p1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_m_7_1); + simde__m256i bit_met_m7_p1 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_m1, a_sq_m7_m1); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_7_1); + simde__m256i bit_met_m7_m1 = simde_mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_m3, a_sq_m7_m3); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_7_3); + simde__m256i bit_met_m7_m3 = simde_mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_m5, a_sq_m7_m5); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_7_5); + simde__m256i bit_met_m7_m5 = simde_mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = simde_mm256_subs_epi16(psi_a_m7_m7, a_sq_m7_m7); + xmm1 = simde_mm256_subs_epi16(xmm0, y0_p_7_7); + simde__m256i bit_met_m7_m7 = simde_mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + + // Detection for 1st bit + // bit = 1 + xmm0 = simde_mm256_max_epi16(bit_met_m7_p7, bit_met_m7_p5); + xmm1 = simde_mm256_max_epi16(bit_met_m7_p3, bit_met_m7_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m7_m1, bit_met_m7_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m7_m5, bit_met_m7_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + simde__m256i logmax_den_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m5_p7, bit_met_m5_p5); + xmm1 = simde_mm256_max_epi16(bit_met_m5_p3, bit_met_m5_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m5_m1, bit_met_m5_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m5, bit_met_m5_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m3_p7, bit_met_m3_p5); + xmm1 = simde_mm256_max_epi16(bit_met_m3_p3, bit_met_m3_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m3_m1, bit_met_m3_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m3_m5, bit_met_m3_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m1_p7, bit_met_m1_p5); + xmm1 = simde_mm256_max_epi16(bit_met_m1_p3, bit_met_m1_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m1, bit_met_m1_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m1_m5, bit_met_m1_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + + // bit = 0 + xmm0 = simde_mm256_max_epi16(bit_met_p7_p7, bit_met_p7_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p7_p3, bit_met_p7_p1); + xmm2 = simde_mm256_max_epi16(bit_met_p7_m1, bit_met_p7_m3); + xmm3 = simde_mm256_max_epi16(bit_met_p7_m5, bit_met_p7_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + simde__m256i logmax_num_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p5_p7, bit_met_p5_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p5_p3, bit_met_p5_p1); + xmm2 = simde_mm256_max_epi16(bit_met_p5_m1, bit_met_p5_m3); + xmm3 = simde_mm256_max_epi16(bit_met_p5_m5, bit_met_p5_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p3_p7, bit_met_p3_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p3, bit_met_p3_p1); + xmm2 = simde_mm256_max_epi16(bit_met_p3_m1, bit_met_p3_m3); + xmm3 = simde_mm256_max_epi16(bit_met_p3_m5, bit_met_p3_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p1_p7, bit_met_p1_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p1_p3, bit_met_p1_p1); + xmm2 = simde_mm256_max_epi16(bit_met_p1_m1, bit_met_p1_m3); + xmm3 = simde_mm256_max_epi16(bit_met_p1_m5, bit_met_p1_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + + y0r = simde_mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 2nd bit + // bit = 1 + xmm0 = simde_mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + + // bit = 0 + xmm0 = simde_mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p1, bit_met_m7_p1); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p5, bit_met_m7_p5); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + + y1r = simde_mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 3rd bit + xmm0 = simde_mm256_max_epi16(bit_met_m7_m7, bit_met_m7_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m7_m3, bit_met_m7_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m7_p1, bit_met_m7_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m7_p5, bit_met_m7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m5_m7, bit_met_m5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m5_m3, bit_met_m5_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p5_m7, bit_met_p5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p5_m3, bit_met_p5_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p5_p1, bit_met_p5_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p5_p5, bit_met_p5_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m7, bit_met_p7_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p7_m3, bit_met_p7_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p7_p1, bit_met_p7_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p7_p5, bit_met_p7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = simde_mm256_max_epi16(bit_met_m3_m7, bit_met_m3_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m3_m3, bit_met_m3_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m3_p1, bit_met_m3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m3_p5, bit_met_m3_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m1_m7, bit_met_m1_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m1_m3, bit_met_m1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p1, bit_met_m1_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m1_p5, bit_met_m1_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p1_m7, bit_met_p1_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p1_m3, bit_met_p1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p1_p1, bit_met_p1_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p1_p5, bit_met_p1_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p3_m7, bit_met_p3_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m3, bit_met_p3_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p3_p1, bit_met_p3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p3_p5, bit_met_p3_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + + simde__m256i y2r = simde_mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 4th bit + xmm0 = simde_mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p5); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = simde_mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p1, bit_met_m7_p1); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + + y0i = simde_mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 5th bit + xmm0 = simde_mm256_max_epi16(bit_met_m7_m7, bit_met_m7_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m7_m3, bit_met_m7_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m7_p1, bit_met_m7_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m7_p5, bit_met_m7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m1_m7, bit_met_m1_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m1_m3, bit_met_m1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p1, bit_met_m1_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m1_p5, bit_met_m1_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p1_m7, bit_met_p1_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p1_m3, bit_met_p1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p1_p1, bit_met_p1_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p1_p5, bit_met_p1_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m7, bit_met_p7_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p7_m3, bit_met_p7_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p7_p1, bit_met_p7_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p7_p5, bit_met_p7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = simde_mm256_max_epi16(bit_met_m5_m7, bit_met_m5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m5_m3, bit_met_m5_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_m3_m7, bit_met_m3_m5); + xmm1 = simde_mm256_max_epi16(bit_met_m3_m3, bit_met_m3_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m3_p1, bit_met_m3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m3_p5, bit_met_m3_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p3_m7, bit_met_p3_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m3, bit_met_p3_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p3_p1, bit_met_p3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p3_p5, bit_met_p3_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p5_m7, bit_met_p5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p5_m3, bit_met_p5_m1); + xmm2 = simde_mm256_max_epi16(bit_met_p5_p1, bit_met_p5_p3); + xmm3 = simde_mm256_max_epi16(bit_met_p5_p5, bit_met_p5_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + + y1i = simde_mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 6th bit + xmm0 = simde_mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p1); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = simde_mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = simde_mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(xmm4, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = simde_mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = simde_mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = simde_mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = simde_mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = simde_mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = simde_mm256_max_epi16(bit_met_m5_p5, bit_met_m7_p5); + xmm4 = simde_mm256_max_epi16(xmm0, xmm1); + xmm5 = simde_mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = simde_mm256_max_epi16(logmax_num_re0, xmm5); + + simde__m256i y2i = simde_mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Map to output stream, difficult to do in SIMD since we have 6 16bit LLRs + int idx0 = 24 * i; + for (int re = 0; re < 16; re++) { + stream0_out[idx0 + 0].r = ((short *)&y0r)[re]; + stream0_out[idx0 + 0].i = ((short *)&y1r)[re]; + stream0_out[idx0 + 1].r = ((short *)&y2r)[re]; + stream0_out[idx0 + 1].i = ((short *)&y0i)[re]; + stream0_out[idx0 + 2].r = ((short *)&y1i)[re]; + stream0_out[idx0 + 2].i = ((short *)&y2i)[re]; + idx0 += 3; + } + } + + _mm_empty(); + _m_empty(); +} + void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, int32_t **ul_ch_mag, int32_t ***rho, @@ -1407,7 +4031,9 @@ void nr_ulsch_compute_ML_llr(int32_t **rxdataF_comp, nr_ulsch_qam16_qam16(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); break; case 6: - AssertFatal(1 == 0, "LLR computation is not implemented yet for ML with Qm = %d\n", mod_order); + nr_ulsch_qam64_qam64(rxdataF_comp0, rxdataF_comp1, ul_ch_mag0, ul_ch_mag1, llr_layers0, rho0, nb_re); + nr_ulsch_qam64_qam64(rxdataF_comp1, rxdataF_comp0, ul_ch_mag1, ul_ch_mag0, llr_layers1, rho1, nb_re); + break; default: AssertFatal(1 == 0, "nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d\n", symbol, mod_order); } From 917ff8e97b6843519d1da886f808a1174381f7d7 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 26 Apr 2023 15:22:43 +0100 Subject: [PATCH 023/119] Remove duplicated code --- CMakeLists.txt | 6 +- .../dlsch_llr_computation_avx2.c | 48 ++---- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 154 +++--------------- openair1/PHY/TOOLS/simde_operations.c | 60 +++++++ openair1/PHY/TOOLS/tools_defs.h | 2 + 5 files changed, 96 insertions(+), 174 deletions(-) create mode 100644 openair1/PHY/TOOLS/simde_operations.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 214a16b79a..2c1b7d6421 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1071,6 +1071,7 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/TOOLS/dB_routines.c ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c ${OPENAIR1_DIR}/PHY/TOOLS/lut.c + ${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c ) set(PHY_SRC @@ -1206,6 +1207,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/TOOLS/dB_routines.c ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c ${OPENAIR1_DIR}/PHY/TOOLS/lut.c + ${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c ${PHY_POLARSRC} ${PHY_SMALLBLOCKSRC} ${PHY_NR_CODINGIF} @@ -1258,6 +1260,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/TOOLS/dB_routines.c ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c ${OPENAIR1_DIR}/PHY/TOOLS/lut.c + ${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c ${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c # ${OPENAIR1_DIR}/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c ${PHY_POLARSRC} @@ -1306,8 +1309,9 @@ set(PHY_MEX_UE ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c - ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c + ${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c + ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c ${OPENAIR_DIR}/common/utils/LOG/log.c ${OPENAIR_DIR}/common/utils/T/T.c diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c index c00040f668..88d7dfef6b 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c @@ -121,34 +121,6 @@ tmp_result2 = simde_mm256_slli_epi16(tmp_result2, 1); \ const simde__m256i a_sq = simde_mm256_adds_epi16(tmp_result, tmp_result2); - void seperate_real_imag_parts(__m256i *out_re, __m256i *out_im, __m256i in0, __m256i in1) - { - __m256i tmp0; - __m256i tmp1; - - in0 = simde_mm256_shufflelo_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in0 = simde_mm256_shufflehi_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in0 = simde_mm256_shuffle_epi32(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - in1 = simde_mm256_shufflelo_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in1 = simde_mm256_shufflehi_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in1 = simde_mm256_shuffle_epi32(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - // in0 = [Re(0,1,2,3) Im(0,1,2,3) Re(4,5,6,7) Im(4,5,6,7)] - // in0 = [Re(8,9,10,11) Im(8,9,10,11) Re(12,13,14,15) Im(12,13,14,15)] - - tmp0 = simde_mm256_unpacklo_epi64(in0, in1); - // axmm2 = [Re(0,1,2,3) Re(8,9,10,11) Re(4,5,6,7) Re(12,13,14,15)] - tmp0 = simde_mm256_permute4x64_epi64(tmp0, 0xd8); // Re(rho) - - tmp1 = simde_mm256_unpackhi_epi64(in0, in1); - // axmm3 = [Im(0,1,2,3) Im(8,9,10,11) Im(4,5,6,7) Im(12,13,14,15)] - tmp1 = simde_mm256_permute4x64_epi64(tmp1, 0xd8); // Im(rho) - - *out_re = tmp0; - *out_im = tmp1; -} - void qam64_qam16_avx2(short *stream0_in, short *stream1_in, short *ch_mag, @@ -245,7 +217,7 @@ void qam64_qam16_avx2(short *stream0_in, xmm3 = _mm_unpackhi_epi64(xmm0,xmm1); // Im(rho) */ simde__m256i xmm0, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; - seperate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i+1]); + simde_mm256_separate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i+1]); const simde__m256i rho_rpi = simde_mm256_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho) const simde__m256i rho_rmi = simde_mm256_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho) @@ -323,7 +295,7 @@ void qam64_qam16_avx2(short *stream0_in, */ simde__m256i y1r, y1i; - seperate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i+1]); + simde_mm256_separate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i+1]); // Psi_r calculation from rho_rpi or rho_rmi xmm0 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(0));// ZERO for abs_pi16 @@ -604,7 +576,7 @@ void qam64_qam16_avx2(short *stream0_in, y0i = simde_mm256_unpackhi_epi64(xmm0,xmm1); */ simde__m256i y0r, y0i; - seperate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i+1]); + simde_mm256_separate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i+1]); /* // Rearrange desired channel magnitudes @@ -619,7 +591,7 @@ void qam64_qam16_avx2(short *stream0_in, ch_mag_des = simde_mm256_unpacklo_epi64(xmm2,xmm3); */ - seperate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i+1]); + simde_mm256_separate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i+1]); // Rearrange interfering channel magnitudes /* @@ -634,7 +606,7 @@ void qam64_qam16_avx2(short *stream0_in, ch_mag_int = simde_mm256_unpacklo_epi64(xmm2,xmm3); */ - seperate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i+1]); + simde_mm256_separate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i+1]); y0r_one_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, ONE_OVER_SQRT_42); y0r_three_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, THREE_OVER_SQRT_42); @@ -1819,7 +1791,7 @@ void qam64_qam64_avx2(int32_t *stream0_in, xmm3 = simde_mm256_permute4x64_epi64(xmm3,0xd8); // Im(rho) */ simde__m256i xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; - seperate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i+1]); + simde_mm256_separate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i+1]); simde__m256i rho_rpi = simde_mm256_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho) simde__m256i rho_rmi = simde_mm256_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho) @@ -1899,7 +1871,7 @@ void qam64_qam64_avx2(int32_t *stream0_in, y1i = simde_mm256_permute4x64_epi64(y1i,0xd8); // Im(y1) */ simde__m256i y1r, y1i, xmm0; - seperate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i+1]); + simde_mm256_separate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i+1]); // Psi_r calculation from rho_rpi or rho_rmi xmm0 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(0));// ZERO for abs_pi16 @@ -2181,7 +2153,7 @@ void qam64_qam64_avx2(int32_t *stream0_in, y0i = _mm_unpackhi_epi64(xmm0,xmm1); */ simde__m256i y0r, y0i; - seperate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i+1]); + simde_mm256_separate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i+1]); // Rearrange desired channel magnitudes // [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2),...,,|h|^2(7),|h|^2(7)]*(2/sqrt(10)) @@ -2197,7 +2169,7 @@ void qam64_qam64_avx2(int32_t *stream0_in, ch_mag_des = _mm_unpacklo_epi64(xmm2,xmm3); */ // xmm2 is dummy variable that contains the same values as ch_mag_des - seperate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i+1]); + simde_mm256_separate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i+1]); // Rearrange interfering channel magnitudes @@ -2212,7 +2184,7 @@ void qam64_qam64_avx2(int32_t *stream0_in, xmm3 = _mm_shuffle_epi32(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); ch_mag_int = _mm_unpacklo_epi64(xmm2,xmm3); */ - seperate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i+1]); + simde_mm256_separate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i+1]); y0r_one_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, ONE_OVER_SQRT_42); y0r_three_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, THREE_OVER_SQRT_42); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 0ecadd6646..f378830c23 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -535,62 +535,22 @@ void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, c16_t *stream1_in, c16_t *stream0_out for (int i = 0; i < length >> 2; i += 2) { /// Compute real and imaginary parts of MF output for stream 0 (desired stream) - - // Put xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] - __m128i xmm0 = stream0_128i_in[i]; // 4 symbols - xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] - __m128i xmm1 = stream0_128i_in[i + 1]; // 4 symbols - xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - __m128i y0r = simde_mm_unpacklo_epi64(xmm0, xmm1); // y0r = Re(y0) - __m128i y0i = simde_mm_unpackhi_epi64(xmm0, xmm1); // y0i = Im(y0) - + __m128i y0r, y0i; + simde_mm128_separate_real_imag_parts(&y0r, &y0i, stream0_128i_in[i], stream0_128i_in[i + 1]); __m128i y0r_over2 = simde_mm_mulhi_epi16(y0r, ONE_OVER_2_SQRT_2); y0r_over2 = _mm_slli_epi16(y0r_over2, 1); // y0r_over2 = Re(y0) / sqrt(2) __m128i y0i_over2 = simde_mm_mulhi_epi16(y0i, ONE_OVER_2_SQRT_2); y0i_over2 = _mm_slli_epi16(y0i_over2, 1); // y0i_over2 = Im(y0) / sqrt(2) /// Compute real and imaginary parts of MF output for stream 1 (interference stream) - - // Put xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] - xmm0 = stream1_128i_in[i]; // 4 symbols - xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] - xmm1 = stream1_128i_in[i + 1]; // 4 symbols - xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - __m128i y1r = simde_mm_unpacklo_epi64(xmm0, xmm1); // y1r = Re(y1) - __m128i y1i = simde_mm_unpackhi_epi64(xmm0, xmm1); // y1i = Im(y1) - __m128i y1r_over2 = simde_mm_srai_epi16(y1r, 1); // y1r_over2 = Re(y1) / 2 - __m128i y1i_over2 = simde_mm_srai_epi16(y1i, 1); // y1i_over2 = Im(y1) / 2 + __m128i y1r_over2, y1i_over2; + simde_mm128_separate_real_imag_parts(&y1r_over2, &y1i_over2, stream1_128i_in[i], stream1_128i_in[i + 1]); + y1r_over2 = simde_mm_srai_epi16(y1r_over2, 1); // y1r_over2 = Re(y1) / 2 + y1i_over2 = simde_mm_srai_epi16(y1i_over2, 1); // y1i_over2 = Im(y1) / 2 /// Get real and imaginary parts of rho - - // Put xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] - xmm0 = rho01_128i[i]; // 4 symbols - xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] - xmm1 = rho01_128i[i + 1]; // 4 symbols - xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - __m128i rhor = simde_mm_unpacklo_epi64(xmm0, xmm1); // rhor = Re(rho) - __m128i rhoi = simde_mm_unpackhi_epi64(xmm0, xmm1); // rhoi = Im(rho) + __m128i rhor, rhoi; + simde_mm128_separate_real_imag_parts(&rhor, &rhoi, rho01_128i[i], rho01_128i[i + 1]); /// Compute |psi_r| and |psi_i| @@ -951,18 +911,7 @@ void nr_ulsch_qam16_qam16(c16_t *stream0_in, for (int i = 0; i < length >> 2; i += 2) { // Get rho - xmm0 = rho01_128i[i]; - xmm1 = rho01_128i[i + 1]; - xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - // xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] - // xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] - xmm2 = simde_mm_unpacklo_epi64(xmm0, xmm1); // Re(rho) - xmm3 = simde_mm_unpackhi_epi64(xmm0, xmm1); // Im(rho) + simde_mm128_separate_real_imag_parts(&xmm2, &xmm3, rho01_128i[i], rho01_128i[i + 1]); rho_rpi = simde_mm_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho) rho_rmi = simde_mm_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho) @@ -989,18 +938,7 @@ void nr_ulsch_qam16_qam16(c16_t *stream0_in, rho_rmi_3_1 = simde_mm_subs_epi16(xmm6, xmm7); // Rearrange interfering MF output - xmm0 = stream1_128i_in[i]; - xmm1 = stream1_128i_in[i + 1]; - xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - // xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] - // xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] - y1r = simde_mm_unpacklo_epi64(xmm0, xmm1); //[y1r(1),y1r(2),y1r(3),y1r(4)] - y1i = simde_mm_unpackhi_epi64(xmm0, xmm1); //[y1i(1),y1i(2),y1i(3),y1i(4)] + simde_mm128_separate_real_imag_parts(&y1r, &y1i, stream1_128i_in[i], stream1_128i_in[i + 1]); xmm0 = simde_mm_setzero_si128(); // ZERO xmm2 = simde_mm_subs_epi16(rho_rpi_1_1, y1r); // = [Re(rho)+ Im(rho)]/sqrt(10) - y1r @@ -1070,43 +1008,14 @@ void nr_ulsch_qam16_qam16(c16_t *stream0_in, psi_i_m3_m3 = simde_mm_abs_epi16(xmm2); // Rearrange desired MF output - xmm0 = stream0_128i_in[i]; - xmm1 = stream0_128i_in[i + 1]; - xmm0 = simde_mm_shufflelo_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shufflehi_epi16(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm0 = simde_mm_shuffle_epi32(xmm0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflelo_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shufflehi_epi16(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm1 = simde_mm_shuffle_epi32(xmm1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - // xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] - // xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] - y0r = simde_mm_unpacklo_epi64(xmm0, xmm1); // = [y0r(1),y0r(2),y0r(3),y0r(4)] - y0i = simde_mm_unpackhi_epi64(xmm0, xmm1); + simde_mm128_separate_real_imag_parts(&y0r, &y0i, stream0_128i_in[i], stream0_128i_in[i + 1]); // Rearrange desired channel magnitudes - xmm2 = ch_mag_128i[i]; // = [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2)]*(2/sqrt(10)) - xmm3 = ch_mag_128i[i + 1]; // = [|h|^2(3),|h|^2(3),|h|^2(4),|h|^2(4)]*(2/sqrt(10)) - xmm2 = simde_mm_shufflelo_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm2 = simde_mm_shufflehi_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm2 = simde_mm_shuffle_epi32(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm3 = simde_mm_shufflelo_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm3 = simde_mm_shufflehi_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm3 = simde_mm_shuffle_epi32(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - ch_mag_des = simde_mm_unpacklo_epi64(xmm2, xmm3); // = [|h|^2(1),|h|^2(2),|h|^2(3),|h|^2(4)]*(2/sqrt(10)) + // [|h|^2(1),|h|^2(2),|h|^2(3),|h|^2(4)]*(2/sqrt(10)) + simde_mm128_separate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_128i[i], ch_mag_128i[i + 1]); // Rearrange interfering channel magnitudes - xmm2 = ch_mag_128i_i[i]; - xmm3 = ch_mag_128i_i[i + 1]; - - xmm2 = simde_mm_shufflelo_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm2 = simde_mm_shufflehi_epi16(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm2 = simde_mm_shuffle_epi32(xmm2, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm3 = simde_mm_shufflelo_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm3 = simde_mm_shufflehi_epi16(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - xmm3 = simde_mm_shuffle_epi32(xmm3, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - ch_mag_int = simde_mm_unpacklo_epi64(xmm2, xmm3); + simde_mm128_separate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_128i_i[i], ch_mag_128i_i[i + 1]); // Scale MF output of desired signal y0r_over_sqrt10 = simde_mm_mulhi_epi16(y0r, ONE_OVER_SQRT_10); @@ -1437,31 +1346,6 @@ static const int16_t ones256[16] __attribute__((aligned(32))) = {0xffff, tmp_result2 = simde_mm256_slli_epi16(tmp_result2, 1); \ const simde__m256i a_sq = simde_mm256_adds_epi16(tmp_result, tmp_result2); -void separate_real_imag_parts(__m256i *out_re, __m256i *out_im, __m256i in0, __m256i in1) -{ - in0 = simde_mm256_shufflelo_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in0 = simde_mm256_shufflehi_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in0 = simde_mm256_shuffle_epi32(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - in1 = simde_mm256_shufflelo_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in1 = simde_mm256_shufflehi_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - in1 = simde_mm256_shuffle_epi32(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); - - // in0 = [Re(0,1,2,3) Im(0,1,2,3) Re(4,5,6,7) Im(4,5,6,7)] - // in0 = [Re(8,9,10,11) Im(8,9,10,11) Re(12,13,14,15) Im(12,13,14,15)] - - __m256i tmp0 = simde_mm256_unpacklo_epi64(in0, in1); - // axmm2 = [Re(0,1,2,3) Re(8,9,10,11) Re(4,5,6,7) Re(12,13,14,15)] - tmp0 = simde_mm256_permute4x64_epi64(tmp0, 0xd8); // Re(rho) - - __m256i tmp1 = simde_mm256_unpackhi_epi64(in0, in1); - // axmm3 = [Im(0,1,2,3) Im(8,9,10,11) Im(4,5,6,7) Im(12,13,14,15)] - tmp1 = simde_mm256_permute4x64_epi64(tmp1, 0xd8); // Im(rho) - - *out_re = tmp0; - *out_im = tmp1; -} - /* * This function computes the LLRs of stream 0 (s_0) in presence of the interfering stream 1 (s_1) assuming that both symbols are * 64QAM. It can be used for both MU-MIMO interference-aware receiver or for SU-MIMO receivers. @@ -1540,7 +1424,7 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, // Get rho simde__m256i xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; - separate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i + 1]); + simde_mm256_separate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i + 1]); simde__m256i rho_rpi = simde_mm256_adds_epi16(xmm2, xmm3); // rho = Re(rho) + Im(rho) simde__m256i rho_rmi = simde_mm256_subs_epi16(xmm2, xmm3); // rho* = Re(rho) - Im(rho) @@ -1603,7 +1487,7 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, // Rearrange interfering MF output simde__m256i y1r, y1i, xmm0; - separate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i + 1]); + simde_mm256_separate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i + 1]); // Psi_r calculation from rho_rpi or rho_rmi xmm0 = simde_mm256_broadcastw_epi16(_mm_set1_epi16(0)); // ZERO for abs_pi16 @@ -1871,15 +1755,15 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, // Rearrange desired MF output simde__m256i y0r, y0i; - separate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i + 1]); + simde_mm256_separate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i + 1]); // Rearrange desired channel magnitudes // [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2),...,,|h|^2(7),|h|^2(7)]*(2/sqrt(10)) // xmm2 is dummy variable that contains the same values as ch_mag_des - separate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i + 1]); + simde_mm256_separate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i + 1]); // Rearrange interfering channel magnitudes - separate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i + 1]); + simde_mm256_separate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i + 1]); y0r_one_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, ONE_OVER_SQRT_42); y0r_three_over_sqrt_21 = simde_mm256_mulhi_epi16(y0r, THREE_OVER_SQRT_42); diff --git a/openair1/PHY/TOOLS/simde_operations.c b/openair1/PHY/TOOLS/simde_operations.c new file mode 100644 index 0000000000..a61956d87b --- /dev/null +++ b/openair1/PHY/TOOLS/simde_operations.c @@ -0,0 +1,60 @@ +/* + * 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 + */ + +#include + +void simde_mm128_separate_real_imag_parts(__m128i *out_re, __m128i *out_im, __m128i in0, __m128i in1) +{ + // Put in0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + in0 = simde_mm_shufflelo_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = simde_mm_shufflehi_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = simde_mm_shuffle_epi32(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // Put xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + in1 = simde_mm_shufflelo_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = simde_mm_shufflehi_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = simde_mm_shuffle_epi32(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + *out_re = simde_mm_unpacklo_epi64(in0, in1); + *out_im = simde_mm_unpackhi_epi64(in0, in1); +} + +void simde_mm256_separate_real_imag_parts(__m256i *out_re, __m256i *out_im, __m256i in0, __m256i in1) +{ + // Put in0 = [Re(0,1,2,3) Im(0,1,2,3) Re(4,5,6,7) Im(4,5,6,7)] + in0 = simde_mm256_shufflelo_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = simde_mm256_shufflehi_epi16(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = simde_mm256_shuffle_epi32(in0, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // Put in1 = [Re(8,9,10,11) Im(8,9,10,11) Re(12,13,14,15) Im(12,13,14,15)] + in1 = simde_mm256_shufflelo_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = simde_mm256_shufflehi_epi16(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = simde_mm256_shuffle_epi32(in1, 0xd8); //_MM_SHUFFLE(0,2,1,3)); + + // Put tmp0 =[Re(0,1,2,3) Re(8,9,10,11) Re(4,5,6,7) Re(12,13,14,15)] + __m256i tmp0 = simde_mm256_unpacklo_epi64(in0, in1); + + // Put tmp1 = [Im(0,1,2,3) Im(8,9,10,11) Im(4,5,6,7) Im(12,13,14,15)] + __m256i tmp1 = simde_mm256_unpackhi_epi64(in0, in1); + + *out_re = simde_mm256_permute4x64_epi64(tmp0, 0xd8); + *out_im = simde_mm256_permute4x64_epi64(tmp1, 0xd8); +} \ No newline at end of file diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 4076352455..060b85f94e 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -851,6 +851,8 @@ c32_t dot_product(const c16_t *x, double interp(double x, double *xs, double *ys, int count); +void simde_mm128_separate_real_imag_parts(__m128i *out_re, __m128i *out_im, __m128i in0, __m128i in1); +void simde_mm256_separate_real_imag_parts(__m256i *out_re, __m256i *out_im, __m256i in0, __m256i in1); #ifdef __cplusplus } From 70270250e853930560a9494e3b852582f75722a0 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 27 Apr 2023 19:43:01 +0100 Subject: [PATCH 024/119] Select Nonlinear ML or Linear MMSE receiver --- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 405a73a5fd..b06b690c0b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1899,9 +1899,6 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, unsigned char harq_pid) { - // Temporary flag: (true) ML receiver, (false) MMSE receiver - bool ml_rx = true; - uint8_t aarx, aatx; uint32_t nb_re_pusch, bwp_start_subcarrier; int avgs = 0; @@ -2002,6 +1999,15 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, uint32_t rxdataF_ext_offset = 0; uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0; + // Flag to select the receiver: (true) Nonlinear ML receiver, (false) Linear MMSE receiver + // By default, we are using the Nonlinear ML receiver, except + // - for 256QAM as Nonlinear ML receiver is not implemented for 256QAM + // - for 64QAM as Nonlinear ML receiver requires more processing time than MMSE, and many machines are not powerful enough + bool ml_rx = true; + if (rel15_ul->nrOfLayers != 2 || rel15_ul->qam_mod_order >= 6) { + ml_rx = false; + } + int ad_shift = 0; if (rel15_ul->nrOfLayers == 1) { ad_shift = 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); From 8cf27b0af81ede6473778e94dbab069dc8439fbd Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 27 Jun 2023 14:05:39 +0200 Subject: [PATCH 025/119] chore(ci-cn): starting 2023/06/22, CN5G images do not support anymore env-variable-based deployment configuration * A common YAML file shall be mounted * Currently SPGWU-TINY is still using the old configuration scheme - But a new UPF is soon to be released Signed-off-by: Raphael Defosseux --- doc/tutorial_resources/oai-cn5g/docker-compose.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/tutorial_resources/oai-cn5g/docker-compose.yml b/doc/tutorial_resources/oai-cn5g/docker-compose.yml index b57942fea0..fc9eab0ad5 100644 --- a/doc/tutorial_resources/oai-cn5g/docker-compose.yml +++ b/doc/tutorial_resources/oai-cn5g/docker-compose.yml @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.70.139 oai-udr: container_name: "oai-udr" - image: oaisoftwarealliance/oai-udr:develop + image: oaisoftwarealliance/oai-udr:v1.5.1 environment: - TZ=Europe/Paris - UDR_NAME=OAI_UDR @@ -58,7 +58,7 @@ services: ipv4_address: 192.168.70.136 oai-udm: container_name: "oai-udm" - image: oaisoftwarealliance/oai-udm:develop + image: oaisoftwarealliance/oai-udm:v1.5.1 environment: - TZ=Europe/Paris - UDM_NAME=OAI_UDM @@ -77,7 +77,7 @@ services: ipv4_address: 192.168.70.137 oai-ausf: container_name: "oai-ausf" - image: oaisoftwarealliance/oai-ausf:develop + image: oaisoftwarealliance/oai-ausf:v1.5.1 environment: - TZ=Europe/Paris - AUSF_NAME=OAI_AUSF @@ -96,7 +96,7 @@ services: ipv4_address: 192.168.70.138 oai-nrf: container_name: "oai-nrf" - image: oaisoftwarealliance/oai-nrf:develop + image: oaisoftwarealliance/oai-nrf:v1.5.1 environment: - TZ=Europe/Paris - NRF_INTERFACE_NAME_FOR_SBI=eth0 @@ -105,7 +105,7 @@ services: ipv4_address: 192.168.70.130 oai-amf: container_name: "oai-amf" - image: oaisoftwarealliance/oai-amf:develop + image: oaisoftwarealliance/oai-amf:v1.5.1 environment: - TZ=Europe/Paris # PLMN informations @@ -151,7 +151,7 @@ services: ipv4_address: 192.168.70.132 oai-smf: container_name: "oai-smf" - image: oaisoftwarealliance/oai-smf:develop + image: oaisoftwarealliance/oai-smf:v1.5.1 environment: - TZ=Europe/Paris - SMF_INTERFACE_NAME_FOR_N4=eth0 @@ -202,7 +202,7 @@ services: ipv4_address: 192.168.70.133 oai-spgwu-tiny: container_name: "oai-spgwu-tiny" - image: oaisoftwarealliance/oai-spgwu-tiny:develop + image: oaisoftwarealliance/oai-spgwu-tiny:v1.5.1 environment: - TZ=Europe/Paris - SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0 From 72927faf06cd7d6f2926a503f17453e22a871665 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 4 Jun 2023 09:43:21 +0200 Subject: [PATCH 026/119] some refactoring in dci configuration --- .../NR_MAC_UE/nr_ue_dci_configuration.c | 141 +++++++++--------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index b3389df86a..8b99818508 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -96,9 +96,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, const NR_SearchSpace_t *ss) { - uint16_t monitoringSymbolsWithinSlot = 0; - int sps = 0; - const NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP; const NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; NR_BWP_Id_t dl_bwp_id = current_DL_BWP ? current_DL_BWP->bwp_id : 0; @@ -187,70 +184,72 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, mac->cg, &mac->def_dci_pdu_rel15[dl_config->slot][dci_format], dci_format, - NR_RNTI_TC, + rnti_type, coreset, dl_bwp_id, ss->searchSpaceType->present, mac->type0_PDCCH_CSS_config.num_rbs, alt_size); - - rel15->BWPStart = coreset_id == 0 ? mac->type0_PDCCH_CSS_config.cset_start_rb : current_DL_BWP->BWPStart; - rel15->BWPSize = coreset_id == 0 ? mac->type0_PDCCH_CSS_config.num_rbs : current_DL_BWP->BWPSize; - - switch(rnti_type) { - case NR_RNTI_C: - // we use DL BWP dedicated - sps = current_DL_BWP->cyclicprefix ? 12 : 14; - // for SPS=14 8 MSBs in positions 13 down to 6 - monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->crnti; - rel15->SubcarrierSpacing = current_DL_BWP->scs; - break; - case NR_RNTI_RA: - // we use the initial DL BWP - sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12; - monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->ra.ra_rnti; - rel15->SubcarrierSpacing = current_DL_BWP->scs; - break; - case NR_RNTI_P: - break; - case NR_RNTI_CS: - break; - case NR_RNTI_TC: - // we use the initial DL BWP - sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12; - monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->ra.t_crnti; - rel15->SubcarrierSpacing = current_DL_BWP->scs; - break; - case NR_RNTI_SP_CSI: - break; - case NR_RNTI_SI: - sps=14; - // for SPS=14 8 MSBs in positions 13 down to 6 - monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - - rel15->rnti = SI_RNTI; // SI-RNTI - 3GPP TS 38.321 Table 7.1-1: RNTI values - - rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; - if(mac->frequency_range == FR2) - rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; - break; - case NR_RNTI_SFI: - break; - case NR_RNTI_INT: - break; - case NR_RNTI_TPC_PUSCH: - break; - case NR_RNTI_TPC_PUCCH: - break; - case NR_RNTI_TPC_SRS: - break; - default: - break; - } } + + rel15->BWPStart = coreset_id == 0 ? mac->type0_PDCCH_CSS_config.cset_start_rb : current_DL_BWP->BWPStart; + rel15->BWPSize = coreset_id == 0 ? mac->type0_PDCCH_CSS_config.num_rbs : current_DL_BWP->BWPSize; + + uint16_t monitoringSymbolsWithinSlot = 0; + int sps = 0; + + switch(rnti_type) { + case NR_RNTI_C: + // we use DL BWP dedicated + sps = current_DL_BWP->cyclicprefix ? 12 : 14; + // for SPS=14 8 MSBs in positions 13 down to 6 + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->crnti; + rel15->SubcarrierSpacing = current_DL_BWP->scs; + break; + case NR_RNTI_RA: + // we use the initial DL BWP + sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12; + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->ra.ra_rnti; + rel15->SubcarrierSpacing = current_DL_BWP->scs; + break; + case NR_RNTI_P: + break; + case NR_RNTI_CS: + break; + case NR_RNTI_TC: + // we use the initial DL BWP + sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12; + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->ra.t_crnti; + rel15->SubcarrierSpacing = current_DL_BWP->scs; + break; + case NR_RNTI_SP_CSI: + break; + case NR_RNTI_SI: + sps=14; + // for SPS=14 8 MSBs in positions 13 down to 6 + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = SI_RNTI; // SI-RNTI - 3GPP TS 38.321 Table 7.1-1: RNTI values + rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; + if(mac->frequency_range == FR2) + rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; + break; + case NR_RNTI_SFI: + break; + case NR_RNTI_INT: + break; + case NR_RNTI_TPC_PUSCH: + break; + case NR_RNTI_TPC_PUCCH: + break; + case NR_RNTI_TPC_SRS: + break; + default: + break; + } + for (int i = 0; i < sps; i++) { if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { rel15->coreset.StartSymbolIndex = i; @@ -263,15 +262,17 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fill_dci_search_candidates(ss, rel15, Y); #ifdef DEBUG_DCI - LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n", - rnti_type, - rel15->BWPSize, - rel15->BWPStart, - rel15->SubcarrierSpacing, - rel15->dci_format_options[0], - rel15->dci_length_options[0], - sps, - monitoringSymbolsWithinSlot); + for (int i = 0; i < rel15->num_dci_options; i++) { + LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n", + rnti_type, + rel15->BWPSize, + rel15->BWPStart, + rel15->SubcarrierSpacing, + rel15->dci_format_options[i], + rel15->dci_length_options[i], + sps, + monitoringSymbolsWithinSlot); + } #endif // add DCI dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; From 409df4bb982e516602490aac8dca0170ca838f2a Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 4 Jun 2023 09:51:00 +0200 Subject: [PATCH 027/119] remove unnecessary part of dci scehduler for RA --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b60e0199a2..b1be2a6190 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -951,7 +951,7 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) nr_scheduled_response_t scheduled_response; nr_dcireq_t dcireq; - if(mac->state == UE_CONNECTED) { + if(mac->state > UE_NOT_SYNC) { dcireq.module_id = mod_id; dcireq.gNB_index = gNB_index; @@ -964,8 +964,10 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) if(mac->ul_time_alignment.ta_apply) schedule_ta_command(dl_config, &mac->ul_time_alignment); - nr_schedule_csirs_reception(mac, rx_frame, rx_slot); - nr_schedule_csi_for_im(mac, rx_frame, rx_slot); + if(mac->state == UE_CONNECTED) { + nr_schedule_csirs_reception(mac, rx_frame, rx_slot); + nr_schedule_csi_for_im(mac, rx_frame, rx_slot); + } dcireq.dl_config_req = *dl_config; fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data); @@ -974,19 +976,6 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) mac->if_module->scheduled_response(&scheduled_response); } } - else if (mac->state == UE_PERFORMING_RA) { - // this is for Msg2/Msg4 - if (mac->ra.ra_state >= WAIT_RAR) { - if(mac->ul_time_alignment.ta_apply) - schedule_ta_command(dl_config, &mac->ul_time_alignment); - config_dci_pdu(mac, dl_config, mac->ra.ra_state == WAIT_RAR ? NR_RNTI_RA : NR_RNTI_TC , rx_slot, mac->ra_SS); - dl_config->number_pdus = 1; - LOG_D(MAC,"mac->cg %p: Calling fill_scheduled_response for type0_pdcch, num_pdus %d\n", mac->cg, dl_config->number_pdus); - fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); - } - } else dl_config->number_pdus = 0; } From 8c2c89491c50aeb375547e369365273e899a778a Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 6 Jun 2023 12:40:34 +0200 Subject: [PATCH 028/119] fix for not initialized pduBitmap --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 6c8a0f337f..4bd00691df 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -653,6 +653,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_0 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; + dlsch_config_pdu_1_0->pduBitmap = 0; + NR_PDSCH_Config_t *pdsch_config = current_DL_BWP ? current_DL_BWP->pdsch_Config : NULL; if (dci_ind->ss_type == NR_SearchSpace__searchSpaceType_PR_common) { dlsch_config_pdu_1_0->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs ? mac->type0_PDCCH_CSS_config.num_rbs : current_DL_BWP->initial_BWPSize; From 1da7cada4858ad0bcbbe36dca151512fbc0e8b42 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 7 Jun 2023 19:10:47 +0200 Subject: [PATCH 029/119] solution to L2 failure -> handling switch to 1_0 --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 4bd00691df..1f1bdd402b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -443,13 +443,14 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); - int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15, slot); - if ((ret&1) == 1) return -1; + int ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15, slot); + if ((ret&1) == 1) + return -1; else if (ret == 2) { - dci->dci_format = NR_UL_DCI_FORMAT_0_0; + dci->dci_format = (dci->dci_format == NR_UL_DCI_FORMAT_0_0) ? NR_DL_DCI_FORMAT_1_0 : NR_UL_DCI_FORMAT_0_0; def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format]; } - int8_t ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); + int ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); return ret_proc; } @@ -2849,7 +2850,7 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci_pdu_rel15, int slot) { - + LOG_D(MAC,"nr_extract_dci_info : dci_pdu %lx, size %d, format %d\n", *dci_pdu, dci_size, dci_format); int pos = 0; int fsize = 0; int rnti_type = get_rnti_type(mac, rnti); @@ -2866,7 +2867,7 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, current_DL_BWP->initial_BWPSize); else N_RB = mac->type0_PDCCH_CSS_config.num_rbs; - LOG_D(MAC,"nr_extract_dci_info : dci_pdu %lx, size %d\n",*dci_pdu,dci_size); + switch(dci_format) { case NR_DL_DCI_FORMAT_1_0: @@ -2916,7 +2917,7 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_UL_DCI_FORMAT_0_0]; - return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); + return 2 + nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); } #ifdef DEBUG_EXTRACT_DCI LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu); @@ -3107,7 +3108,7 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_UL_DCI_FORMAT_0_0]; - return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); + return 2 + nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); } // Freq domain assignment 0-16 bit @@ -3248,8 +3249,13 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, #ifdef DEBUG_EXTRACT_DCI LOG_I(MAC,"Format indicator %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,dci_size-pos,*dci_pdu); #endif - if (dci_pdu_rel15->format_indicator == 1) - return 1; // discard dci, format indicator not corresponding to dci_format + + //switch to DCI_1_0 + if (dci_pdu_rel15->format_indicator == 1) { + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_DL_DCI_FORMAT_1_0]; + return 2 + nr_extract_dci_info(mac, NR_DL_DCI_FORMAT_1_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); + } + fsize = dci_pdu_rel15->frequency_domain_assignment.nbits; pos+=fsize; dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1< Date: Tue, 27 Jun 2023 19:20:34 +0200 Subject: [PATCH 030/119] review --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 7 +++---- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 1f1bdd402b..b1e0c17cc8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -443,15 +443,14 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); - int ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15, slot); - if ((ret&1) == 1) + const int ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15, slot); + if ((ret & 1) == 1) return -1; else if (ret == 2) { dci->dci_format = (dci->dci_format == NR_UL_DCI_FORMAT_0_0) ? NR_DL_DCI_FORMAT_1_0 : NR_UL_DCI_FORMAT_0_0; def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format]; } - int ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); - return ret_proc; + return nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); } int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b1be2a6190..51c4d6f184 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -951,7 +951,7 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) nr_scheduled_response_t scheduled_response; nr_dcireq_t dcireq; - if(mac->state > UE_NOT_SYNC) { + if(mac->state > UE_NOT_SYNC) { dcireq.module_id = mod_id; dcireq.gNB_index = gNB_index; From c44dcefd1691d6ddd6725929d2be06f12a1167cb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 16 Jun 2023 19:39:22 +0200 Subject: [PATCH 031/119] Document environment variables used by OAI programs --- doc/README.md | 1 + doc/environment-variables.md | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 doc/environment-variables.md diff --git a/doc/README.md b/doc/README.md index 6abca52f0b..25696d8237 100644 --- a/doc/README.md +++ b/doc/README.md @@ -20,6 +20,7 @@ - [GET_SOURCES.md](./GET_SOURCES.md): how to download the sources - [BUILD.md](./BUILD.md): how to build the sources - [clang-format.md](./clang-format.md): how to format the code +- [environment-variables.md](./environment-variables.md): the environment variables used by OAI There is some general information in the [OpenAirInterface Gitlab Wiki](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/home) diff --git a/doc/environment-variables.md b/doc/environment-variables.md new file mode 100644 index 0000000000..5b2ae52030 --- /dev/null +++ b/doc/environment-variables.md @@ -0,0 +1,21 @@ +# Environment variables + +OAI uses/supports a number of environment variables, documented in the following: + +- `NFAPI_TRACE_LEVEL`: set the nfapi custom logging framework's log level; can be one of `error`, `warn`, `note`, `info`, `debug` +- `NR_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in SISO case +- `NR_MIMO2x2_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in 2x2 MIMO case +- `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) +- `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` +- `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation +- `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) +- `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) +- `gdbStacks`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread +- `threadPoolMeasurements`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) + +Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: +- `HOST`: alternative host to connect to, for CLI, if neither `REMADDR` nor `SSH_CLIENT` are defined +- `REMADDR`: host to connect to, for CLI client +- `SSH_CLIENT`: alternative host to connect to, for CLI, if `REMADDR` is not defined +- `USER`: user name in the command-line interface +- `rftestInputFile`: input file for the `calibration_test` tool From 01d1a47adfb9da2efee6ad1050d8d8e3a52b4494 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 16 Jun 2023 19:40:13 +0200 Subject: [PATCH 032/119] Remove commented code that uses getenv(): it might be confusing if reactivated --- openair1/PHY/CODING/TESTBENCH/polartest.c | 2 -- openair1/SIMULATION/LTE_PHY/dlsim.c | 2 -- openair1/SIMULATION/LTE_PHY/dlsim_tm4.c | 2 -- openair1/SIMULATION/LTE_PHY/dlsim_tm7.c | 2 -- openair1/SIMULATION/LTE_PHY/mbmssim.c | 2 -- openair1/SIMULATION/LTE_PHY/ulsim.c | 3 --- 6 files changed, 13 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index 7c1534ca51..462ad53a6e 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -128,8 +128,6 @@ int main(int argc, char *argv[]) char fileName[512], currentTimeInfo[25]; char folderName[] = "."; FILE *logFile = NULL; - /*folderName=getenv("HOME"); - strcat(folderName,"/Desktop/polartestResults");*/ if (logFlag){ time (¤tTime); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index c7e4f27f70..88e8727245 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -1019,8 +1019,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c index 9a086e1a7f..2f26be3d84 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c @@ -887,8 +887,6 @@ int main(int argc, char **argv) hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c index 030a6b6cc6..84480dfdde 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c @@ -649,8 +649,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index accb6004f8..331b16b9bf 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -1147,8 +1147,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index a9f8ca823e..70622b2120 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -653,9 +653,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s//SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname); - //mkdir(dirname, 0777); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_antrx%d_channel%s_tx%d.csv", N_RB_DL,mcs,n_rx,channel_model_input,transmission_m); time_meas_fd = fopen(time_meas_fname,"w"); From ba11dfba4ec735ca0742cdd15cc7e012125d5c2f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:18:26 +0200 Subject: [PATCH 033/119] Rename env var gdbStacks to OAI_GDBSTACKS - make it clear that it belongs to OAI - follow convention of uppercase name --- common/utils/assertions.h | 2 +- doc/environment-variables.md | 2 +- docker/scripts/enb_entrypoint.sh | 2 +- docker/scripts/gnb-aw2s_entrypoint.sh | 2 +- docker/scripts/gnb_entrypoint.sh | 2 +- docker/scripts/lte_ru_entrypoint.sh | 2 +- docker/scripts/lte_ue_entrypoint.sh | 2 +- docker/scripts/nr_ue_entrypoint.sh | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/utils/assertions.h b/common/utils/assertions.h index 3424392e7a..453e853aec 100644 --- a/common/utils/assertions.h +++ b/common/utils/assertions.h @@ -33,7 +33,7 @@ #define OAI_EXIT_ASSERT 1 #define _Assert_Exit_ \ - if (getenv("gdbStacks")) { \ + if (getenv("OAI_GDBSTACKS")) { \ char tmp [1000]; \ sprintf(tmp,"gdb -ex='set confirm off' -ex 'thread apply all bt' -ex q -p %d < /dev/null", getpid()); \ __attribute__((unused)) int dummy=system(tmp); \ diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 5b2ae52030..9137533e8a 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -7,10 +7,10 @@ OAI uses/supports a number of environment variables, documented in the following - `NR_MIMO2x2_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in 2x2 MIMO case - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` +- `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) -- `gdbStacks`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread - `threadPoolMeasurements`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: diff --git a/docker/scripts/enb_entrypoint.sh b/docker/scripts/enb_entrypoint.sh index aadd8b71d1..cda5793ab3 100755 --- a/docker/scripts/enb_entrypoint.sh +++ b/docker/scripts/enb_entrypoint.sh @@ -26,7 +26,7 @@ elif [[ -v USE_N3XX ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting eNB soft modem" diff --git a/docker/scripts/gnb-aw2s_entrypoint.sh b/docker/scripts/gnb-aw2s_entrypoint.sh index b03e214ce1..752e3005ed 100755 --- a/docker/scripts/gnb-aw2s_entrypoint.sh +++ b/docker/scripts/gnb-aw2s_entrypoint.sh @@ -15,7 +15,7 @@ echo "== Configuration file:" cat $CONFIGFILE # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting gNB soft modem with AW2S" diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh index ef268b1143..230f3f0f7d 100755 --- a/docker/scripts/gnb_entrypoint.sh +++ b/docker/scripts/gnb_entrypoint.sh @@ -27,7 +27,7 @@ elif [[ -v USE_N3XX ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting gNB soft modem" diff --git a/docker/scripts/lte_ru_entrypoint.sh b/docker/scripts/lte_ru_entrypoint.sh index 4ce5615482..0305cf27ff 100755 --- a/docker/scripts/lte_ru_entrypoint.sh +++ b/docker/scripts/lte_ru_entrypoint.sh @@ -26,7 +26,7 @@ elif [[ -v USE_N3XX ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting eNB soft modem" diff --git a/docker/scripts/lte_ue_entrypoint.sh b/docker/scripts/lte_ue_entrypoint.sh index a8d0f8fd1a..f88692a957 100755 --- a/docker/scripts/lte_ue_entrypoint.sh +++ b/docker/scripts/lte_ue_entrypoint.sh @@ -52,7 +52,7 @@ if [[ -f "$CONFIGFILE" ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting LTE UE soft modem" diff --git a/docker/scripts/nr_ue_entrypoint.sh b/docker/scripts/nr_ue_entrypoint.sh index 840a8ae729..e84386276a 100755 --- a/docker/scripts/nr_ue_entrypoint.sh +++ b/docker/scripts/nr_ue_entrypoint.sh @@ -33,7 +33,7 @@ while [[ $# -gt 0 ]]; do done # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting NR UE soft modem" From 49703eee7b1a2a806d59ba445745ad8e2713d78c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:19:41 +0200 Subject: [PATCH 034/119] Rename threadPoolMeasurements to OAI_THREADPOOLMEASUREMENTS - make it clear that it belongs to OAI - follow convention of uppercase name --- common/utils/threadPool/thread-pool.c | 2 +- common/utils/threadPool/thread-pool.md | 4 ++-- doc/environment-variables.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index 5531a3aed3..1a2fafdbf8 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -106,7 +106,7 @@ void *one_thread(void *arg) { void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name) { memset(pool,0,sizeof(*pool)); - char *measr=getenv("threadPoolMeasurements"); + char *measr=getenv("OAI_THREADPOOLMEASUREMENTS"); pool->measurePerf=performanceMeas; // force measurement if the output is defined pool->measurePerf |= measr!=NULL; diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md index 311857ff3e..02dd9e0387 100644 --- a/common/utils/threadPool/thread-pool.md +++ b/common/utils/threadPool/thread-pool.md @@ -182,7 +182,7 @@ Returns the total number of jobs that were aborted, i.e., waiting for execution ## Performance measurements -A performance measurement is integrated: the pool will automacillay fill timestamps if you set the environement variable `threadPoolMeasurements` to a valid file name. The following measurements will be written to Linux pipe on a per-job basis: +A performance measurement is integrated: the pool will automacillay fill timestamps if you set the environement variable `OAI_THREADPOOLMEASUREMENTS` to a valid file name. The following measurements will be written to Linux pipe on a per-job basis: * `creationTime`: time the request is push to the pool; * `startProcessingTime`: time a worker start to run on the job @@ -193,6 +193,6 @@ The `measurement_display` tool to read the Linux pipe and display it in ASCII is In the cmake build directory, type `make/ninja measurement_display`. Use as follows: ``` -sudo threadPoolMeasurements=tpool.meas ./nr-softmodem ... +sudo OAI_THREADPOOLMEASUREMENTS=tpool.meas ./nr-softmodem ... ./measurement_display tpool.meas ``` diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 9137533e8a..9439ebd64c 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -8,10 +8,10 @@ OAI uses/supports a number of environment variables, documented in the following - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread +- `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) -- `threadPoolMeasurements`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: - `HOST`: alternative host to connect to, for CLI, if neither `REMADDR` nor `SSH_CLIENT` are defined From 710bfdbf048d699bcc72eeb06e9aef19be19330c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:45:52 +0200 Subject: [PATCH 035/119] Introduce env var OAI_RNGSEED can be used to set a random number generator (RNG) seed uniformly from command line --- doc/environment-variables.md | 1 + openair1/SIMULATION/TOOLS/rangen_double.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 9439ebd64c..30742b3892 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -8,6 +8,7 @@ OAI uses/supports a number of environment variables, documented in the following - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread +- `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators - `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) diff --git a/openair1/SIMULATION/TOOLS/rangen_double.c b/openair1/SIMULATION/TOOLS/rangen_double.c index 9c10275c17..80bb33fc6a 100644 --- a/openair1/SIMULATION/TOOLS/rangen_double.c +++ b/openair1/SIMULATION/TOOLS/rangen_double.c @@ -55,6 +55,8 @@ void randominit(unsigned long seed_init) unsigned long seed = seed_init; if (seed_init == 0) fill_random(&seed, sizeof(seed)); + if (getenv("OAI_RNGSEED")) + seed = atoi(getenv("OAI_RNGSEED")); printf("Initializing random number generator, seed %lu\n", seed); // initialize uniformrandom RNG From 7a3aaca1ef4fecf476f9d78b40704fa90f56916f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 22 Jun 2023 12:18:54 +0200 Subject: [PATCH 036/119] Print warning if RFSIMULATOR environment variable is used --- radio/rfsimulator/simulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 4db78e9659..1175d9ec42 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -312,6 +312,9 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { /* for compatibility keep environment variable usage */ if ( getenv("RFSIMULATOR") != NULL ) { rfsimulator->ip=getenv("RFSIMULATOR"); + LOG_W(HW, "The RFSIMULATOR environment variable is deprecated and support will be removed in the future. Instead, add parameter --rfsimulator.serveraddr %s to set the server address. Note: the default is \"server\"; for the gNB/eNB, you don't have to set any configuration.\n", rfsimulator->ip); + LOG_I(HW, "Remove RFSIMULATOR environment variable to get rid of this message and the sleep.\n"); + sleep(10); } if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || From 04247d501d5972e0598e7c7e8a0c261b9abaf43e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 22 Jun 2023 12:37:26 +0200 Subject: [PATCH 037/119] Remove RFSIMULATOR environment variable from repository --- .../4g_rfsimulator_fdd_05MHz/docker-compose.yml | 4 +--- .../docker-compose.yml | 4 +--- .../4g_rfsimulator_fdd_10MHz/docker-compose.yml | 4 +--- .../4g_rfsimulator_fdd_20MHz/docker-compose.yml | 4 +--- .../4g_rfsimulator_fembms/docker-compose.yml | 4 +--- .../4g_rfsimulator_mbms/docker-compose.yml | 4 +--- .../4g_rfsimulator_tdd_05MHz/docker-compose.yml | 4 +--- .../5g_f1_rfsimulator/docker-compose.yaml | 5 +---- .../5g_fdd_rfsimulator/docker-compose.yaml | 4 +--- ci-scripts/yaml_files/5g_rfsimulator/README.md | 3 +-- .../5g_rfsimulator/docker-compose.yaml | 7 ++----- .../5g_rfsimulator_24prb/docker-compose.yaml | 4 +--- .../5g_rfsimulator_2x2/docker-compose.yaml | 4 +--- .../docker-compose.yaml | 4 +--- .../5g_rfsimulator_e1/docker-compose.yaml | 4 +--- .../docker-compose.yaml | 4 +--- .../5g_rfsimulator_fr2_32prb/docker-compose.yaml | 4 +--- .../5g_rfsimulator_tdd_dora/docker-compose.yaml | 4 +--- .../5g_rfsimulator_u0_25prb/docker-compose.yaml | 4 +--- doc/E1-design.md | 2 +- doc/NR_SA_Tutorial_OAI_nrUE.md | 2 +- doc/RUNMODEM.md | 4 ++-- doc/RUN_NR_NFAPI.md | 2 +- doc/RUN_NR_PRS.md | 12 ++++++++---- doc/RUN_NR_multiple_BWPs.md | 4 ++-- doc/SystemX-tutorial-design.md | 7 ++----- doc/environment-variables.md | 1 - radio/rfsimulator/README.md | 16 +++++++--------- radio/rfsimulator/simulator.c | 8 -------- 29 files changed, 44 insertions(+), 93 deletions(-) diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml index ca005e9568..7acbc62bd7 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.25prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml index bb0bb9f982..8c79cbeca2 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml @@ -10,7 +10,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/enb.band7.25prb.rfsim.nos1.conf:/opt/oai-enb/etc/enb.conf @@ -31,8 +30,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time --noS1 + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml index 1ba0178949..b26fd4cac2 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.50prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 50 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 50 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml index edde78480e..128eafaf5d 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.100prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 100 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 100 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml index f568989f3f..8da7c4041c 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml @@ -10,7 +10,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --eNBs.[0].component_carriers.[0].mbms_dedicated_serving_cell ENABLE --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf @@ -29,8 +28,7 @@ services: ipv4_address: 192.168.61.30 environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --log_config.global_log_options level,nocolor,time --noS1 + USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/lteue.usim-mbs.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml index 5dc9ae1a04..159943a76a 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml @@ -10,7 +10,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf @@ -34,8 +33,7 @@ services: environment: TZ: Europe/Paris HOSTNAME: oai_ue0 - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --log_config.global_log_options level,nocolor,time --noS1 + USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/lteue.usim-mbs.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml index 18ab587731..b592997edc 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band38.25prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -T -C 2605000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -T -C 2605000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index dd2a1b2cdd..dd8c62d97d 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-cu environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,7 +185,6 @@ services: privileged: true container_name: rfsim5g-oai-du environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-cu @@ -205,8 +203,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.142 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --rfsimulator.serveraddr 192.168.71.142 --log_config.global_log_options level,nocolor,time depends_on: - oai-du networks: diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 42fe53b2b9..93da3f9f0f 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,8 +185,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169080000 --CO -400000000 --ssb 378 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169080000 --CO -400000000 --ssb 378 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index b516e93813..a018c085d6 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -244,13 +244,12 @@ Create entry for Second UE in docker-compose.yaml file as follows: privileged: true container_name: rfsim5g-oai-nr-ue2 environment: - RFSIMULATOR: 192.168.71.140 FULL_IMSI: '208990100001101' FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' OPC: 'C42449363BBAD02B66D16BC975D77CC1' DNN: oai NSSAI_SST: 1 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index e4129adee2..21792e35bf 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,8 +185,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -206,8 +204,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue2 environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index f076cf2db0..c0c61b4e3b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,8 +185,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 4d3e8b7dde..cd5c28b9ff 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -187,8 +186,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml index e43bc0e0d9..7d2270b7c9 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml @@ -6,7 +6,6 @@ services: container_name: rfsim5g-oai-du network_mode: "host" environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --MACRLCs.[0].local_n_address 172.21.16.109 --MACRLCs.[0].remote_n_address 172.21.6.22 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/gnb-du.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf @@ -21,8 +20,7 @@ services: container_name: rfsim5g-oai-nr-ue network_mode: "host" environment: - RFSIMULATOR: 127.0.0.1 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 208990100001140 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 208990100001140 --rfsimulator.serveraddr 127.0.0.1 --log_config.global_log_options level,nocolor,time depends_on: - oai-du volumes: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index b44822b3e8..71f00f96c2 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -212,7 +212,6 @@ services: privileged: true container_name: rfsim5g-oai-du environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time networks: ran_net: @@ -230,8 +229,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.72.142 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --rfsimulator.serveraddr 192.168.72.142 --log_config.global_log_options level,nocolor,time depends_on: - oai-du networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml index b654f06d12..7c17f96957 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml @@ -5,7 +5,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time networks: public_net: @@ -24,8 +23,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --noS1 --rrc_config_path etc/rrc/ --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --noS1 --rrc_config_path etc/rrc/ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index eef67d713b..2f36192188 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -5,7 +5,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time networks: public_net: @@ -24,8 +23,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index ed2af44fbb..1a83cd6678 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -5,7 +5,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time networks: public_net: @@ -24,8 +23,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index f2c90fa7c7..14a989934b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -187,8 +186,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152250000 --CO -400000000 --ssb 76 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152250000 --CO -400000000 --ssb 76 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/doc/E1-design.md b/doc/E1-design.md index 90e0807793..6f9e8f4edd 100644 --- a/doc/E1-design.md +++ b/doc/E1-design.md @@ -96,7 +96,7 @@ You need to use `--rfsim` if you are running the test with rfsimulator. OAI UE: ``` -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --rfsimulator.serveraddr 127.0.0.1 ``` # 3. Configuration file IP addresses of network functions diff --git a/doc/NR_SA_Tutorial_OAI_nrUE.md b/doc/NR_SA_Tutorial_OAI_nrUE.md index 0d0ec23346..81c861bdfa 100644 --- a/doc/NR_SA_Tutorial_OAI_nrUE.md +++ b/doc/NR_SA_Tutorial_OAI_nrUE.md @@ -168,7 +168,7 @@ Run OAI nrUE with RFsimulator cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1 ``` ### 5.2.1 Ping test diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index d32758b1a2..dde31cbd2f 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -166,8 +166,8 @@ In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB by To run using the RFsimulator: ```bash -sudo RFSIMULATOR=gnb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD +sudo ./nr-uesoftmodem --do-ra --rfsim --rfsimulator.serveraddr 127.0.0.1 --parallel-config PARALLEL_SINGLE_THREAD ``` Using USRPs: diff --git a/doc/RUN_NR_NFAPI.md b/doc/RUN_NR_NFAPI.md index e294703d44..503fead0ed 100644 --- a/doc/RUN_NR_NFAPI.md +++ b/doc/RUN_NR_NFAPI.md @@ -31,7 +31,7 @@ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfap ``` ### UE command ``` -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d +sudo ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d --rfsimulator.serveraddr 127.0.0.1 ``` ## Procedure to run NR nFAPI using Hardware (tested with USRP x310) diff --git a/doc/RUN_NR_PRS.md b/doc/RUN_NR_PRS.md index 5cdb47c04b..64e754cb0f 100644 --- a/doc/RUN_NR_PRS.md +++ b/doc/RUN_NR_PRS.md @@ -71,7 +71,7 @@ If **N310 USRPs** are used, then run above command `without -E option` i.e witho To run using **rfsimulator**, execute following command: -```sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` +```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` ## FR2 test In FR2 mode, we need RF beamforming module to transmit signal in mmWave frequency range. **X310 USRPs** can be used with BasicTx daughtercard to transmit baseband signal at **Intermediate Frequncy(IF)** and then RF beamforming module would perform beamforming and the upconversion to FR2 frequencies. IF can be specified using `if_freq` in the RU section of gNB config. @@ -83,7 +83,7 @@ If RF beamforming module is NOT present, gNB can still be launched with USRP alo To run using **rfsimulator**, execute following command: -```sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` +```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` ## Multiple gNB scenario PRS is primarily used for positioning and localization of the UE with multiple gNBs transmitting simultaneously. OAI PRS implementation supports multiple gNB transmission provided all the gNBs are tightely synchronized using GPSDO clock. Therefore before running this scenario, make sure the USRPs has built-in GPSDO and the GPS antennas are connected with good satellite visibility. Also every time a gNB is launched, wait until `GPS LOCKED` is printed on the terminal during gNB startup. If USRP fails to lock with GPSDO, try again until its locked. @@ -112,7 +112,9 @@ If **N310 USRPs** are used, then run above command `without -E option` i.e witho To run using **rfsimulator** with local ETH IF `127.0.0.1`, execute following command: -```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf``` +``` +sudo ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf --rfsimulator.serveraddr 127.0.0.1 +``` ## FR2 test Like gNB, RF beamforming module is receiving at mmWave frequencies and then **X310 USRPs** with BasicRx daughtercard to receive the signal at intermediate frequncy(IF) from RF beamforming module. IF can be specified using `--if_freq` option in nrUE command line. @@ -124,7 +126,9 @@ If RF beamforming module is NOT present, nrUE can still be launched with USRP al To run using **rfsimulator** with local ETH IF `127.0.0.1`, execute following command: -```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr2.64prb.conf``` +``` +sudo ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr2.64prb.conf --rfsimulator.serveraddr 127.0.0.1 +``` ## Multiple gNB scenario In nrUE prs config file, change `Active_gNBs` to the actual number of gNBs launched. Also verify the parameter in `prs_config` sections of nrUE config is matching with that of gNB config used. And launch nrUE using one of the above commands depending on FR1/FR2 test scenario. diff --git a/doc/RUN_NR_multiple_BWPs.md b/doc/RUN_NR_multiple_BWPs.md index 80a0515b56..c6b497043a 100644 --- a/doc/RUN_NR_multiple_BWPs.md +++ b/doc/RUN_NR_multiple_BWPs.md @@ -47,5 +47,5 @@ Each dedicated BWP must have: ## UE command: ``` - sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 208990000000001 -``` \ No newline at end of file + sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 208990000000001 --rfsimulator.serveraddr 127.0.0.1 +``` diff --git a/doc/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md index 804658fd4d..62761417bc 100644 --- a/doc/SystemX-tutorial-design.md +++ b/doc/SystemX-tutorial-design.md @@ -133,14 +133,11 @@ Usage with RFsimulator: **gNB** ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O \ -../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf \ ---parallel-config PARALLEL\_SINGLE\_THREAD +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL\_SINGLE\_THREAD ``` **nrUE** ```bash -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C \ -3510000000 -d +sudo ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000 -d --rfsimulator.serveraddr 127.0.0.1 ``` diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 30742b3892..31520b0a2d 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -11,7 +11,6 @@ OAI uses/supports a number of environment variables, documented in the following - `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators - `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation -- `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md index 357e70e5a6..e8baff472c 100644 --- a/radio/rfsimulator/README.md +++ b/radio/rfsimulator/README.md @@ -57,8 +57,6 @@ The RF simulator is using the configuration module, and its parameters are defin | modelname | Name of the channel model to apply on received iqs when the `chanmod` option is enabled | AWGN | | IQfile | Path to the file to be used to store iqs, when the `saviq` option is enabled | /tmp/rfsimulator.iqs | -Setting the env variable RFSIMULATOR can be used instead of using the serveraddr parameter; it is to preserve compatibility with previous version. - ## How to use the RF simulator options To define and use a channel model, the configuration file needs to include a channel configuration file. To do this, add `@include "channelmod_rfsimu.conf"` to the end of the configuration file, and place the channel configuration file in the same directory. An example channel configuration file `channelmod_rfsimu.conf` is in `ci-scripts/conf_files`. @@ -81,7 +79,7 @@ set the model with: Example run: ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN ``` where `@include "channelmod_rfsimu.conf"` has been added at the end of the file, and `ci-scripts/conf_files/channelmod_rfsimu.conf` copied to `targets/PROJECTS/GENERIC-LTE-EPC/CONF/`. @@ -90,11 +88,11 @@ where `@include "channelmod_rfsimu.conf"` has been added at the end of the file, For the UE, it should be set to the IP address of the eNB. For example: ```bash -sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 +sudo ./lte-uesoftmodem -C 2685000000 -r 50 --rfsimulator.serveraddr 192.168.2.200 ``` For the eNB, use a valid configuration file setup for the USRP board tests and start the softmodem as usual, **but**, adding the `--rfsim` option. ```bash -sudo RFSIMULATOR=enb ./lte-softmodem -O --rfsim +sudo ./lte-softmodem -O --rfsim ``` Except this, the UE and the eNB can be used as if the RF is real. noS1 mode can also be used with the RF simulator. @@ -115,13 +113,13 @@ make rfsimulator ### Launch gNB in one window ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test ``` ### Launch UE in another window ```bash -sudo RFSIMULATOR= ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . +sudo ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . --rfsimulator.serveraddr ``` Notes: @@ -131,7 +129,7 @@ Notes: 3. The --rrc_config_path parameter SHALL specify where the 2 RAW files are located (`rbconfig.raw` and `reconfig.raw`). - If you are running on the same machine and launched the 2 executables (`nr-softmodem` and `nr-uesoftmodem`) from the same directory, nothing has to be done. - If you launched the 2 executables from 2 different folders, just point to the location where you launched the `nr-softmodem`: - * `sudo RFSIMULATOR= ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path /the/path/where/you/launched/nr-softmodem` + * `sudo ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path /the/path/where/you/launched/nr-softmodem --rfsimulator.serveraddr ` - If you are not running on the same machine or launched the 2 executables from 2 different folders, you need to **COPY** the 2 raw files * `scp usera@machineA:/the/path/where/you/launched/nr-softmodem/r*config.raw userb@machineB:/the/path/where/you/will/launch/nr-uesoftmodem/` * Obviously this operation SHALL be done before launching the `nr-uesoftmodem` executable. @@ -203,7 +201,7 @@ to add a lot of noise: Example run commands: ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN ``` # Real time control and monitoring diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 1175d9ec42..1a4e05c20d 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -219,14 +219,6 @@ static void socketError(rfsimulator_state_t *bridge, int sock) { } } -#define helpTxt "\ -\x1b[31m\ -rfsimulator: error: you have to run one UE and one eNB\n\ -For this, export RFSIMULATOR=enb (eNB case) or \n\ - RFSIMULATOR= (UE case)\n\ - or use rfsimulator.serveraddr configuration option\n\ -\x1b[m" - enum blocking_t { notBlocking, blocking From 40640f943e345a8653ef49cc5f112c9b7dd45172 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 24 Jun 2023 18:41:16 +0200 Subject: [PATCH 038/119] Add RFsimulator server option to rfsim configs --- ci-scripts/conf_files/enb.band38.25prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.100prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.25prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf | 4 ++++ ci-scripts/conf_files/enb.band7.50prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf | 4 ++++ ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf | 4 ++++ ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf | 4 ++++ ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf | 4 ++++ ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf | 4 ++++ 11 files changed, 44 insertions(+) diff --git a/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf b/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf index 79f4fce746..e19cd4d68a 100644 --- a/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf @@ -208,6 +208,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf b/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf index 71fbc663fe..3c0b994017 100644 --- a/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf b/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf index 71e9029c4b..c5d8383860 100644 --- a/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf b/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf index 71e9029c4b..c5d8383860 100644 --- a/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf +++ b/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf b/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf index 4e037ab3da..abfc3887cd 100644 --- a/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf index e98896ac5d..e0b5dc7257 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf @@ -374,6 +374,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf index e460fb0a4d..7603148fb7 100644 --- a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf @@ -234,6 +234,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf index f4f65fe8dc..5bf2525092 100644 --- a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf @@ -212,6 +212,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index 453b03910b..ab6c6b2467 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -221,6 +221,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf index 9728977d21..ff1651c89a 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf @@ -254,6 +254,10 @@ THREAD_STRUCT = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf index 9a6efada5b..a90174f3b7 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf @@ -219,6 +219,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" From 2ce109cd633eeaea7756c8f5a18ba422054d42cc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 24 Jun 2023 18:41:38 +0200 Subject: [PATCH 039/119] Remove RFsimulator server option from non-rfsim configs --- .../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf | 7 ------- ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf | 9 --------- .../conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf | 9 --------- 3 files changed, 25 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 8234a17020..26b2a4f111 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -217,13 +217,6 @@ THREAD_STRUCT = ( worker_config = "WORKER_ENABLE"; } ); -rfsimulator: { -serveraddr = "server"; - serverport = "4043"; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs" -} log_config : { diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf index 16cc70ca4b..d208d098af 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf @@ -226,15 +226,6 @@ THREAD_STRUCT = ( } ); -rfsimulator : -{ - serveraddr = "server"; - serverport = "4043"; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs"; -}; - security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf index a90174f3b7..485f395019 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf @@ -232,15 +232,6 @@ THREAD_STRUCT = ( } ); -rfsimulator : -{ - serveraddr = "server"; - serverport = "4043"; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs"; -}; - security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen From e45da1a6fa7e587f3682c8cb55bbd678a32e1585 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 22 Jun 2023 19:18:29 +0200 Subject: [PATCH 040/119] moving handling of RA success for reconfigurationWithSync at RRC --- .../SIMULATION/NR_PHY/nr_dummy_functions.c | 2 ++ openair2/COMMON/mac_messages_def.h | 2 ++ openair2/COMMON/mac_messages_types.h | 10 ++++++++- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- openair2/RRC/NR_UE/L2_interface_ue.c | 12 +++++------ openair2/RRC/NR_UE/rrc_UE.c | 21 +++++++++++++++++++ openair2/RRC/NR_UE/rrc_proto.h | 1 + 7 files changed, 41 insertions(+), 9 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index dccdce2934..6d3948974d 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -32,6 +32,8 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync) {} +void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) {} + void rrc_data_ind(const protocol_ctxt_t *const ctxt_pP, const rb_id_t Srb_id, const sdu_size_t sdu_sizeP, diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index d4a923b90b..50e7a108c9 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -48,6 +48,8 @@ MESSAGE_DEF(RRC_MAC_MCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDat MESSAGE_DEF(RRC_MAC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacPcchDataReq, rrc_mac_pcch_data_req) +MESSAGE_DEF(NR_RRC_MAC_RA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacRaInd, nr_rrc_mac_ra_ind) + /* RRC configures DRX context (MAC timers) of a UE */ MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req_t, rrc_mac_drx_config_req) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index fde990b0fe..5703a886c0 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -54,7 +54,9 @@ #define RRC_MAC_MCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_ind #define RRC_MAC_PCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_pcch_data_req -#define RRC_MAC_DRX_CONFIG_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_drx_config_req +#define NR_RRC_MAC_RA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_ra_ind + +#define RRC_MAC_DRX_CONFIG_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_drx_config_req // Some constants from "LAYER2/MAC/defs.h" #define BCCH_SDU_SIZE (512) @@ -65,6 +67,12 @@ //-------------------------------------------------------------------------------------------// // Messages between RRC and MAC layers + +typedef struct NRRrcMacRaInd_s { + uint32_t frame; + bool RA_succeeded; +} NRRrcMacRaInd; + typedef struct RrcMacInSyncInd_s { uint32_t frame; uint8_t sub_frame; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 130b46143b..1c09ec574d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -896,7 +896,6 @@ void nr_ra_succeeded(const module_id_t mod_id, const uint8_t gNB_index, const fr if (ra->cfra) { LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mod_id, frame, slot); - nr_rrc_RA_succeeded(mod_id, gNB_index); mac->state = UE_CONNECTED; ra->RA_window_cnt = -1; } else { @@ -911,6 +910,7 @@ void nr_ra_succeeded(const module_id_t mod_id, const uint8_t gNB_index, const fr LOG_D(MAC, "In %s: [UE %d] clearing RA_active flag...\n", __FUNCTION__, mod_id); ra->RA_active = 0; ra->ra_state = RA_SUCCEEDED; + nr_mac_rrc_ra_ind(mod_id, frame, true); } // Handling failure of RA procedure @ MAC layer diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 7222defbe4..06fb26536e 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -155,12 +155,10 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } -int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) +void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) { - if (NR_UE_rrc_inst[mod_id].timers_and_constants.T304_active == true) { - LOG_W(NR_RRC, "T304 was stoped with value %i\n", NR_UE_rrc_inst[mod_id].timers_and_constants.T304_cnt); - NR_UE_rrc_inst[mod_id].timers_and_constants.T304_active = false; - NR_UE_rrc_inst[mod_id].timers_and_constants.T304_cnt = 0; - } - return 0; + MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_RA_IND); + NR_RRC_MAC_RA_IND (message_p).frame = frame; + NR_RRC_MAC_RA_IND (message_p).RA_succeeded = success; + itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 69efec94ce..87f7e50157 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2249,6 +2249,18 @@ int32_t nr_rrc_ue_establish_drb(module_id_t ue_mod_idP, return 0; } +void nr_rrc_handle_ra_indication(unsigned int mod_id, bool ra_succeeded) +{ + NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[mod_id].timers_and_constants; + if (ra_succeeded && timers->T304_active == true) { + // successful Random Access procedure triggered by reconfigurationWithSync + timers->T304_active = false; + timers->T304_cnt = 0; + // TODO handle the rest of procedures as described in 5.3.5.3 for when + // reconfigurationWithSync is included in spCellConfig + } +} + void *rrc_nrue_task(void *args_p) { MessageDef *msg_p; @@ -2293,6 +2305,15 @@ void *rrc_nrue_task(void *args_p) nr_rrc_handle_timers(timers); break; + case NR_RRC_MAC_RA_IND: + LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n RA %s", + ue_mod_id, + ITTI_MSG_NAME (msg_p), + NR_RRC_MAC_RA_IND (msg_p).frame, + NR_RRC_MAC_RA_IND (msg_p).RA_succeeded ? "successful" : "failed"); + nr_rrc_handle_ra_indication(ue_mod_id, NR_RRC_MAC_RA_IND (msg_p).RA_succeeded); + break; + case NR_RRC_MAC_BCCH_DATA_IND: LOG_D(NR_RRC, "[UE %d] Received %s: frameP %d, gNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index); diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index f303d809fe..67369a8488 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -116,6 +116,7 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync); +void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success); /**\brief \param module_id module id From a0a2248ea1f6c082b1eeb407b9b0aaf46ce3f0a2 Mon Sep 17 00:00:00 2001 From: Melissa Elkadi Date: Fri, 30 Jun 2023 18:53:29 +0200 Subject: [PATCH 041/119] Introduce #defines for Sidelink Synchronization Implement the #define variables required for synchronization: These variables include offset and payload size values that vary from the Uu interface, in relation to the PSS, SSS and PBCH elements. We also introduce the new sl_mode command line flag, which is used to switch between the Uu interface and SL interface. This will allow us to modify exisitng PSS and SSS functions, without copying complete 5G functions and only changing a few lines to support sidelink mode. Fixing formatting for softmodem-common.h --- executables/softmodem-common.h | 16 +++++- .../nrPolar_tools/nr_polar_decoding_tools.c | 14 ++++-- .../CODING/nrPolar_tools/nr_polar_pbch_defs.h | 3 ++ openair1/PHY/NR_REFSIG/ss_pbch_nr.h | 10 ++++ openair1/PHY/NR_REFSIG/sss_nr.h | 9 ++++ openair1/PHY/NR_UE_TRANSPORT/pss_nr.c | 18 ++++--- openair1/PHY/NR_UE_TRANSPORT/sss_nr.c | 50 ++++++++++--------- openair1/PHY/defs_nr_UE.h | 21 ++++++++ openair1/PHY/defs_nr_common.h | 4 ++ .../NR_UE_PHY/unit_tests/src/pss_test.c | 10 ++-- .../NR_UE_PHY/unit_tests/src/pss_util_test.c | 21 +++++--- .../NR_UE_PHY/unit_tests/src/sss_test.c | 4 +- 12 files changed, 130 insertions(+), 50 deletions(-) diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 1f37c9bdea..097546568f 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -58,7 +58,7 @@ extern "C" #define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n" #define CONFIG_HLP_DORA "test gNB and UE with RA procedures\n" #define CONFIG_HLP_SA "run gNB in standalone mode\n" -#define CONFIG_HLP_SL_MODE "sets the NR sidelink mode (0: not in sidelink mode, 1: in-coverage/gNB, 2: out-of-coverage/no gNB)" +#define CONFIG_HLP_SL_MODE "sets the NR sidelink mode (0: not in sidelink mode, 1: in-coverage/gNB, 2: out-of-coverage/no gNB)\n" #define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n" #define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0" #define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n" @@ -106,6 +106,9 @@ extern "C" #define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n" #define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n" #define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence" +#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n" +#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n" +#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n" /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters common to eNodeB and UE */ @@ -137,6 +140,10 @@ extern "C" #define NON_STOP softmodem_params.non_stop #define EMULATE_L1 softmodem_params.emulate_l1 #define CONTINUOUS_TX softmodem_params.continuous_tx +#define SYNC_REF softmodem_params.sync_ref +#define NID1 softmodem_params.nid1 +#define NID2 softmodem_params.nid2 + #define REORDER_THREAD_DISABLE softmodem_params.reorder_thread_disable #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat"; @@ -181,6 +188,8 @@ extern int usrp_tx_thread; {"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, .iptr=&EMULATE_L1, .defintval=0, TYPE_INT, 0}, \ {"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \ {"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \ + {"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \ + {"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \ } // clang-format on @@ -227,6 +236,8 @@ extern int usrp_tx_thread; { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ } // clang-format on @@ -335,6 +346,9 @@ typedef struct { int non_stop; int emulate_l1; int continuous_tx; + int sync_ref; + int nid1; + int nid2; } softmodem_params_t; extern uint64_t get_softmodem_optmask(void); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c index 20ecc690b3..7fd8d351ff 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c @@ -351,9 +351,17 @@ void applyGtoright(const t_nrPolar_params *pp,decoder_node_t *node) { ((__m64 *)alpha_r)[0] = _mm_subs_pi16(((__m64 *)alpha_v)[1],_mm_sign_pi16(((__m64 *)alpha_v)[0],((__m64 *)betal)[0])); } else - {// equivalent scalar code to above, activated only on non x86/ARM architectures or Nv=1,2 - for (int i=0;iNv/2;i++) { - alpha_r[i] = alpha_v[i+(node->Nv/2)] - (betal[i]*alpha_v[i]); + { + int temp_alpha_r; + for (int i = 0; i < node->Nv / 2; i++) { + temp_alpha_r = alpha_v[i + (node->Nv / 2)] - (betal[i] * alpha_v[i]); + if (temp_alpha_r > SHRT_MAX) { + alpha_r[i] = SHRT_MAX; + } else if (temp_alpha_r < -SHRT_MAX) { + alpha_r[i] = -SHRT_MAX; + } else { + alpha_r[i] = temp_alpha_r; + } } } if (node->Nv == 2) { // apply hard decision on right node diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h index 2ced9633ce..1904d1bd83 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h @@ -35,6 +35,7 @@ #define NR_POLAR_PBCH_AGGREGATION_LEVEL 0 //uint8_t #define NR_POLAR_PBCH_MESSAGE_TYPE 0 //int8_t +#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 //int8_t #define NR_POLAR_PBCH_PAYLOAD_BITS 32 //uint16_t #define NR_POLAR_PBCH_CRC_PARITY_BITS 24 #define NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS 3 @@ -52,6 +53,8 @@ #define NR_POLAR_PBCH_I_BIL 0 //uint8_t #define NR_POLAR_PBCH_E 864 //uint16_t #define NR_POLAR_PBCH_E_DWORD 27 // NR_POLAR_PBCH_E/32 +#define NR_POLAR_PSBCH_E 1792 //uint16_t +#define NR_POLAR_PSBCH_E_DWORD 56 // NR_POLAR_PSBCH_E/32 /* * TEST CODE diff --git a/openair1/PHY/NR_REFSIG/ss_pbch_nr.h b/openair1/PHY/NR_REFSIG/ss_pbch_nr.h index ad96054c12..0929d483cd 100644 --- a/openair1/PHY/NR_REFSIG/ss_pbch_nr.h +++ b/openair1/PHY/NR_REFSIG/ss_pbch_nr.h @@ -41,6 +41,9 @@ /* PSS parameters */ #define NUMBER_PSS_SEQUENCE (3) +#define NUMBER_PSS_SEQUENCE_SL (2) +#define PSS_SSS_SUB_CARRIER_START (56) +#define PSS_SSS_SUB_CARRIER_START_SL (2) #define INVALID_PSS_SEQUENCE (NUMBER_PSS_SEQUENCE) #define LENGTH_PSS_NR (127) #define N_SC_RB (12) /* Resource block size in frequency domain expressed as a number if subcarriers */ @@ -62,6 +65,13 @@ #define SSS_SYMBOL_NB ((2) + OFFSET_SS_PBCH) #define PBCH_LAST_SYMBOL_NB ((3) + OFFSET_SS_PBCH) + +#define OFFSET_SS_PSBCH -1 +#define PSS0_SL_SYMBOL_NB ((1) + OFFSET_SS_PSBCH) +#define PSS1_SL_SYMBOL_NB ((2) + OFFSET_SS_PSBCH) +#define SSS0_SL_SYMBOL_NB ((3) + OFFSET_SS_PSBCH) +#define SSS1_SL_SYMBOL_NB ((4) + OFFSET_SS_PSBCH) + /* SS/PBCH parameters */ #define N_RB_SS_PBCH_BLOCK (20) #define NB_SYMBOLS_PBCH (3) diff --git a/openair1/PHY/NR_REFSIG/sss_nr.h b/openair1/PHY/NR_REFSIG/sss_nr.h index 7303d99d3b..38d6e72819 100644 --- a/openair1/PHY/NR_REFSIG/sss_nr.h +++ b/openair1/PHY/NR_REFSIG/sss_nr.h @@ -47,13 +47,22 @@ #define SCALING_METRIC_SSS_NR (15)//(19) #define N_ID_2_NUMBER (NUMBER_PSS_SEQUENCE) +#define N_ID_2_NUMBER_SL (NUMBER_PSS_SEQUENCE_SL) #define N_ID_1_NUMBER (NUMBER_SSS_SEQUENCE) #define GET_NID2(Nid_cell) (Nid_cell%3) #define GET_NID1(Nid_cell) (Nid_cell/3) +#define GET_NID2_SL(Nid_SL) (Nid_SL/NUMBER_SSS_SEQUENCE) +#define GET_NID1_SL(Nid_SL) (Nid_SL%NUMBER_SSS_SEQUENCE) + #define PSS_SC_START_NR (52) /* see from TS 38.211 table 7.4.3.1-1: Resources within an SS/PBCH block for PSS... */ +#define SSS_START_IDX (3) /* [0:PSBCH 1:PSS0 2:PSS1 3:SSS0 4:SSS1] */ +#define NUM_SSS_SYMBOLS (2) + +#define SSS_METRIC_FLOOR_NR (30000) + /************** VARIABLES *****************************************/ #define PHASE_HYPOTHESIS_NUMBER (16) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 48486bbdee..7323d27dbb 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -73,7 +73,7 @@ int16_t *get_primary_synchro_nr2(const int nid2) * *********************************************************************/ -void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) +void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) { AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size); AssertFatal(N_ID_2>=0 && N_ID_2 <=2,"Illegal N_ID_2 %d\n",N_ID_2); @@ -88,9 +88,8 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) assert(N_ID_2 < NUMBER_PSS_SEQUENCE); memcpy(x, x_initial, sizeof(x_initial)); - for (int i=0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) { - x[i+INITIAL_PSS_NR] = (x[i + 4] + x[i])%(2); - } + for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) + x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2); for (int n=0; n < LENGTH_PSS_NR; n++) { const int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR); @@ -139,7 +138,8 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) * sample 0 is for continuous frequency which is used here */ - unsigned int k = fp->first_carrier_offset + fp->ssb_start_subcarrier + 56; //and + unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL; + unsigned int k = fp->first_carrier_offset + fp->ssb_start_subcarrier + subcarrier_start; if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size; c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32))); memset(synchroF_tmp, 0, sizeof(synchroF_tmp)); @@ -237,7 +237,8 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) static void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue) { AssertFatal(frame_parms_ue->ofdm_symbol_size > 127, "illegal ofdm_symbol_size %d\n", frame_parms_ue->ofdm_symbol_size); - for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) { + int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; + for (int i = 0; i < pss_sequence; i++) { primary_synchro_nr2[i] = malloc16_clear(LENGTH_PSS_NR * sizeof(int16_t)); AssertFatal(primary_synchro_nr2[i], "Fatal memory allocation problem \n"); primary_synchro_time_nr[i] = malloc16_clear(frame_parms_ue->ofdm_symbol_size * sizeof(c16_t)); @@ -583,7 +584,8 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i pss_source = 0; int maxval=0; - for (int j = 0; j < NUMBER_PSS_SEQUENCE; j++) + int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; + for (int j = 0; j < max_size; j++) for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { maxval = max(maxval, abs(primary_synchro_time_nr[j][i].r)); maxval = max(maxval, abs(primary_synchro_time_nr[j][i].i)); @@ -595,7 +597,7 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i /* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */ uint16_t pss_index_start = 0; - uint16_t pss_index_end = NUMBER_PSS_SEQUENCE; + uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; if (ue->target_Nid_cell != -1) { pss_index_start = GET_NID2(ue->target_Nid_cell); pss_index_end = pss_index_start + 1; diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 2f53a7b95d..cb8e4f40e9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -36,7 +36,7 @@ #include "PHY/defs_nr_UE.h" #include "PHY/MODULATION/modulation_UE.h" - +#include "executables/softmodem-common.h" #include "PHY/NR_REFSIG/ss_pbch_nr.h" #define DEFINE_VARIABLES_SSS_NR_H @@ -78,31 +78,25 @@ void init_context_sss_nr(int amp) int16_t x1[LENGTH_SSS_NR]; int16_t dss_current; int m0, m1; + int nid_2_num = get_softmodem_params()->sl_mode == 0 ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL; const int x0_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 }; const int x1_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 }; - - for (int i=0; i < INITIAL_SSS_NR; i++) { + for (int i = 0; i < INITIAL_SSS_NR; i++) { x0[i] = x0_initial[i]; x1[i] = x1_initial[i]; } - - for (int i=0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) { - x0[i+7] = (x0[i + 4] + x0[i])%(2); - x1[i+7] = (x1[i + 1] + x1[i])%(2); + for (int i = 0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) { + x0[i + 7] = (x0[i + 4] + x0[i]) % (2); + x1[i + 7] = (x1[i + 1] + x1[i]) % (2); } - for (int N_ID_2 = 0; N_ID_2 < N_ID_2_NUMBER; N_ID_2++) { - + for (int N_ID_2 = 0; N_ID_2 < nid_2_num; N_ID_2++) { for (int N_ID_1 = 0; N_ID_1 < N_ID_1_NUMBER; N_ID_1++) { - - m0 = 15*(N_ID_1/112) + (5*N_ID_2); - m1 = N_ID_1%112; - + m0 = 15 * (N_ID_1 / 112) + (5 * N_ID_2); + m1 = N_ID_1 % 112; for (int n = 0; n < LENGTH_SSS_NR; n++) { - - dss_current = (1 - 2*x0[(n + m0)%(LENGTH_SSS_NR)])*(1 - 2*x1[(n + m1)%(LENGTH_SSS_NR)]); - + dss_current = (1 - 2 * x0 [(n + m0) % (LENGTH_SSS_NR)]) * (1 - 2 * x1[(n + m1) % (LENGTH_SSS_NR)]); /* Modulation of SSS is a BPSK TS 36.211 chapter 5.1.2 BPSK */ #if 1 d_sss[N_ID_2][N_ID_1][n] = dss_current;// * amp; @@ -276,8 +270,9 @@ static int do_pss_sss_extract_nr( for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { int pss_symbol = 0; - int sss_symbol = SSS_SYMBOL_NB - PSS_SYMBOL_NB; - + int sss_symbol = get_softmodem_params()->sl_mode == 0 ? + (SSS_SYMBOL_NB - PSS_SYMBOL_NB) : + (SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ; unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size; c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size; @@ -286,12 +281,16 @@ static int do_pss_sss_extract_nr( c16_t *pss_rxF_ext = pss_ext[aarx]; c16_t *sss_rxF_ext = sss_ext[aarx]; - unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; + unsigned int k = frame_parms->first_carrier_offset + + frame_parms->ssb_start_subcarrier + + ((get_softmodem_params()->sl_mode == 0) ? + PSS_SSS_SUB_CARRIER_START : + PSS_SSS_SUB_CARRIER_START_SL); if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; for (int i=0; i < LENGTH_PSS_NR; i++) { - if (doPss) { + if (doPss) { pss_rxF_ext[i] = pss_rxF[k]; } @@ -300,9 +299,7 @@ static int do_pss_sss_extract_nr( } k++; - - if (k == ofdm_symbol_size) k=0; - + if (k == frame_parms->ofdm_symbol_size) k = 0; } } @@ -365,7 +362,12 @@ static int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue, * *********************************************************************/ -int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +int rx_sss_nr(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int32_t *tot_metric, + uint8_t *phase_max, + int *freq_offset_sss, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { uint8_t i; c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR]; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 870f093c74..d4c5a2da49 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -318,6 +318,22 @@ typedef struct { fapi_nr_dl_config_dci_dl_pdu_rel15_t pdcch_config[FAPI_NR_MAX_SS]; } NR_UE_PDCCH_CONFIG; +#define NR_PSBCH_MAX_NB_CARRIERS 132 +#define NR_PSBCH_MAX_NB_MOD_SYMBOLS 99 +#define NR_PSBCH_DMRS_LENGTH 297 // in mod symbols +#define NR_PSBCH_DMRS_LENGTH_DWORD 20 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32) + +/* NR Sidelink PSBCH payload fields + TODO: This will be removed in the future and + filled in by the upper layers once developed. */ +typedef struct { + uint32_t coverageIndicator : 1; + uint32_t tddConfig : 12; + uint32_t DFN : 10; + uint32_t slotIndex : 7; + uint32_t reserved : 2; +} PSBCH_payload; + #define PBCH_A 24 typedef struct { @@ -378,8 +394,12 @@ typedef struct { int if_freq_off; /// \brief Indicator that UE is synchronized to a gNB int is_synchronized; + /// \brief Indicator that UE is synchronized to a SyncRef UE on Sidelink + int is_synchronized_sl; /// \brief Target gNB Nid_cell when UE is resynchronizing int target_Nid_cell; + /// \brief Indicator that UE is an SynchRef UE + int sync_ref; /// Data structure for UE process scheduling UE_nr_proc_t proc; /// Flag to indicate the UE shouldn't do timing correction at all @@ -660,6 +680,7 @@ typedef struct nr_rxtx_thread_data_s { UE_nr_rxtx_proc_t proc; PHY_VARS_NR_UE *UE; int writeBlockSize; + notifiedFIFO_t txFifo; nr_phy_data_t phy_data; int tx_wait_for_dlsch; } nr_rxtx_thread_data_t; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index e8dba45f2b..2b0a07fda7 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -169,6 +169,8 @@ struct NR_DL_FRAME_PARMS { /// Frame type (0 FDD, 1 TDD) frame_type_t frame_type; uint8_t tdd_config; + /// Sidelink Cell ID + uint16_t Nid_SL; /// Cell ID uint16_t Nid_cell; /// subcarrier spacing (15,30,60,120) @@ -260,6 +262,8 @@ struct NR_DL_FRAME_PARMS { uint8_t ssb_index; /// OFDM symbol offset divisor for UL uint32_t ofdm_offset_divisor; + uint16_t tdd_slot_config; + uint8_t tdd_period; }; // PRS config structures diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_test.c index de1249457f..c9e76846e9 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_test.c @@ -119,14 +119,15 @@ void test_synchro_pss_nr(PHY_VARS_NR_UE *PHY_VARS_NR_UE, int position_symbol, in /* search pss */ synchro_position = pss_synchro_nr(PHY_VARS_NR_UE, rate_change); + int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; - if (pss_sequence_number < NUMBER_PSS_SEQUENCE) { + if (pss_sequence_number < pss_sequence) { NID2_value = pss_sequence_number; } else { - NID2_value = NUMBER_PSS_SEQUENCE; + NID2_value = pss_sequence; } - if (NID2_value < NUMBER_PSS_SEQUENCE) { + if (NID2_value < pss_sequence) { test->number_of_tests++; /* position should be adjusted with i&q samples which are successively stored as int16 in the received buffer */ int test_margin = PSS_DETECTION_MARGIN_MAX; /* warning correlation results give an offset position between 0 and 12 */ @@ -213,9 +214,10 @@ int main(int argc, char *argv[]) test_synchro_pss_nr(PHY_vars_UE, 0, INVALID_PSS_SEQUENCE, &test); #endif + int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; for (int index_position = 0; index_position < size_test_position; index_position++) { - for (int number_pss_sequence = 0; number_pss_sequence < NUMBER_PSS_SEQUENCE; number_pss_sequence++) { + for (int number_pss_sequence = 0; number_pss_sequence < pss_sequence; number_pss_sequence++) { p_test_synchro_pss(PHY_vars_UE, test_position[index_position], number_pss_sequence, &test); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c index 9c96d39534..815c12a6a6 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c @@ -111,12 +111,15 @@ void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, i void display_data(int pss_sequence_number, int16_t *rxdata, int position) { #ifdef DEBUG_TEST_PSS - int16_t *pss_sequence[NUMBER_PSS_SEQUENCE] = {primary_synch0_time, primary_synch1_time, primary_synch2_time}; - int16_t *pss_sequence_time = pss_sequence[pss_sequence_number]; + int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; + int16_t *pss_sequence[pss_sequence] = {primary_synch0_time, primary_synch1_time, primary_synch2_time}; + int16_t *pss_sequence_sl[pss_sequence] = {primary_synch0_time, primary_synch1_time}; + int16_t *pss_sequence_time = pss_sequence[pss_sequence_number];; + if (get_softmodem_params()->sl_mode != 0) { + pss_sequence_time = pss_sequence_sl[pss_sequence_number]; printf(" pss %6d data \n", pss_sequence_number); - for (int i = 0; i < 4; i++) { - if (pss_sequence_number < NUMBER_PSS_SEQUENCE) { + if (pss_sequence_number < pss_sequence) { printf("[i %6d] : %4d [i %6d] : %8i at address : %p \n", i, pss_sequence_time[2*i], (i + position), rxdata[2*i + (position*2)], &(rxdata[2*i + (position*2)])); printf("[q %6d] : %4d [q %6d] : %8i at address : %p \n", i, pss_sequence_time[2*i+1], (i + position), rxdata[2*i + 1 + (position*2)], &(rxdata[2*i + 1 + (position*2)])); } else { @@ -242,7 +245,8 @@ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission int n_ssb_crb = 0; int ssb_subcarrier_offset = 0; nr_init_frame_parms_ue(frame_parms, mu, extended_prefix_flag, N_RB_DL, n_ssb_crb, ssb_subcarrier_offset); - PHY_vars_UE->frame_parms.Nid_cell = (3 * N_ID_1_NUMBER) + N_ID_2_NUMBER; /* set to unvalid value */ + int nid_2_num = get_softmodem_params()->sl_mode == 0 ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL; + PHY_vars_UE->frame_parms.Nid_cell = (3 * N_ID_1_NUMBER) + nid_2_num; /* set to unvalid value */ //phy_init_nr_top(frame_parms); @@ -447,8 +451,8 @@ int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int p printf("This pss sequence can not be fully written in the received window \n"); return (-1); } - - if ((pss_sequence_number >= NUMBER_PSS_SEQUENCE) && (pss_sequence_number < 0)) { + int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; + if ((pss_sequence_number >= pss_sequence) && (pss_sequence_number < 0)) { printf("Unknow pss sequence %d \n", pss_sequence_number); return (-1); } @@ -504,8 +508,9 @@ void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_ if (position_symbol < 0) { set_pss_in_rx_buffer_from_external_buffer(PHY_vars_UE, input_buffer); } + int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; /* write pss sequence in received ue buffer */ - else if (pss_sequence_number < NUMBER_PSS_SEQUENCE) { + else if (pss_sequence_number < pss_sequence) { if (position_symbol > (samples_for_frame - frame_parms->ofdm_symbol_size)) { printf("This position for pss sequence %d is not supported because it exceeds the frame length %d!\n", position_symbol, samples_for_frame); exit(0); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c index 6f6594861a..fa2a8cffd1 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c @@ -227,10 +227,10 @@ int main(int argc, char *argv[]) Nid2 = GET_NID2(Nid_cell[index]); Nid1 = GET_NID1(Nid_cell[index]); - + int nid_2_num = get_softmodem_params()->sl_mode == 0 ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL; for (int position = 0; position < size_test_position; position++) { - PHY_vars_UE->frame_parms.Nid_cell = (3 * N_ID_1_NUMBER) + N_ID_2_NUMBER; /* set to invalid value */ + PHY_vars_UE->frame_parms.Nid_cell = (3 * N_ID_1_NUMBER) + nid_2_num; /* set to invalid value */ phase = (*p_test_synchro_pss_sss)(PHY_vars_UE, test_position[position], &frame_parms_gNB, &test); /* return phase index which gives phase error from an array */ From 9ea0ef666e41d6d658de6fde794b139e006674f5 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Sat, 1 Jul 2023 10:05:07 +0100 Subject: [PATCH 042/119] Add support for NR band n48 --- openair2/GNB_APP/gnb_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index f5ce7121cc..3d1a766b44 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -115,6 +115,7 @@ const sync_raster_t sync_raster[] = { {40, 0, 5756, 1, 5995}, {41, 0, 6246, 3, 6717}, {41, 1, 6252, 3, 6714}, + {48, 1, 7884, 1, 7982}, {50, 0, 3584, 1, 3787}, {51, 0, 3572, 1, 3574}, {66, 0, 5279, 1, 5494}, From 57a3f9fe2f56b97d471217a010f06f5b9dc83dc6 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 3 Jul 2023 07:48:03 +0100 Subject: [PATCH 043/119] Bugfix when deleting a SDAP entity that is not the first one on the list and prevents segfault when removing the last one on the list Fix delete entity function, a SDAP entity is a combination of a UE and PDUSession, we cannot just simply delete the first entity for a UE --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index e81490630c..a0c8f10ada 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -468,23 +468,21 @@ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id) return NULL; } -void delete_nr_sdap_entity(ue_id_t ue_id) +int nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) { - nr_sdap_entity_t *entityPtr, *entityPrev = NULL; - entityPtr = sdap_info.sdap_entity_llist; - - if (entityPtr->ue_id == ue_id) { - sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; - free(entityPtr); - } else { - while (entityPtr->ue_id != ue_id && entityPtr->next_entity != NULL) { - entityPrev = entityPtr; - entityPtr = entityPtr->next_entity; - } - - if (entityPtr->ue_id != ue_id) { - entityPrev->next_entity = entityPtr->next_entity; + nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; + int pos = 0; + while (entityPtr != NULL) { + if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { + if (pos == 0) { + sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + } + LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); free(entityPtr); + return 1; } + entityPtr = entityPtr->next_entity; + pos++; } + return 0; } From 62d33ce523a7a1ae837078d4a3ef648fc68b5199 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 3 Jul 2023 09:40:34 +0100 Subject: [PATCH 044/119] Add function to remove all SDAP entities for a UE --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index a0c8f10ada..bc3ea0ad9d 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -486,3 +486,23 @@ int nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) } return 0; } + +void nr_sdap_delete_ue_entities(ue_id_t ue_id) +{ + nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; + int pos = 0; + while (entityPtr != NULL) { + if (entityPtr->ue_id == ue_id) { + if (pos == 0) { + sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + } + LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); + nr_sdap_entity_t *entityPrev = entityPtr; + free(entityPtr); + entityPtr = entityPrev->next_entity; + } else { + entityPtr = entityPtr->next_entity; + } + pos++; + } +} From 2500138feafaebdcd5cfc11c792cb98405a1a942 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 7 Jun 2023 18:35:01 +0200 Subject: [PATCH 045/119] Fixup: copying via cls_cmd only supports absolute paths --- ci-scripts/cls_cmd.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_cmd.py b/ci-scripts/cls_cmd.py index 1e4c12e854..30f00cdb02 100644 --- a/ci-scripts/cls_cmd.py +++ b/ci-scripts/cls_cmd.py @@ -118,11 +118,14 @@ class LocalCmd(Cmd): def getBefore(self): return self.cp.stdout - def copyin(self, scpIp, scpUser, scpPw, src, tgt): - self.run(f'cp -r {src} {tgt}') + def copyin(self, src, tgt, recursive=False): + if src[0] != '/' or tgt[0] != '/': + raise Exception('support only absolute file paths!') + opt = '-r' if recursive else '' + self.run(f'cp {opt} {src} {tgt}') - def copyout(self, scpIp, scpUser, scpPw, src, tgt): - self.run(f'cp -r {src} {tgt}') + def copyout(self, src, tgt, recursive=False): + self.copyin(src, tgt, recursive) class RemoteCmd(Cmd): def __init__(self, hostname, d=None): From 9f55d7121cbc42c3783da68402eaf4867808fa92 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 7 Jun 2023 18:41:27 +0200 Subject: [PATCH 046/119] Refactor Ping to use %cn_ip% for address to ping, or hardcoded --- ci-scripts/cls_oaicitest.py | 43 +++++++++---------- .../container_lte_b200_fdd_05Mhz_tm1.xml | 2 +- ...lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml | 4 +- .../container_lte_b200_fdd_10Mhz_tm1.xml | 2 +- .../container_lte_b200_fdd_10Mhz_tm1_cdrx.xml | 2 +- .../container_lte_b200_fdd_20Mhz_tm1.xml | 2 +- .../container_lte_b200_tdd_05Mhz_tm1.xml | 2 +- .../container_lte_b200_tdd_05Mhz_tm2.xml | 2 +- .../container_lte_b200_tdd_10Mhz_tm1.xml | 2 +- .../container_lte_b200_tdd_20Mhz_tm1.xml | 2 +- ...e_b200_tdd_20Mhz_tm1_default_scheduler.xml | 2 +- .../container_lte_n3xx_tdd_2x2_tm1.xml | 4 +- .../container_lte_n3xx_tdd_2x2_tm2.xml | 4 +- .../xml_files/container_nsa_b200_quectel.xml | 8 ++-- .../xml_files/container_sa_aw2s_asue.xml | 4 +- .../xml_files/container_sa_b200_quectel.xml | 4 +- .../container_sa_f1_b200_quectel.xml | 8 ++-- ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 4 +- .../fr1_nsa_2x2_quectel_attach_detach.xml | 2 +- ci-scripts/xml_files/fr1_nsa_quectel.xml | 4 +- .../fr1_nsa_quectel_attach_detach.xml | 4 +- ci-scripts/xml_files/fr1_nsa_quectel_long.xml | 4 +- ci-scripts/xml_files/fr1_sa_oaiue_b200.xml | 4 +- ci-scripts/xml_files/fr1_sa_oaiue_n310.xml | 4 +- ci-scripts/xml_files/fr1_sa_oaiue_x300.xml | 4 +- ci-scripts/xml_files/fr1_sa_quectel.xml | 4 +- .../xml_files/fr1_sa_quectel_162prb.xml | 2 +- .../xml_files/fr1_sa_quectel_stages.xml | 2 +- 28 files changed, 66 insertions(+), 69 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index ed04b34aef..97eaed8ba5 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -511,37 +511,34 @@ class OaiCiTest(): return (False, f"UE {ue.getName()} has no IP address") ping_log_file = f'ping_{self.testCase_id}_{ue.getName()}.log' ping_time = re.findall("-c *(\d+)",str(self.ping_args)) - #target address is different depending on EPC type - if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): - Target = EPC.MmeIPAddress - elif re.match('OAICN5G', EPC.Type, re.IGNORECASE): - Target = EPC.MmeIPAddress - elif re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE): - Target = "172.21.6.100" - else: - Target = EPC.IPAddress + local_ping_log_file = f'{os.getcwd()}/{ping_log_file}' + # if has pattern %cn_ip%, replace with core IP address, else we assume the IP is present + if re.search('%cn_ip%', self.ping_args): + #target address is different depending on EPC type + if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): + self.ping_args = re.sub('%cn_ip%', EPC.MmeIPAddress, self.ping_args) + elif re.match('OAICN5G', EPC.Type, re.IGNORECASE): + self.ping_args = re.sub('%cn_ip%', EPC.MmeIPAddress, self.ping_args) + elif re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE): + self.ping_args = re.sub('%cn_ip%', '172.21.6.100', self.ping_args) + else: + self.ping_args = re.sub('%cn_ip%', EPC.IPAddress, self.ping_args) #ping from module NIC rather than IP address to make sure round trip is over the air interface = f'-I {ue.getIFName()}' if ue.getIFName() else '' - ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} {Target} &> /tmp/{ping_log_file}' + ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} 2>&1 | tee /tmp/{ping_log_file}' cmd = cls_cmd.getConnection(ue.getHost()) response = cmd.run(ping_cmd, timeout=int(ping_time[0])*1.5) if response.returncode != 0: - ping_status = -1 - else: - #copy the ping log file to have it locally for analysis (ping stats) - cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=ping_log_file) - - cmd.close() - - # TIMEOUT CASE - ue_header = f'UE {ue.getName()} ({ueIP})' - if ping_status < 0: message = ue_header + ': ping crashed: TIMEOUT?' logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m') return (False, message) - #search is done on cat result - logging.debug('Analyzing Ping log file : ' + os.getcwd() + '/' + ping_log_file) - with open(ping_log_file, 'r') as f: + + #copy the ping log file to have it locally for analysis (ping stats) + cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=local_ping_log_file) + cmd.close() + + ue_header = f'UE {ue.getName()} ({ueIP})' + with open(local_ping_log_file, 'r') as f: ping_output = "".join(f.readlines()) result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', ping_output) if result is None: diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml index 0023edd171..7d43346bd6 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml @@ -110,7 +110,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml index bf8cb5e256..34bee784a4 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml @@ -148,7 +148,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 @@ -156,7 +156,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml index ea89f4193a..040211347b 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml @@ -104,7 +104,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Ping ping (10MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml index 788a1759dc..dc6df2da57 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml @@ -97,7 +97,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Ping ping (10MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml index 4fef927a3b..8015a54f43 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml @@ -103,7 +103,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Ping ping (20MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml index eb11412ef5..1aaa731b93 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml @@ -111,7 +111,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml index 887b5dab9b..c3a0b2ef89 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml @@ -101,7 +101,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm2.xml Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml index 3874ff7028..e82564338f 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml @@ -101,7 +101,7 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml Ping ping (10MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml index 77e00d72ac..3e558f0ac3 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml @@ -101,7 +101,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml Ping ping (20MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml index fd454f13e2..645de59565 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml @@ -103,7 +103,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml Ping ping (20MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml index 480825bede..49cd79783a 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml @@ -102,7 +102,7 @@ Ping Ping: 20 pings nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 1 60 @@ -111,7 +111,7 @@ Ping Ping: 100 pings, size 1024 nrmodule2_quectel - -c 100 -s 1024 -i 0,2 + -c 100 -s 1024 -i 0,2 %cn_ip% 1 60 diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml index b3dc7efab7..a9ed0b2bea 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml @@ -102,7 +102,7 @@ Ping Ping: 20 pings nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 1 60 @@ -111,7 +111,7 @@ Ping Ping: 100 pings, size 1024 nrmodule2_quectel - -c 100 -s 1024 -i 0,2 + -c 100 -s 1024 -i 0,2 %cn_ip% 1 60 diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index ee264b6c43..6a2f31aac2 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -151,7 +151,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -160,7 +160,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 @@ -169,7 +169,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -178,7 +178,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 7959718eb0..8241d2da83 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -123,7 +123,7 @@ Ping Ping: 20pings in 20sec, multi-ue amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 - -c 20 + -c 20 %cn_ip% 1 25 @@ -132,7 +132,7 @@ Ping Ping: 100pings in 20sec, multi-ue amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 30 diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index 97b77e2499..9d36b76084 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -113,7 +113,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -122,7 +122,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 diff --git a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml index 3fab62b265..a00a575a81 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -119,7 +119,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 25 @@ -128,7 +128,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 110 @@ -137,7 +137,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 110 @@ -146,7 +146,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 110 diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 185d637218..78787d34fa 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -144,7 +144,7 @@ Ping Ping: 20pings in 20sec nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 5 @@ -152,7 +152,7 @@ Ping Ping: 100pings in 20sec nrmodule2_quectel - -c 100 -i 0,2 + -c 100 -i 0,2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index d1515898ff..37a80058d3 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -144,7 +144,7 @@ Ping Ping: 20pings in 20sec nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel.xml b/ci-scripts/xml_files/fr1_nsa_quectel.xml index 962b3eef7e..e300bd7f1c 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel.xml @@ -141,7 +141,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -150,7 +150,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml index 593e2d326d..732dd3bb7d 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml @@ -109,7 +109,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 50 @@ -117,7 +117,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 50 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel_long.xml b/ci-scripts/xml_files/fr1_nsa_quectel_long.xml index 89825cdbf2..a37cbb4d72 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel_long.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel_long.xml @@ -106,7 +106,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 50 @@ -114,7 +114,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 50 diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml b/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml index 454cd1486b..97a6404c55 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml @@ -79,7 +79,7 @@ Ping Ping from CN to UE: 20pings in 20sec - -c 20 + -c 20 %cn_ip% 5 @@ -87,7 +87,7 @@ Ping Ping from CN to UE: 100pings in 20sec oai_ue_obelix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml index 7105828be4..00c3431aa0 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -95,7 +95,7 @@ Ping Ping from CN to UE: 20pings in 20sec oai_ue_obelix - -c 20 + -c 20 %cn_ip% 5 @@ -103,7 +103,7 @@ Ping Ping from CN to UE: 100pings in 20sec oai_ue_obelix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml b/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml index fcc6088096..315674c9e6 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml @@ -80,7 +80,7 @@ Ping Ping from CN to UE: 20pings in 20sec oai_ue_obelix - -c 20 + -c 20 %cn_ip% 5 @@ -88,7 +88,7 @@ Ping Ping from CN to UE: 100pings in 20sec oai_ue_obelix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index b13de6f3ef..5fd276e6ce 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -114,7 +114,7 @@ Ping Ping: 40pings in 40sec nrmodule2_quectel - -c 40 + -c 40 %cn_ip% 1 10 @@ -123,7 +123,7 @@ Ping Ping: 100pings in 20sec nrmodule2_quectel - -c 100 -i 0,2 + -c 100 -i 0,2 %cn_ip% 1 10 diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index d1c250862d..507e9b1b92 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -111,7 +111,7 @@ Ping Ping: 40pings in 40sec nrmodule2_quectel - -c 40 + -c 40 %cn_ip% 1 20 diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 94cf5d71ef..006526e177 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -119,7 +119,7 @@ Ping Ping: 40pings in 40sec nrmodule2_quectel - -c 40 + -c 40 %cn_ip% 1 20 From 2880be7282fa792cbefb00e54eef4ecad2774a7c Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Tue, 13 Jun 2023 11:52:36 +0200 Subject: [PATCH 047/119] Rename UENetworkScript to NetworkScript in ci_ueinfra --- ci-scripts/ci_ueinfra.yaml | 30 +++++++++++++++--------------- ci-scripts/cls_module_ue.py | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 8a6c76645a..bd2442cf16 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -4,7 +4,7 @@ idefix: TermScript: sudo -S killall --signal SIGKILL quectel-CM AttachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 wup DetachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 detach - UENetworkScript: ip a show dev wwan0 + NetworkScript: ip a show dev wwan0 IF: wwan0 MTU: 1500 Trace: True @@ -15,7 +15,7 @@ nrmodule2_quectel: TermScript: sudo -S killall --signal SIGKILL quectel-CM AttachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 wup DetachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 detach - UENetworkScript: ip a show dev wwan0 + NetworkScript: ip a show dev wwan0 IF: wwan0 MTU: 1500 LogStore: /media/ci_qlogs @@ -29,7 +29,7 @@ adb_ue_1: CheckStatusScript: /home/oaicicd/ci_ctl_adb.sh check R3CM40LZPHT DataEnableScript: adb -s R3CM40LZPHT shell "svc data enable" DataDisableScript: adb -s R3CM40LZPHT shell "svc data disable" - UENetworkScript: adb -s R3CM40LZPHT shell "ip address show | grep rmnet_data0" + NetworkScript: adb -s R3CM40LZPHT shell "ip address show | grep rmnet_data0" CmdPrefix: adb -s R3CM40LZPHT shell MTU: 1500 LogStore: /media/usb-drive/ci_adb_1-logs @@ -42,7 +42,7 @@ adb_ue_2: CheckStatusScript: /home/oaicicd/ci_ctl_adb.sh check 5200c00db4413517 DataEnableScript: adb -s 5200c00db4413517 shell "svc data enable" DataDisableScript: adb -s 5200c00db4413517 shell "svc data disable" - UENetworkScript: adb -s 5200c00db4413517 shell "ip address show | grep rmnet" + NetworkScript: adb -s 5200c00db4413517 shell "ip address show | grep rmnet" CmdPrefix: adb -s 5200c00db4413517 shell MTU: 1500 LogStore: /media/usb-drive/ci_adb_2-logs @@ -55,74 +55,74 @@ amarisoft_ue_1: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":1}' - UENetworkScript: ip netns exec ue1 ip a show dev pdn0 + NetworkScript: ip netns exec ue1 ip a show dev pdn0 CmdPrefix: ip netns exec ue1 MTU: 1500 amarisoft_ue_2: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":2}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":2}' - UENetworkScript: ip netns exec ue2 ip a show dev pdn0 + NetworkScript: ip netns exec ue2 ip a show dev pdn0 CmdPrefix: ip netns exec ue2 MTU: 1500 amarisoft_ue_3: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":3}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":3}' - UENetworkScript: ip netns exec ue3 ip a show dev pdn0 + NetworkScript: ip netns exec ue3 ip a show dev pdn0 CmdPrefix: ip netns exec ue3 MTU: 1500 amarisoft_ue_4: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":4}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":4}' - UENetworkScript: ip netns exec ue4 ip a show dev pdn0 + NetworkScript: ip netns exec ue4 ip a show dev pdn0 CmdPrefix: ip netns exec ue4 MTU: 1500 amarisoft_ue_5: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":5}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":5}' - UENetworkScript: ip netns exec ue5 ip a show dev pdn0 + NetworkScript: ip netns exec ue5 ip a show dev pdn0 CmdPrefix: ip netns exec ue5 MTU: 1500 amarisoft_ue_6: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":6}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":6}' - UENetworkScript: ip netns exec ue6 ip a show dev pdn0 + NetworkScript: ip netns exec ue6 ip a show dev pdn0 CmdPrefix: ip netns exec ue6 MTU: 1500 amarisoft_ue_7: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":7}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":7}' - UENetworkScript: ip netns exec ue7 ip a show dev pdn0 + NetworkScript: ip netns exec ue7 ip a show dev pdn0 CmdPrefix: ip netns exec ue7 MTU: 1500 amarisoft_ue_8: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":8}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":8}' - UENetworkScript: ip netns exec ue8 ip a show dev pdn0 + NetworkScript: ip netns exec ue8 ip a show dev pdn0 CmdPrefix: ip netns exec ue8 MTU: 1500 amarisoft_ue_9: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":9}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":9}' - UENetworkScript: ip netns exec ue9 ip a show dev pdn0 + NetworkScript: ip netns exec ue9 ip a show dev pdn0 CmdPrefix: ip netns exec ue9 MTU: 1500 amarisoft_ue_10: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":10}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":10}' - UENetworkScript: ip netns exec ue10 ip a show dev pdn0 + NetworkScript: ip netns exec ue10 ip a show dev pdn0 CmdPrefix: ip netns exec ue10 MTU: 1500 oai_ue_obelix: Host: obelix - UENetworkScript: ip a show dev oaitun_ue1 + NetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 diff --git a/ci-scripts/cls_module_ue.py b/ci-scripts/cls_module_ue.py index 26a2d1c242..19dac1044d 100644 --- a/ci-scripts/cls_module_ue.py +++ b/ci-scripts/cls_module_ue.py @@ -54,7 +54,7 @@ class Module_UE: "detach": m.get('DetachScript'), "initialize": m.get('InitScript'), "terminate": m.get('TermScript'), - "getNetwork": m.get('UENetworkScript'), + "getNetwork": m.get('NetworkScript'), "check": m.get('CheckStatusScript'), "dataEnable": m.get('DataEnableScript'), "dataDisable": m.get('DataDisableScript'), From aac010ea18e6d2247572cadd5c4b32868f6ea7f4 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Tue, 13 Jun 2023 11:56:56 +0200 Subject: [PATCH 048/119] Add 5grfsim, 4grfsim, l2sim5g, l2sim4g interface details in ci_ueinfra --- ci-scripts/ci_ueinfra.yaml | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index bd2442cf16..2aa3952fcb 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -126,3 +126,59 @@ oai_ue_obelix: Host: obelix NetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 + +rfsim5g_gnb_nos1: + Host: localhost + NetworkScript: docker exec rfsim5g-oai-gnb ip a show dev oaitun_enb1 + CmdPrefix: docker exec rfsim5g-oai-gnb + IF: oaitun_enb1 + +rfsim5g_ue: + Host: localhost + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue1 + +rfsim5g_ext_dn: + Host: localhost + NetworkScript: docker exec rfsim5g-oai-ext-dn ip a show dev eth0 + CmdPrefix: docker exec rfsim5g-oai-ext-dn + +rfsim4g_ue: + Host: localhost + NetworkScript: docker exec rfsim4g-oai-lte-ue0 ip a show dev oaitun_ue1 + CmdPrefix: docker exec rfsim4g-oai-lte-ue0 + IF: oaitun_ue1 + +rfsim4g_ext_dn: + Host: localhost + NetworkScript: docker exec rfsim4g-trf-gen ip a show dev eth0 + CmdPrefix: docker exec rfsim4g-trf-gen + +rfsim4g_enb_nos1: + Host: localhost + NetworkScript: docker exec rfsim4g-oai-enb ip a show dev oaitun_enb1 + CmdPrefix: docker exec rfsim4g-oai-enb + IF: oaitun_enb1 + +l2sim5g_ue: + Host: localhost + NetworkScript: docker exec l2sim-oai-nr-ue0 ip a show dev oaitun_ue1 + CmdPrefix: docker exec l2sim-oai-nr-ue0 + IF: oaitun_ue1 + +l2sim5g_ext_dn: + Host: localhost + NetworkScript: docker exec l2sim-oai-ext-dn ip a show dev eth0 + CmdPrefix: docker exec l2sim-oai-ext-dn + +l2sim4g_ue: + Host: localhost + NetworkScript: docker exec l2sim4g-oai-lte-ue1 ip a show dev oaitun_ue1 + CmdPrefix: docker exec l2sim4g-oai-lte-ue1 + IF: oaitun_ue1 + +l2sim4g_ext_dn: + Host: localhost + NetworkScript: docker exec l2sim4g-trf-gen ip a show dev eth0 + CmdPrefix: docker exec l2sim4g-trf-gen From 54d2b887b8f2f84cc69d84b8bec65649c1b4c4d9 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 3 Jul 2023 14:41:21 +0200 Subject: [PATCH 049/119] Use Ping instead of PingFromContainer in simulator tests Affected tests: - 5G RFsim TDD do-ra - 5g-rfsim-fdd - 5g-rfsim - 5grfsim-e1 - 5grfsim-24prb - 5grfsim-fr2-32prb - 5grfsim-fdd-phytest - 5grfsim-u0-25prb - 5grfsim-2x2 - 5grfsim-f1 - 5grfsim-f1-accelleran - 4g-l2sim-tdd - 4g-rfsim-fdd-05mhz - 4g-rfsim-fdd-05mhz-nos1 - 4g-rfsim-fdd-10mhz - 4g-rfsim-fdd-20mhz - 4g-rfsim-tdd-05mhz - 5g-l2sim --- .../xml_files/container_4g_l2sim_tdd.xml | 16 +++++----- .../container_4g_rfsim_fdd_05MHz.xml | 16 +++++----- .../container_4g_rfsim_fdd_05MHz_noS1.xml | 16 +++++----- .../container_4g_rfsim_fdd_10MHz.xml | 16 +++++----- .../container_4g_rfsim_fdd_20MHz.xml | 16 +++++----- .../container_4g_rfsim_tdd_05MHz.xml | 16 +++++----- .../xml_files/container_5g_e1_rfsim.xml | 16 +++++----- .../xml_files/container_5g_f1_rfsim.xml | 16 +++++----- .../xml_files/container_5g_fdd_rfsim.xml | 16 +++++----- .../xml_files/container_5g_l2sim_tdd.xml | 16 +++++----- ci-scripts/xml_files/container_5g_rfsim.xml | 32 +++++++++---------- .../xml_files/container_5g_rfsim_24prb.xml | 16 +++++----- .../xml_files/container_5g_rfsim_2x2.xml | 16 +++++----- .../container_5g_rfsim_f1_accelleran.xml | 8 ++--- .../container_5g_rfsim_fdd_phytest.xml | 16 +++++----- .../container_5g_rfsim_fr2_32prb.xml | 16 +++++----- .../xml_files/container_5g_rfsim_tdd_dora.xml | 16 +++++----- .../xml_files/container_5g_rfsim_u0_25prb.xml | 16 +++++----- 18 files changed, 148 insertions(+), 148 deletions(-) diff --git a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml index 419ede8cbb..22f4a8be3a 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml @@ -89,19 +89,19 @@ - PingFromContainer + Ping Ping trf-gen from LTE-UE 1 - l2sim4g-oai-lte-ue1 - -I oaitun_ue1 -c 20 192.168.61.11 - 0 + l2sim4g_ue + -c 20 192.168.61.11 + 0 - PingFromContainer + Ping Ping LTE-UE 1 from trf-gen - l2sim4g-trf-gen - -c 20 12.0.0.2 - 0 + l2sim4g_ext_dn + -c 20 12.0.0.2 + 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index a776b85c2c..37d53e09e4 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -95,19 +95,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index e70d954a22..5a6189dced 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -75,19 +75,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 10.0.1.1 - 5 + rfsim4g_ue + -c 20 10.0.1.1 + 5 - PingFromContainer + Ping Ping LTE-UE from eNB - rfsim4g-oai-enb - -I oaitun_enb1 -c 20 10.0.1.2 - 5 + rfsim4g_enb_nos1 + -c 20 10.0.1.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index 6b88816c4a..e6c3e1f965 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -95,19 +95,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index e33554c8ce..86b217a2a4 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -95,19 +95,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index c39679e063..862e9cca52 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -96,19 +96,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index 7130976dad..e37ba4cf96 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -87,19 +87,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.73.135 - 5 + rfsim5g_ue + -c 20 192.168.73.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 8a7549da91..86d369e526 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -87,19 +87,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index e1dc8f0d60..e2d1e3c287 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_l2sim_tdd.xml b/ci-scripts/xml_files/container_5g_l2sim_tdd.xml index e2631d6e05..6abadf2f4c 100644 --- a/ci-scripts/xml_files/container_5g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_5g_l2sim_tdd.xml @@ -87,19 +87,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - l2sim-oai-nr-ue0 - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + l2sim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - l2sim-oai-ext-dn - -c 20 12.1.1.2 - 5 + l2sim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 86e5159264..4923177ee5 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -91,35 +91,35 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 - PingFromContainer + Ping Ping ext-dn from Second NR-UE - rfsim5g-oai-nr-ue2 - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping Second NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.3 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.3 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index fea7e03e5e..f124176209 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 -i0.2 192.168.72.135 - 5 + rfsim5g_ue + -c 20 -i0.2 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 -i0.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 -i0.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 5c5b5a8d8b..b178fe0df7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml index d727fdfd1e..d1433db738 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml @@ -58,11 +58,11 @@ - PingFromContainer + Ping Test Connectivity (ping) - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 12.1.1.1 - 0 + rfsim5g_ue + -c 20 12.1.1.1 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 4d86cd69ef..1ad3158d20 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -62,19 +62,19 @@ - PingFromContainer + Ping Ping gNB from NR-UE - rfsim5g-oai-nr-ue - -c20 -i0.2 10.0.1.1 - 0 + rfsim5g_ue + -c20 -i0.2 10.0.1.1 + 0 - PingFromContainer + Ping Ping NR-UE from gNB - rfsim5g-oai-gnb - -c20 -i0.2 10.0.1.2 - 0 + rfsim5g_gnb_nos1 + -c20 -i0.2 10.0.1.2 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index b6209e871c..19bb89518a 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -60,19 +60,19 @@ - PingFromContainer + Ping Ping gNB from NR-UE - rfsim5g-oai-nr-ue - -c20 -i0.2 10.0.1.1 - 0 + rfsim5g_ue + -c20 -i0.2 10.0.1.1 + 0 - PingFromContainer + Ping Ping NR-UE from gNB - rfsim5g-oai-gnb - -c20 -i0.2 10.0.1.2 - 0 + rfsim5g_gnb_nos1 + -c20 -i0.2 10.0.1.2 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index 095986b751..e7b0e7903d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -60,19 +60,19 @@ - PingFromContainer + Ping Ping gNB from NR-UE - rfsim5g-oai-nr-ue - -c20 -i0.2 10.0.1.1 - 0 + rfsim5g_ue + -c20 -i0.2 10.0.1.1 + 0 - PingFromContainer + Ping Ping NR-UE from gNB - rfsim5g-oai-gnb - -c20 -i0.2 10.0.1.2 - 0 + rfsim5g_gnb_nos1 + -c20 -i0.2 10.0.1.2 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index b030f5d423..e9e9374cf1 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 From d0aa233aaf73add0a18721c0072f91afe62db84f Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 12 Jun 2023 17:11:22 +0200 Subject: [PATCH 050/119] Remove PingFromContainer definition and portions where it is called in main.py --- ci-scripts/cls_containerize.py | 56 ---------------------------------- ci-scripts/main.py | 15 --------- ci-scripts/xml_class_list.yml | 1 - 3 files changed, 72 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 520876ad06..813b14ce22 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -1341,62 +1341,6 @@ class Containerize(): HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', [message]) - def PingFromContainer(self, HTML, RAN, UE): - myCmd = cls_cmd.LocalCmd() - self.exitStatus = 0 - ymlPath = self.yamlPath[0].split('/') - logPath = '../cmake_targets/log/' + ymlPath[1] - cmd = f'mkdir -p {logPath}' - myCmd.run(cmd, silent=True) - - cmd = f'docker exec {self.pingContName} /bin/bash -c "ping {self.pingOptions}" 2>&1 | tee {logPath}/ping_{HTML.testCase_id}.log' - pingStatus = myCmd.run(cmd, timeout=100, reportNonZero=False) - myCmd.close() - - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', pingStatus.stdout) - if result is None: - self.PingExit(HTML, RAN, UE, False, 'Packet Loss Not Found') - return - - packetloss = result.group('packetloss') - if float(packetloss) == 100: - self.PingExit(HTML, RAN, UE, False, 'Packet Loss is 100%') - return - - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', pingStatus.stdout) - if result is None: - self.PingExit(HTML, RAN, UE, False, 'Ping RTT_Min RTT_Avg RTT_Max Not Found!') - return - - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - - message = 'ping result\n' - message += ' ' + pal_msg + '\n' - message += ' ' + min_msg + '\n' - message += ' ' + avg_msg + '\n' - message += ' ' + max_msg + '\n' - packetLossOK = True - if float(packetloss) > float(self.pingLossThreshold): - message += '\nPacket Loss too high' - packetLossOK = False - elif float(packetloss) > 0: - message += '\nPacket Loss is not 0%' - self.PingExit(HTML, RAN, UE, packetLossOK, message) - - if packetLossOK: - logging.debug('\u001B[1;37;44m ping result \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - logging.info('\u001B[1m Ping Test PASS\u001B[0m') - def PingExit(self, HTML, RAN, UE, status, message): if status: HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', [message]) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 97bc6fbef1..898dfca6d8 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -374,17 +374,6 @@ def GetParametersFromXML(action): if (string_field is not None): CONTAINERS.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')] - elif action == 'PingFromContainer': - string_field = test.findtext('container_name') - if (string_field is not None): - CONTAINERS.pingContName = string_field - string_field = test.findtext('options') - if (string_field is not None): - CONTAINERS.pingOptions = string_field - string_field = test.findtext('loss_threshold') - if (string_field is not None): - CONTAINERS.pingLossThreshold = string_field - elif action == 'IperfFromContainer': string_field = test.findtext('server_container_name') if (string_field is not None): @@ -881,10 +870,6 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CONTAINERS.UndeployGenObject(HTML, RAN, CiTestObj) if CONTAINERS.exitStatus==1: RAN.prematureExit = True - elif action == 'PingFromContainer': - CONTAINERS.PingFromContainer(HTML, RAN, CiTestObj) - if CONTAINERS.exitStatus==1: - RAN.prematureExit = True elif action == 'IperfFromContainer': CONTAINERS.IperfFromContainer(HTML, RAN, CiTestObj) if CONTAINERS.exitStatus==1: diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 1f7b1afdbe..116ad769c1 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -40,7 +40,6 @@ - Deploy_Run_PhySim - DeployGenObject - UndeployGenObject - - PingFromContainer - IperfFromContainer - StatsFromGenObject - LicenceAndFormattingCheck From 0807b1d99b54b5acd5ce0f4524a8603a1f8f5b33 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Jun 2023 14:23:24 +0200 Subject: [PATCH 051/119] CI: docs for nrUE pipeline --- doc/TESTBenches.md | 11 ++++++ .../5g-nrue-bench.pdf | Bin 0 -> 138821 bytes .../5g-nrue-bench.png | Bin 0 -> 24001 bytes .../5g-nrue-bench.tex | 36 ++++++++++++++++++ doc/testbenches_doc_resources/openshift.png | Bin 0 -> 9309 bytes 5 files changed, 47 insertions(+) create mode 100644 doc/testbenches_doc_resources/5g-nrue-bench.pdf create mode 100644 doc/testbenches_doc_resources/5g-nrue-bench.png create mode 100644 doc/testbenches_doc_resources/5g-nrue-bench.tex create mode 100644 doc/testbenches_doc_resources/openshift.png diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 300d9cd56a..1641e0160a 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -61,6 +61,14 @@ Note: The available resources, and their current usage, is indicated here: [PDF version](testbenches_doc_resources/5g-aw2s-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-aw2s-bench.tex) if you want to modify to reflect your setup +### 5G UE OTA Testbench + +**Purpose**: Over-the-air 5G tests with OAI UE + +![OAI UE Testbench](testbenches_doc_resources/5g-nrue-bench.png) + +[PDF version](testbenches_doc_resources/5g-nrue-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-nrue-bench.tex) if you want to modify to reflect your setup + ### 4G Testbench(es) **Purpose**: 4G/LTE testbenches @@ -121,6 +129,9 @@ Webhook - [RAN-SA-B200-Module-SABOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-SA-B200-Module-SABOX-Container/) - ofqot + B200, idefix + Quectel, nepes w/ sabox - basic SA test (20 MHz TDD), F1, reestablishment, ... +- [RAN-SA-OAIUE-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-OAIUE-CN5G/) + - 5G-NR SA test setup: gNB on avra(RHEL9.2) + N310, OAIUE on caracal(RHEL9.1) + N310, OAI CN5G + - OpenShift cluster for CN deployment and container images for gNB and UE deployment - [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/) - obelix: Ubuntu 20 image build using docker (Note: builds U20 images while pipeline is named U18!) diff --git a/doc/testbenches_doc_resources/5g-nrue-bench.pdf b/doc/testbenches_doc_resources/5g-nrue-bench.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7e461807c11ac0a0235f690318ab8234d2ab398a GIT binary patch literal 138821 zcmce-1#lco(=8}wW@ct)W@fgSdBn`jXn`%3C5y>oW|qZdF*7r3$M=5!+xKGO--zAV ziO@v1rluzAWS-NRS>2Q>5>kw;Oq_6()ANJNaICB(EF=I^TQ~s$IA#S4M=LjL5-wgY zl7C-t%u+V?ZWb;i%u@CyZWa<2W&m>wI3Xc8S2q_669+i2l|d~}lm}d~l zPrUII*tnSZ*h$3Hp=dZ)`(Ywp2r zFb*fm5yahSRlCS(r(aodi_9QJ43nb!$$^_ndU|*3Hwva}y?s=V;(uIoy? zp~}o$OsS6?cR2eCRYw$+Ah(h~B5Lhe2;s}Rpy_L9PF%ww?)hngNVM?yOvs_JOss+- zji3owoK`<&l$*#a(O1^0CnHBdwHBwmz^grM$&Iq**{PA$#=S^~xfP+civRMo)}o%T zVW?a8rK0;Pc-aD<5xJ=G<-I>-zPTi)Y*OW+xePr?4E60@zXo>yS%REfQnnURXiEki z&Q~(7dxnID(bA)TUl!ZmlexZhoG3m(*H=R3b5=8SR5)SJLfg5avU_cY`Zf zDr|~V30Z+w#-l{LIbMS91Qnt;+k>q<1q*Oi24Y7Tv!!|w#8~L>dCTKnb`5=Nm z!}j}-smDCnthR~f=WiNsV(S@LF_rpSzySpBTO7K~{Em#qY{9^HB;WSD1R~_~=jHC} zz-UXsAvg<1^Z$e}@aS*&bNo*<(C~J$AYs-~Hnp`dbAw}6cQ-V`pQ@NxStz+Xm;y=kUtf@Qv;;`l zn7NU#ashu;4USn%4B$obg#~!R%F0f{%Fb&5$1LpvaCahMW&3x8nuROC-NnqpmE_d?8^5@|?urFIWGI*6h6hJ)Pwm4b;KW!}s)={HOHAAv64{MVLVBwV>+$kLdklz<;U8{|ors9Gn<|*qONioEX_T zxp}!*8EqV_{vX51^FPB0JZ2%`}+>me z>g4`b`Vrw}?sV?-QrPd_?qff(@LK!hl^T0p_%pEU&d7+^ka*21<7tl5sb$`O6w+uU z3Ge%5K}#OfXYM=Ba{|K<^_22O>g1Ny;_v#2&+5cl^r`08r~0=LD}ly6(-EQYUiQlX z^Jd|<)|S9Pmlw+J`>zs_pXRkc5_uo}h;KsSmS`^K+E^#O%QBZGxWil?zrnEPsvgon zZHf_i)oz^YL(h1@zJz(+h3imA9ZY8lJ?M=Lg)W!X9t`Oaoo)6IqMa6mvow?9WUK`# z)P&m$Y^7Vwf!$x^VwEFFDe2%=u`K#m{%NVnOKW8rzry%&RX!}nm5^0fAjU-QG8qOj zR1sV^L~jnmToa#-4Q44x18oG4%iV$X>ssH%^kDG0;pdTtx#4cd0G-($zjCch$r^Uy znh1^bWU6?}f*mRTl%i(EpkP%gA2x5=g?Pm54!#w$lNrX1SWgvlY>!H6eqKPwK+#>{hcc6U94;f@vr6Fni>(ldg|_UE_D6F!Hq)|E+ao# zBbfa`6^erF`wgNNEWq%G6=$}fKWrptzLoaqNu$N(63b0{Z1O9DG{C7;3k{nNTDE|_TW<;@IHN|a!v3jl|u~UsrgDKZea-j$ICILR$REszUhz*9Dkr9 zmOWsr4{?nK^B=?IpiV|xwi}b;57jhH?JsN;7s^JW3lG)4)(v%^4iS3iC`z;jqX1?Z z$8f$ciE-s-(ZQu)Z&dyT0Tp{4b+^A=dp1o^aG?doiC!#x6||~#-UbYRTyYL21$U#; znhz5jN1Hy*xtF7mC6zc03kZAE>E%qlYX4tAi=*jr|JZF-+VElWqIzO3qoQTB&d2eS zui^vIDm71p1a-Xs3#qzh`&lDEOCu*1p^|&T`yf|Ey3&b06&uV^vJ_*I<Fj$rR zwFa=LkrOlV+Qy72hkiI^xkh^zPQ#6|^GoRTKMN=)v$?dCm~E|%j)JE`Kzb}Tcst2m0~lz7VRoN~jAx!cx>nVfNgUQWZUD@jo8z>9Bh&~-y^$oFlVmt z@qWAG(OS&)n1GFi-So5E{Ey@2UkBhWAF0T#9i666RxOXfgEo_e#rvxD|AW4|vRYcV?wlKy zBN-FSOyfYGZ9LCUKG1zgk>$098rHmU0bM51&{e(12C^fSWr;Pl0^NkS00&xCeU|PRjrK5mv4h$$qp&yb@m3 zk)(sidoRWLpEy)pn5J!uljXzY(p2(~wyWrYYtM7Cwci`^SD+xo;Gb z9lEOSOl&OG3AQ4EWWHX92eGI7(Ls8sJBjI*6KCv!0WND0jbcC|O$Xx%T@ihMx6aDGd5=_lQGU^Y9fuCFvHJZ)0 zd$3vGNw>I)Jcv0um1?5x1v2O^C{zNvzx-o80VxubP5s3|CNORqNz>>D1mfD(gQ&+9 z)!_fKTb2)vOVcsW>E49HNQ~oPf;caV4SqI6S&`f2_B)V|vSfly{>@~^`sT)=dE$6$ zBig@3ZdQP3aTPhk7RuWAC<5cTEG4wQomIA^k1Bv+d>S5~)oNFYmkV_ttLVDlz#ODx zNdl-Q6pm)=bAP2$eXtHH9p}PrM9pE%w}6l<>>JfAPbXK^^KUycpiq?W_m_BuGmUn(9WW!Ovb120|`f2Az@FH$!N{4Aad#b#@k&l`Fgj4c)b0~O>C^d38xSM9#~ z-4)=DMO=1z!XW3r_HMH_Rdjm5@LuCM8PMGGk_Bms5*qa+xa1Kie&wL_Skbvkd2|ms z<35UC?)lnSqYouK(BdDHYFuWcw(~icg{`|nF#VyusUtXQ(X<~Mt3UfQV2<1QBDMWj z2H?I`^7ehm+$zuc8jfESJB80ro+iA;dD+4$5gyH- z3eI-@EG>`0PWdw@j6cf1PQ}Xg{VbLAvo3ue*!5b;2dkj~0`#x}d3~Xq2djxadW@$t z^g@xmy2NXNAjxruEdR%xmhErq{a-n)l)Iyun+?G6pWK!Oj#&cWU}ED4OtXP0J20J8 zxACz6p0EKA#cbSMRV-Z8O&px;El7CanAJ=it^R%p9Qj{=z+uWR=D>;om>2%1=4Sg_ zfB-Yg|EAu~UhVL{ohwlWMc#%O{Xemp9XQMXe>QXee_`|AN&d^^|EtnL)&W>W!7*#w zm;>7roGd^G$XM7|S-X+2ad7_+$i)E;P5?&>VDb(`T^wK!a8Y+MF#}d|5*8jdW)^DF zVn9bJnz-7Lu>Gg*`VaQ3teos@oPRqW|1JJ2XPusz_)BS&ABTE{I2f52Wg_&{bSb8j z-_EjKP3vVxn=B8x+4DR*C)sytqR+B%+VBzc%Rw;MzK`)je<9b^{dGg5tNV3tbNq5c zd*NYH=@;d^c4!R<2As96-$t41l;C4x-~`~Av3tMyEq(LmOThU5-N||4<@+`=vcS{y zKta|;*WpGavH#hzRj&8*zV?RCYfhrj%hA>L)a|FxzcW5)H~2sAXVi2)@CDy>ee~w$ zcI9paye!YjKWyZ7ZESQI-V9B5&D33&;&&gXf4S_u{22b+k3P%`+`eDheCmI_4177Z zGCKG~z5U0sb7srex7(>a{|iWJJZj^Oh4t0-_0@&-x!=fb1EQYV%Gm4e?R@RWxP(E|Yv98D zraB+r51JE&U(arVu6Sv`?0Ouf&P#!$`P`)c*YO``4=eZpqPBe{q+^V!oR%IB50P!c z3yi}-Q4)gPT4Ai11Ss+!ps{@)y*<-ip`rcI&`^($_sH&#cdXGr6Jhz$KL4Oik8b4% zyF}DX=jKo?!j#_L-6JEM^P~Jalb~~5CG-?}x*}H=cy7-yd=VslBldgRw#xHQU-JGp z=;B$n`7heI31sDDltt{d=hwk6VYUbBFp-nMR}rtY?FS#s!mbh%R-uRcUZsX2k>e0A z@Q;btHicziK1H}G-xOvqk1fn|`+b$EReamN)-soMd5tZCc?*%g`Gbe{hh6c{EEi-s zwmo*e2Hs|E3cbF;*K|F+_y#_KlfHQ`PyG#h|NUlUp|_(CXrj8p(WIS|CslC%06Ebw z=w88ld#uJ=!aArSwvs9}Jm#b%nZ#yco4h=Zm&AyO#0Ur%#JD&so7_AKEZvdk>+4}x zkF;Kg6oHo;Ow}i`(l0)V0!Nl&D8j~e65I>kBgGHr!YByg>fg@JJ=gBH#F2%c=hd0J z?p~XLEb2!V9y=BIhd|vA=X1)!{%6g~e2x*n+`7bP9f!pe7FQ7;CZ{yU6hx9evWVC> zs%O3kkI9#fE;@Xx;c0c2LOjX

5;IKn@w>KDS5h!UIz`6GPr98RRN}vM3VIfmJ>A1**x8M#^aH$fu{jA6#qAi!};B_SEh(QwQ1v zPMN2TG5~wz5&Eg&?J61ozL{o=k#JqkWb*ndJrwzv2vknoHP58hN9dMsk)~Z7=bN=w z%#ogxhmUeSoBf7X{D;p5zL2-r)JgOxTf_t_!bC-3pH2K1K1bWqxqc_do1Y&RddtPA zf|0kMHCcbd^>$t8X{-O0$ZtO3r`Ys>HE3+?kV$ZZD0pyH%j^O;mhlP{n6CzEP^Z^< zkC+@v`NdGMCvFP#RR&G8p(x)QtBR-E67tA!&~)Gc8-|K0s#w7F*R`Oya5M7V$>2H` z(l?0b$cID(1mYv&73oxum$3NyiVEo{UWI-Wo~g&q7aiw-E;2Vd$tc=4gLMOQQd~SD zT=;>V=qy0%{l+VCe)u}Jq2GHvx30ugiMP8jP>^d5AAtHS^sq{OrbB1_^o3+Cn5}p~ zftx2fI+^`>M#XJYhUZ)RU`#Q1+rT%FYOjIPx}wAc&B4VWH>9EyKG9YPi0$|Y^x<&r zIvo-Fj056_dA5wiAdLX9mX*_9k9W7Y&(4G?Hi=0Bi`qaIV`3cGi@!3u+y!pdU=zFO z`pVz_n%S{AF4w$X=}52PKX{HidE01QgW;htu{kdACg|VcK0c~M(6(FcOXPjWtt@5a?yV2e|Js&9F+^an0BSCZujSXUVO7Mi`HL8C5vO>Sb>c$jdr%-M*!P#&{8FI zFg>hJ>wJgqx^MoRZu;>){P{EmJtVe^RX8R}jhixD5XC1$mRKAqp7s3tH7%e57=zJ5Go_LNd2R=DtNoW2|5?HlS>2Fg(J z*P&1?ww%uUCVpbSqiyQkxAoWtv&Skw31uJ+0*mnr?3g?5T?W+~yQ3Sd%4?US1_(U>YmAF*TBLKB|v&0HZ7=d=W$i`_cAbuQ=MozSMd z55n!7_(B-y9*`-=twF~}ki8Czy-J0OLk~ecCO#k&pW!br%?Zyh%t=3adoq*1k!2T1 zuX6H^ZqCu(6F=_|4Lr1N8~Hr>zPvyq$3c+Q@gQz@KXwfVygso{2|b?J)pVyO9*qJ8 zirL-w{GOZIv5k>nJAdptJ0uRuL&QI{vX5r7P+1)38>9wX14Z_22DjUL9`VN=_2<)V zau7SNAQCK&_E9;jR!1?3Hmhy)tts{;6=_o_`vPXl)!5EDOySFjaHw`9iPnN}&--H4(w)i~7}IR*T){b=EARM6{k}(;o;Aqup=4L1zo= z+$+LvLEb#CurlcR8{;XsnZDhg0BW{d8hdRiMb#-tBBG6{@pzH1SC7bN{7y+ycSY>Y zn*oRYi2^Tsm$@(R<25LKpWDFv)q`iVEp78=HSqr7VfAvuWmu3vo>PcDtQQ)VM)Zg0 zU`!H>Y{T9b!X5_WaTrQ2HHLL0ixn1gOkPo)K`%e}UJ;1-SZ8X1b<7#U>OC~>7B#4( zGF>V1cY4T@{WFmxrCBcK`_CYgC5*h;ws@Y@{;tY4IjSkvKb*xl(r>UkBJVg)m^UOO z*M0~j9YfyHSJ?}(HT63fC!^{QaQ+DDO~P!Bmu9uXwSnfwo4p&o+qpsq+Y~C@&Gq&5 z(y}iR^W+&Ius3&@HU~xg{OTP_72pQuytsHmGUPsM(OHgNhh49*+kqF)*oMGs&Ev)o zR6%d>zf%5Lhu_#Ma8-*g&uXn0QHusv2;MLul#qQ6>kra^5p>AHL{f0niM33rA4&d# zW85O<0z0W1yzsV8A{-CyOF@YnfM$qm=s+ODC+7|;CEzr6#cO;g;_TuGdJU1}0X07A zT#PYFpC~Skn6#f3n?l}X=tz;eQ~_0rnm7*Gw{^a&ws3egiH-EY@e>;i?hI{Xfqq*@ zgm_L`Zx&GsY1%yZsw;Fi^i}#5>M^;q8IWHespay>;{Q{f(&?m0-*9$e`1><>d5!1I zA4j;?y|MmR>Av*T$%BiIQzEgaJfD|uo850WUjW^=+tUB)(T4**sXVX%V4hza(PbqY zl_63M*B~y53GpnhTa`(NeJMQ}&Ce4k?BXk(;n^Rw8k_iytzIB2oB{?-duL$ED?>+s zWz7)iBm(~gR)Na^4}ld#kh~|HqM{P_aTV3UR&;kVb_ORF?3^?uEr=KdcG}V`L{AJ3 zv-%t>RuSA5A0SD>yJ-fu_uT%&BqQ0+6QhIjHE_L7WsijNt#^CIx$mJY($y(5oaOOy z-^8vjX$~=2pZE3=u13hexE|hu^9(eRtT0~Fqbzl0Y7fd|Ca>`|^zR1Fa@(y`;FOdXs zgR%%i_6R^G>k@{w!t{@R=81iLZPP_ji)#s?noz(@o<@YPk^6LRSVq&Z3x;q4dG*o$ zrEJW`E_^i#eQ!&KNwgpuQF{cy zsL3&ze!7ev8hqOy8ch6k_$5+DPW)3vSvgSKlel8f<8t30xWNtbK)G<(7f{l4cc!X~ z=;A)@31_gr-s#`}iX3q+HaxkQdc#^WS404to zL?9*QmO)=vhov0oC6C9r2$k|9Oy5KPE~}N)-WMmEAUt?4xl0UtcBM+LVbH34$(+3(=u!Pog&G8PDZBq=E->J$p{mgMAw6a3;Y^bI5MbB%doK2v6Wa$@i<$_7Ha!(?KRw zqRM=u0f}kC=|?{?HwXQGM!h|$-w9I3DI*k~oySZ$Q|IJHVSR}Y&x%j|d*hNA=i(Uu z=p^|W!6h4OYSzjQG{~)WvlbepYwVnKyqC!E(83O)RmJEtI9YWyIw~r6^X=i!VQ%1k zk+E1|!EhOdDLy)0c+%V^qV6{2#-wO3( z4d;!k?HW`1PvuQ|rE5?V=q_y^kuXB;Izz!lFiGm$$W;W0({+pGp|iJUV)GX<=BC%>GC%Td((CbbVBB zd?=;&C}0wi+{QfG1s{Lh9~!3;WB!t8KwYL32q2v~e#0MfjalV*FZCO)wR6LNHW{+TLbGA$))r4cJqU2X=^^h!!`~?5sC=*_?bahetG2$W-=$Iz!qLr$}Hh^ zuAKuQ=Qm3{lNg(^Cx%wQCY0Qa8-XUMI32eo9ywzWuWMv$q7;IDpQ6doZf?e;cJn7Jg~Ll-E@q)x!+EXNRT>JM6(p_&G{+ zb4zIpywVaRdpJnLN~{0W4>i9kl5NGrt2b~3z>ZwG=MPaV0JvoMU(wY_ML&Wg(1VvE zF;_K4u$O0YL!b#7hW8oc&~&Cjx1J+x=B$?T#3=Pd>UVdq4#d*j_N6EAs_8(lR3JUX zf}UOP)`OuxNo)J<`ZUGSeT#;uMZ|tePdM+W-6}uD%Cj|q;`vT6F~*#~@i@+hv^HBQ z)V|aFvB9I(d>W2Ko_+EUdG7QF@AMD#_YY-=ug{1dKHuj<&a3kRFS!=Tc4eNwDk$$> zl5t{4L*EXg=1r-}MoCeGVt6vIqFdg4t!b;!3 z1()*t&Sk)U8%0xFl8QtNkiOBn|7u$b+9HlSa@40F6MZ=!=sbx(hGe7gAzudFl*9Qx zfunUCpUn;PA;qh+WF=a_W!&;uXC$K|D5{y!7cl)(X)@WF)xgs$@N>Egl-Ia9W9o}} zyUc-kryjxKAgj!ASlwID+c;%@>ZCR?u%bdA{aaB5M-qK3HE)cOYX-b>|1r+>|0wqI z0mD#0bSIoWC^GE^!Q|v33t$q4%m5J%Z4+~ss1m%&MH0OskmTSu-|?FjNY4xBFU`9F zU}*1dQaXx1sYkTEK}4Uc^aQ)By_5i^1=r)IAtQAa{t-*VYQ zBN|YCtCABKbmo6n7nx{eGPe-UsNVNsSowT*jv={$pE-31brYCl0Mri^qF*kp}x!Ix9RyPc^83auJE`yeo5ag+uRT}Cc< zFxnpDQoe2hn~@B`-FZ}8)41(!%Z^6GsXlGE<*^+W2`AiVf5hW~yn26s2ev(Zh}wZb zEPvcrH3O2laIQ-&Ts34RYMCcFiY~w2)Quz-bq>l|XZ03gi#g);Q1N4_DXbXJkW$tU zVElm!s=@JMsFLx5xp95a)_FOlAdQ5FHY9}T2;C=VC@Lr#-TU(h#W@0Q5G5FsD4{re z5$yOLf5i=f+OHgQoAzkfkrEap?1nHaKjcC$ztE9c9HU!l{oE z6tM_14~WhFR@*oh{2`myU~W;uQDA7x4C-CU5{Tis1y}7@HdLKyd8x5IGt5^3D#y2# zE*g-ue;Y;y4Zax6$_I!w7J|{apePLx{BbJS=?}3q3OBv9^a*S*9&FQhKd%~Zd~RL% z5>wP#4$j`GTF>7F?qbnIxI}v6U}*M_VbP3sz`hb;!P#%89P)!q6TsFJ(3x#z!kyuQ zES;n^m`=Wx^?YV-U6BUehSUwuo;;p1$CIH73DAB*$A$#ZJNQYCpgdEuMS=v48%@^n zA%3Fxb6!*D=aG6U9ydZzkWXTmA=^|9S!K+|=zc@QtvP}N^!0e`ZwCi+b+re`r`aL? zK&pYc!VKPRWq6e{iyNMReLLqP?TrZV!pqI~`e>oH2d%hv&L15~;^4K%j=nOXSh^Bo zPB;V|2MPQ(6l&hQA=#pS-&(7mVNJUa+$>Z1(Z)4haEa z!}-v_8)Y0|h(AG|D0rbFgS`R|VYUAVt~`gcL0Ke!GMTI!&2F-G87jl92ACZR_M)rB zJ3{~*<6(@$P-q`jJ$LM!L^X@I!B1gu7^2(UxyuYK#U|*h7uxKOi7*ttzV6?%^g?f7wOs+ zfg`uT5xsB9OivrzHg3RH#Z^IE1KGR0aGImAl02z6_J9z2bUvuR#AGz(5-a2p1H#VQ6E@w~q$K6Iggqi5qQE&8AaDM>s>V9@Q^0oe}&KGrMc z-Da@>j)*I%cPRbKcsX%t;b#&8}S#aUo zMZB(69OaWes;X~uG|5D8Gx7ktW0hiF@1o*u(X-<#bh-Jz{gD#OH*s6XYtxGU_tW z3(G14AP;ec(|2VQ6HpAUtxzJ)c*b2rR+Y^~MLdA9C!C6XBSKbPe;D{1Qjx8GRboMD zZ%)kMNb?PSs!Snd9N!hQOAY3mS9r>C>%2ge7%sHiP{Y1Ndx7cZXaV-+q#qdWpF3wf z8oT6O;3^7xB^#Mhk#*7v#}V+yd;>a7?O>2pq-ZX0czVC1@KGFthEV130QubJ_n=9s zwD>x*#m05&AAIf{s9&=A#6-I-a#>20&J zG$~7s>n4y>mB6trQ6wlOSq*B{g*;E+;!!ljlo;HImVNfb{@|>z0_rnNstpZZzSA~? zNwJzW_=m;xrU7v=Mlq!hH*``V;e2mbH0vtR1+P_!<0z?QChz?%!`~lb9U8XdFDG~t z&y9TXCmcN2$fJBHie>oc%rQpDWf}ymZ3YqWqiN^EekA>}-IRgRwU||DJV?X>cLKMm z%0w=wpAWARH;`XO1|%VK_gDREF6$e zI8@Nf8!&@KeCSb~5-Qb-52_r!LHC*#1oZ$rCT(lqmJv7`2)M2=QU^AF$@qI8fE#1H zi2$Rib6_XIX-N?IY7L~c-+H!s{0CIvgQ$}AhWd**4OoqF_Q5+(@eXNNzsieJBso+M zSrRr5&b6WX=p}CN0%eok_ut5-L`cMvTL|5gvxh|xll9%>JHitS_xierX-3qJhxkW>(Ujj$oj zw~&*HS;lIS31<~)%nSE>Zq4$eP}ca9)KO-ZoF4l$wLdpxuz%1Zo>>LV_l#-yYK4GG3B|-Z(MokmO5((vAguPIF2xKzDo7cwR9^gjwj6w{;B#=aKX6 zbq&|?1vGt5?w2SrHme9aMrm(DUn4bSLN!bufo%g_o!IGhSuv^L$c zCdL`dM2dJ^zDCEE1hib%TMSVx5;iuw2el~_Y_d|d6FVdn#Nfv!wd$A%vNQECn(PcX zRE7R*KS;rvE`qN|kOQ6lZM+8))|dPqeK%Ky@wk2_Z6#>Ko;4kYB7Y4u7Z8yyJ6k`%k_<#)fj1j=#*>ut(Ks2t&o% zw8n8S!L0TUtBS*zm)9h2_`%vu6{R~QAx1iPlu$NVJ||_ zqXRLF#&rdlJ1fvTB_9>Rc%K{;8|A{F@KS1y3f8p5oA8 zp!kXmZ3)? z?K@x6JBB{rj05kWVD#LrlJi1sFOjjma)2jiw*`wS?pHBRv{qe@`GD0F2<31^=J^t0 zX;oBW5IB%R0$5Zg?V)SMXC#ALsQ+$HKbiy57^d}r!Q$$zfV}Jo-;lvP*1YGwwH^#& z0?+Ciee1$G(>?dwMFY7^cx-_iqr4O^;k#a^cW6Ef7O5ZFF(Yc_#MV|giqZ_|hXT_$ zMSS{3Ew??Wh@jevp!MZ>of=&{_ahaDt~smQ480(A-)?eaIXc)aqB~hJYX-$xg0g8X zGERWZxF>-ofs2co&{?LVkGu0hZN*vg7?dzwD7;RCk^qgYFU`&h+A^jMGB0b$`JS_~ zHn*sU(mHfx1U1#o@<&=zZ^!#2WAmms$`F=MNRMH3uno)>R^bILeZ-wreGN1dMDkY? z$R!+jzfco#qG-zwAt_a1Og;rE;t@fNUM*Z5w6qOLcowH$t_oC7Hm(%f!fIr$IHjyt zRfbk`zXTcZU)0wf(+E;s!@`hqfOOT)CD#TW z9UY9-84@KE&>=yHVX|(mal9OG)wupK23^wh@Kxp zW2FXnhJ@g|R4aV3x@g|s7A+eO&rLPD^78~Kx^uElwXR>p<&YZU7~slV9!XLz-O^J{ zJlft54gTAKKk%uaSXI>0+RHfUOx%0pV_{Y3V=onW@4}ihC!@AnTvZqt!qRu~kVRkm zgIybGDu<|m?}211anXD?)seU(uNf-jYDvBAhDao)(yY)>VIDU*?^!Z+kYF`fUr_W< zyEWukb>+7Lv1lK16Gu2{;PLYZhJQqWtE2i3ts3kX&tM}+I;&#JaP%P8{N_bl5G3oc z$EqJ-lp4D-j0pd;aaPF2R4l{eBbdUmJMQG9i!-d@Q|y(7Q)AN+@feoOUNao4fJR=~ zM`5v9v7MyK^&~4DUf%=i4cM69z`*YRfjXFxj%uyfDiE=QjbsC!NE8HY*CFv#U~&3#urgI_Ph> zHgAr{lH1~2U`QTVm&+i0J=n%*U`Vj5@s7$iVUO@ZGpzKDK1^<{LIfGYH?&!8I3%Jlwo8M%6zbkRt!(74P8Xlg<+9z<2a>?nMmc^ zk%GIF(g{YTMc$3_H{JG6bnYt>(IfxLu!ApjR+vsxRZS68S}5sWJPJVoh^w{3IeU)H zu7>vBpT|;^mD6iBD|L~3NOpb&e0;QjfrFQ$qocF4?fUE|K0iPC=uHfmU6Staa{)$4 z8nB1=sYd4iqw1*b*jG06E%oc(t(>szD4rc0&j$O3rGoIVJl`3pEyOy`EH4#J(pQ}l zYi~WlwD3WOIj3LK24+1xzZzTgeCz5q5}y6=%1)V}JbE@9Mkn@7lSPGygBosjb+3kh z#tE;1I8APV_7C%1!hu~j-bD!yV=p&)Qz0&(VHANk_>{gKMbKuxp@@^(l%ACPu@RL) zLmZs$De(M(ll~o>PD8l_A(}e>l-IDxk_>$~gn!a$mhilIUaGW~#fx>dr%V?CNY`5U ziUPl=W>7ihC08vnl^kDMjgW^eC0$)8E{uR}9!7;8@A-hNIlqXRmX@KVskyMk+0@u{ zzM{D~JG(eDGdGtp{7@5t`1h{8@eQwvo8m}!)1VKd(ke>q?umXGI6X2%yXJ?~P(xpM zOxC$n(vBL!86E7(Ow!g7!H8x4KyHYWER#^NSi%@;U8FOv2z|)org7r>sBfWo6+_+HOVm%d)27wmOFx6j|5(|2`dGfKKu=6QN==!iiaQ6HQZRSr^uiXeB=cAgaei$t{sfG+`epB5| zr6ABo?-At-#?{*0Eo61IM_?n)u#~}dM#pj!l(1``Kp^K=){P4q56)rnXqz(wUQQa0 z9s_TbAt@;bF){Z!IU5xf5&2j2Jlr`hmPH>7mi#K3YXY6Djksz?-!y@}9iP|q)e9_I z&^ip`Gg`&L!Ps9R$EglkT=eCvA_ZoKjDp1jpbIKxbZMlOq!o*#MnAHf$U<<{C zJI+NQRpLT$hKgH!x#1RC_-j-$jRNEs&V?f~;$8B|u9TBcmnh5bv|PIe5_^i$c$L_? z7ry54rMT)g*fr+Qr+vnw$odUfVe4^BD?=Rp*dm1NI~ZYbRt1GsqT}p_w*oQ0qKlJ% zOC6|%$T`x5WuR$pbA~u}r27&Haa|BX?&O1P8_(l2AW-?dIzItJGPLQZY~S{|m&zJE zNG~-RA&&=G(HsTBwVys%i`WyZL!9TmHMMG(`#0g#@>7h3DxK*WwK$a(*rr>-bP~Wh zK0aW>{r+KRXLfAtCZg?SG5z2nr>dP#&-2{&_{iE8u<3oz*{PBGCu7v?)u;mTAk_EL zcSLGIE$AF?J8k*H>gA4+L2HZ32eN5wlL^OQS{Ap-75>K0KR<3i7p!#Kw}2%xjd--& zgB0X)O9ai`;15I(eneZd@y#C=t$EIhrPGinxV~o01AMyp{P(aVJ84C%cACyBBrQZEMxRs7Q}n!ptysTtaSU0ji}F;+`cgL=J7Ci6qEgSH_id5 zjbuHysVuTO!x(S0{D^A?M?<)2>Uko6IQSeT#mQdjf5QC)+kPfed~;Fube7zI`1NbH z{ABFq<%Q7UH@_#E4DgO-YUtmDgjIxu=MbyDuh5aOfGIn+K!2`GX(C^NKAw^)24aL| zhwv*^^TZhq++{Nnbvmkru6H@s&!ROI3@$8Cuch-;l6lnE+244D_7af#1~RN7>@zRX zI)p_S;Q7oI1jk#;`Y`sQ>y6f-1Gv3!gToHm$=>dS(I>THwl8}NF{zT_8rN;e<&pQi zHk$5`oPXSKc)}6V6zbhnWELP{u zS?^^^Gf1H#7{J93LQTyzV@MgZ!Beh~-1j{}!B&HF(5jK>LLwvw>|CmCD|2BJ>Fdgc|Je5M6$d+llT-s!6VtMGJ~ml>X4VE*TWOre+HQm(LF!i}&MTp<;DVjPjfr>ga3-!u%J){VHfiaW&)Gk65 z#oTQl92s_TmVF3>f78tko|C>9aokjA*L4wW4f6?>H~pYbHMq3T4`~oLxB+I?0c5G? zS7us+QL4B8^@NKc!Prf9-RjAg{1vk`i4ph+!S=V9N>w}&O$~-xaYq1tEaX$FrlRO( zW{cFR`bsG+xP68lQw!=<>gJ#@?bpqPFFrgNizgPUnO!5{c;(B(EZd1kle+yBW(_rc zHsrSYE!*iD&)_cl8gR3|#X~@SvrUK!>5JtbLM)8818zmWy%$4Ph<(f=^ zkT61n^so&=O$Hn5nzSqPf0aJX`T{Q}Cs$rUcXDF;JqtFo`C>&;B`3(6KGZGZiXVSv z#l!z}RWPLauD);Hhhama_I=3Yr^yWp>eqrZx>RLJX5s_F}n zuL^Zmzqyx=DlZc4pU2-LqHr0_?`G?B3Q`#F4Y@Ald@~7|-5-&};Zi66S%edQnBB?# z>hm@%{JQ^;GP`qgbHgXMgum*E5}TeuY-I1~Cwiuo`5$=4dTc{>0m0-^A*A5mb7)nF+ zUX^D+d2=>SOk)L?>q3!Tgka(EH3}p|+i3ZV>LvsOFk(ZDK z{vb&iYK6HF84}?jWEqE!AfU~ch^2$DE|lP;1JY$P&OrwgvtYI05DsBm#93ykiO=J~ z0~2Y0IN#O<(*GMH1zfD!5h5Qf6tK^xVt@Vf4-TwlPe5uf?9c=UrEO(dt?`YXCGtyu z`*-}TzDgpDFP%L^3z#|!(|o*=(($Sh#6-&P>WO@@_5@a+v)cCkIAvtvfBaBlm7R;3 zq{aHg#Ui6`C_sO?dLi3xT(ITEwU_wjSGG0PR#sM)m$!9w)iuU%dC;4k{pROi@wohX zKbMeT33Y~XNNZ!Y{80q}K1!gvk^9*EDe3rkW8L6UP)2qAcTbqOkx6ze3&O0s*N+qV zUjl+zG}&vbvgMC)7qQ$`$GRA+U;>!seb!;4IIOKAy;3;VSKc(7JR$w;8${f2`B8e2 zY2%Wx_d4$f+SB10E^H`Y8a9}i$mA;I{-_*Eqw#JwlE*2gi1>iXAu%%r;e)~(4X}kG z?RE3ER9)Tm_gTvYov%=Q;|g)B%|qudJlPB5IBB?_*A%q$b?D|sLsPJ$R2csz5DR?1 z(`yQ&nc9eO zkL~ITseou;Xhhviu9Ar|2-`t9m9GL00)HXYd;SEkEk~|3>NHVA$eA7b*9}!0{hoJ_v&M|C{lw{G4$k>0QxyC+XGLjcFjk$RtTM4)WE|jwhZ828@nDT{d-P zcq1e5Omdf28F%o&SksQ3TZ@Z|E2s|B(9+Vfb7$M`U2PQ4ceBbV71+yaYA?R@Qcm5Q zl1v(XN@V`Vn zxz0_z$%pD6PO! zuffbAjLTnQ`Y^-LCnFUYaSwtWq+wsQk0Lg1LH}edgR?GimcEM`qf{~^?rBX0l>);j zzeG*PJH_M}9?}|PdQQw3@Ru@XHi?``?W;@%ao>{&EAZ9i9Wb5`w6%&eqe-RGcs=uq zv5UY-!tE`A>e3G*CnZHVyvN3!C;@qL@U!bXORB1h%FD}Zs%f`rTN|V3yIYxYo!3lj zT3V_b8&_}GFz<}h>swklo>NVRad^Vs3AXq4^$$_rp2zmT2pi0E&%c<=+^Ex6MCCD~ zV!kXBy*=el-02T99&rgZWAbe-zeG(QuHTAjOSw*cbj`GLBhuW0TsM}*stABVSP$jr z#I+O;>zFpMBf{O$5(S9hTrS`a_kkqd;lLL5l(aV^?7>RA3cK=9$qR!&%AfT;#S zJ(PxGS;W|5@DI#EY?o^Xik-whc}CiS?4v5JKE1K7D#d2NzYO{(65L*Q$fkIj4X;Ea zy~WM=Eah&-h$9Y}L;4iMPZ>F8hS(kiGhTz9%*h~9-IK@(@15}^KRfOx%fLw=Dty>5 z)qp8}37Kpl!-utDCIP3cvP8-_osK6m1Y%-{hKyV1@E)|I0gGzy`^Uq(ul?Jt1qH>G z6=k)x^-WF9?d?0RzFPZXc6AW;P7r?aiWN&&u3Wfe@oDoZU?K{kK8>g9HOx z=BL3h1jEfv^&eMhH97+av;DM%+M2)|a6G(QT^|%u)2h;{0_36C9+Z2C#l>skT{s)8y|%fzxqSy!*BN7HCDe|#tFKB1`s zOK)aeovH5a{J7(qYgjFHIIqe4H``!tzndFivGRqB`t;;=)TPf_h-X=3M}YuK{`T@GY1^7Q~5U;~;84Xf-xyO7hTkYF}pugv=B0 z|KC6U$L+->MdjsXHPw~%4GpwHO6@MJa>~o5RA#SlZ98_(tW5=l$De%CvQ?{Vo0>~& zY6y}yw6-?w*g<$Z+4%w0WP1CD^4R|0WrO+P!+U5NOv-k3HIrr%#tfxh^LCS#$Ef#D zL2KB|t%W^J8nJamIWC6c{HrWaN>`v1);JFtW(GbAH59-Nju`D#D*uWod znaHn29-z`7&M&b&hrd0eL=_vfDS4ghP%xJtQMFW!oC3qaHN6T9tg-5{g0R`=5a5F~ z#r7-3ivMb=o5_V^{s7dgcr>0zA^uWdsa&UudHyv7_=hCJ_XG=zgAmA&w?IDyY;f=z zX~2#W;NciSLHHS&SK*MnJ<62O0Yx`jSv90bbfXg}+NMH&i-LColor(qZbx<62pgB0i7b^0iz8&$cnSs*RQWEJiHwbL8_`IkCkVPYRO?VoziZ1~ zw_9py1)#cVU&%mYHmo^fR-EIaih~lmq}bvqeX0*4TT5JvHrgH|{fYqdbG8YdIm?BT z4tF_f`NdH`%%i&79$5z6wqQ+$W+`9-uez&@O0MDC0WTu2yK>9J0)hDb=pq>#n1VE! zceTw%hD-uerEAO$Ov7F+I{~5(um=Vt4D-4zng$rsxshrikkCDe2a;zF=o9cb?;tL! zBH>+5k5W2J$e7|fiK7OE19Q3_MNrS@H;q|*peh^EM=g$WXfm%}yojcLRaMs4)$*$7&YfIf;k=z3R5dki*t+$k(@x!7R5)|)?4rtw`qtLEwzlSu zU4?|{w={q6``=r$aRZGDs=gU7TqwYI|Ame8Ajex82grOA&WsBhqpDbPx(#9Mp ze$265)=XjMnCg(qpy)7=7!2riTC46Le?ABVd1#xV3xQ*Z?btIJ0fV2gAg^aXp`Ip? z^s7dDXdNal)7OQ-uJ)jGt*gh;aO69G|G%~t74h_SLf0GG+8TBcxE3~b79Buw{;Flm zSFB#WcWQ2(o6{(R-yHLbfkcu}>rqhmMk zOC8#m$M*js8_WwYB{DZ^Qq5vvI7Nq$YhwW%zU63$)|PDButT^R+e6N6)DVPDv!ZG> zLB0PJY#EpXcxULX(OB3*6fA4JMOGG#-j<=3gX?H9Ck`;#&DrL?0Fb-o*bAk}LpjI+ zO8{ITEctanY0qIPMtsmoifp6pMX#SuM?mQJeyr73Blz z@vL^dV}yrAZI~Erp{`iaFa>wrEUfJ`2BgC-ConEbz&Oqy&cNBMYTUN6!SF)d7E-$VB` zfTY@i(zkR)0^kKJLL8P#vyr%0%Mbl}84v&U$3u9y$I&jA~}k3a*q0&WHD5$F;T6nqx490 zLK5YY8C|PXNKZnmB+NHJjjQZHQhln!@YF9A5yNyCH^>;fXgKBB0+IL+{`r?%ii(QL z%PFuo5xU+=%`F`}n|4w>Z{mrLyE>{G8jhWL+}4tkV`t4=vSLL=ZSD5bQqh{UqkX}p zmtJ|*RZCZ_JmvJ$+B$ar;0Hh0R#eC{2e`$3*SEjj-9v|Sq%(Qm{-0=rx%KvYZIRF- zG;m4Xv$iXRmnimZ%VQ)B!D6ns+j7`H3;9*-&O+7&Tu&!d9L}FI z1$^X_r&M1o)?vS{C@8;Mh@xX-j4`2Ga(J%E@J3o*9u0fK$1oLFvUyT-?8yc;#iRnG zoHLHWy6L+pc??@(xRGWu!;BG4L#Kh*iJ%DSO$0fx+XC2mhv~RHV8AYT`~Goj*EQD? zzFkyKV+3lOn|Mnp59y_q&~_@tl-1Q;xnx;kS^11(j^0*Ma_aokw-y!g6Ue*gUT^^+ z?I)dj%H@j|ZrZkO;nKwot*wQnrS&Z>&F$?iOp_re@A?+S_Wl8a?b$EB_#%(P|Is#> z5AM1DAzL_;g#c~|Y?tiU6JRJX(9@)Ya-Uq}QMX`gIlSYJB5@uiu9%pdQ{DX#z!h&- z0=uU4fIzZ%$bEzB*Fs)1K#XV0GxoJZAJ=!pC_R^ zX9LOIikoV@qU#PQ(OUlI7QNz_-XXvA80}PvsqU?eDv}CFmrv135yz^&`lpBsgOFBc z;%0nJ7%mENnQ|P*lSEuNdOK}kI1th~@anOEV9YDa3R5nfs5$RR&&!56GchQwB+X`3 z*zv>#c`3q-i<8p^s|O0qB!OeX&CZ))(?KWc9kER_5Ta}_AJ<{%uq2o3Ff0Kq%3}oh zTja%XBz|3Ye_>e}^}|rQ-c;90V+2}ubturLgq%)0ZCkl+!|7+vU$<$~%vrO_YHHZY zgxl{dt*$DstDSM|F`EjupE&R26>Ha$7i*iF3G?TCUdBR_TY#M%EKjDte=w8B_WxiT z%%_h&_Ba>P9S+o3im`bgibPsRzUAF*Z#K9K!_1*nj?FM}4@HNtiJNPhsZ`W+ zDnysd?CMPYE+~mQKy`Nv9FWb$3p#MHz7+N~y`weAgmKHqWt!oCBP__O zKL^)gGoCJ_w3$B;2MCWTJ)E*+X2`_wENnd%${SXbK||G9&J1!w3Wuc7VPv*UQo3a_ zJ|nh)dXH3^h|e0~QP+KZ?|g8!Wt}x%&%Iz zwzRTJ8DkpT+PEOo(AFmArCxJQS9ec;|3E68$z%I}j1A`V&!7C=GZB^sV;eKtT&<<3 z>YhwB)SgD(wWruMw-Kt`5B@H?!H=P=DzmvpkCRY$3IJ+i9_lW*I^7+~(v>9cAYd17 z0l?=7pEb&(PTU8~6_$ELl^m2QxbPB5PS~FCE+p*4fjA@4GLo3!CpbDKOf3hw$&?u< zo-?|rAW^q)+Z0+~5;@bBj|Cidoe8wwxo8FP5`F{NW%z(TjV+W}BO48=E@rTRx(&%< ztp+$G#S)V-!wo=-6STD>s25}#_}h86X$(%>%YZ>n8Dog585b#|!@_<6?>e0T$m3An z2^zybWS|Ym5az5tiIc}tXx5UHUt|^~vpd?Zu9;FW7Zg1xo$Xwu>Dxb6-`rMETvAe5 zSZy}r4rX-7NZ`Gw^b zE7z_&{-hJO6_?CC;rOzeTJmuM>D5immo2=is-dBdnJ2lghVShJ+q-)D2L{vWJa7MZ z+hD%@^7$8kpUmDQeJ@yDaaHA1zi9i1gzIQQ+w2(C1KqU1;!Ree5=7Qi@0EuH)Kwj1 zUje03D9b2gj3Ct$8r~JnmIyC-?}W0r7&I8NXs=FgqqnjqO$Ev`zCjQY5Ok_ISm)Q0 z4uH)th`UiPO-S9<5^1P9Ho6m;fJPmUu%A(DnNU>Zdg=g$%B#2Yr;dlZ+wrXQz+}x> z8{ho-c-GKc!cfFBPs?}!->AT%-lb5?>`_u3N&Hf}=hV%FbT6upsU{Rl!xO}1C3{y? zA6g$#Y5~^a1$swd6BEcKi=}iRa{m z3m05+#gZjgEM9!_X{S~0`02(@+)N!&=48?H2*hyR#c$4N&O*VQTWi3TbEtJ4gwSe; z17;ZbI>&I1-j)<+v{1u2r!>rHFqfxE*q3A;qo0x{G;|YQozM_UqHWsT5ufPDJ0-!A=^h+g9Ql7TvKw$AR71F zU&wVZ97FT~Rk{swOL7n5p;!Q_M9;CG!!BNY1pubDDW4j)?0=(={T zD@{i1!Yva$IBs2i?cZ)^>Fbp&90tV*u!tCf+m-e8n~RD!Z7-O1%#1C?rN_>ixuv*- zk53}|mNuY(|K(Ff7{-E=iS@xyhpW>vOZI3-ZPDeLSV6Rh18>m zXP|xE!A#q5D&pE4{S@|K%b7$X6ztJT_YI7a|PPA|E`Sd3flz;N2rkEW#&2D z!jH^^Mr9L%v)b8Z(JP(^N67qf`hkntGQ>cyRmO--0DefV@PLItPohm(z22PRYlz+iIG`x zbwLq1L`T$%s;)|LeuC3-P%wqC4+^r#(5^91@ok5j#^Yuc(gyZ&2uF}J+c+@>W~z%t zA(3O^ykzMKWY@u#7-(zH!Jbnmku$zd-e@Qd-(0y^T>$66lOkS<}s zdalOgtZfJ~uG!vYMvWP&P9kS{w0#S82jF$VZ%QnVdCz(qQA5BIscsqc9!mowr5Xf) zKBzPCl)UdwHsDFgH6T*bfOJ^W1(+|a?^5{*Lerze1a@9Ib>cGPi*_EVz9epFS5_Gc z^5MvLfAHh&MMXtrWjfB0`eAmdDb*C-ckjMz;Z zRtkwoS$WQcM*uN2b`7B>*h+jB04sU2J^&&-*K+_YXOZhNfvUHL{?Eh{br&!pR3quz zlwuJ*Eh2w5Su*r`0ott8m!dL(=bpmBKLZ+U^v}kbJQiA6a$#IWRTqa&NZT(r(vJHD z5#R^l77~iR}p{s>fLrOdJ>;m5JT$960cgzt}Stj_w-`wd~x@?d!BJ zsj;!Xt(970=&b5pvgfp;p>0QHL*voM9kZpd_?Vf;U9tG8hV~t$H8q5jS2Q+|!=<9sA|oD*BnJ(4^9Gy@hsTWsFB|*$S6V{O;TXjb<&s_I3QqC zo#67K>IBLYa3MXO5b}j4w}|vg_(Jtl2N`Ly7{hhaVE>C z#3H{q2t~022Ta`xMbmJ&wsu!W1%~5j0z7@y=%vyD@@d)V1Y-))$~JGg=sIC##fj?2 zpsCEHVcM8-Hin{DhvE5<%nZZYjwrAPRXB_^!vq}nyFdKtvNdZqZ7=xFKYX{SqGEe# zX+fDVI?_p|(!1WwE2kYDh2@nOU4HrY(y}Sjj@nvWa?yeX+e(TXcC^)#y{+}^3(hBq zeaRJ9%sb=ss)qU%YgUts5YFG&wqt8yAtCu2w{NEnO~u8f)m0Vsb#zgvu4y1Eh=>T| zvpIIP?(FEe=9(LB*qg`p|C{a0FTZ^8rB{;Ko229-W4kcCYb(2Syr|SZ9mxeeGqMJ% z170j+QHc3;^q5J8hCagucE5Z=XmO#y>%x$8T^JRDykz(st{o_?yISs6fGKfoB9g%F zM*#k|2OA@*z0||r9efbM>>4)s(^otojNS!qLtXU5sO~_B*6mlwD&tJz?a_|SxG>Li zImp2`BT(`1it3;@HfOo0ISc+OA7^{qzYz>8_GT|Y*hP)8hA{@1C;7>GW;amCp%XG~ z`9!|U9AFLanXtF5)r=1I2{Z_C)4OZt2J4wkoT9T=f;x);d2a+ukENkWh7Vd283IgT z7elKVV+UD|8raFx{sUv%N=j$XopaUl6|2^--%?n#y{xRTqP()9fdF*_OXy|1x}E34 z5E@_G+Iq#3C8y1wzqO!f=B$}z)zu9<+UuHI2(~XW;FE2yzwzdwo9?h>F_ba(G(AR9FlMu-4yu)5FF5BGI%hEL z$0K`8c#oU$;NWS_m`P+5J)w6|iR6lJt02b+gMCL5Z>7)3gPewX>^9`Gv(jpKQ5BMQ zSdN79hyz(JdxdKthS9~rOqe5HRQhckkCzh2EKp9-5bc03MOTjF^HsG}Vlw@Ci5$$I z@oM|#QYC+bZkUn@W5$0A=z%xmclCCy3?w%%?wUByWuFj2b?KH@;KKm72gn+l80J^z9urW|qV{4+Le+qS)=q`an@86Der(iit7 z5<1P=MLSME^PB6oZ$JC|^G-kWOoGPCSFf&bX>Dk4uivqQAoj5{kK0mEFm?LWm220O z*VdI(R*~zF<$!#A{#j>Ta^)3QEnj}dS>LQ~Xsl^!B5OoRRrQwQl69N55Wp{~tgL65 z?F8Nls!MFY=DO?mba(d>Z2#nwPx2V<-QIcky*uu{&n8F?+DjeLSejK1c90d2QwS*% zS7hF!NFKnmmA0aUIF?8JfobNM(SAXEdg`1S}xJlLS5 z;GIeFIRlX#lcgixj_Lw&gWH1&rh;5?E0Hx2PlK>r6wLNjji~e{!b#|N878y8C?P(s zuEVb!ksu#U9)e2@lJ`|oWdbTlioJsZt5_7o2P1NgU}sJ^Sis>L5tQP2yA%4Si=$XG zNVy%v|NT3mlv5}i^OSTUX$S47svAqq0o24>;=c{DB1Loz$cof6o)Fux0?Kdz# z6ax+%Ez4w;XamjdaMDLe7gf^={KxeKRcdY&$zwuYXN*0rG<__VtXAmE7HnoC=otm2rE^a>etT&tL3^?^)U~#qIB#BIN$GL3 zW?r^%;nu>!RqNK)wYD_0@2G8QS+s2Vg3B&jwQl{1C!bVSO~0B6?^Jc?d;9L)*Ijo* zcTcb5L_hxc<2;fZHkf z63OChrUspq#PHnZZA!ukLtlyi?1t{8D^_hSDxP=BNd%1vmtMMR<*Yfg&N=_Q%BChB z9l+Ap>CUAXg4Od*Kdqp=;>f8-ZP>D)e?7A#-0X6^}d z%WG>Z>ge31>Xw$Rg++zsmD6TS+geaWnEBdGo0@iY)V4I&x3w-_xoT@^*%@b@b-~3K zt=zEjqDwC!WS(4&^`-9Qz)lv9j%%*@^>x>Gb@y1d^U+5i$PRwn6qQnOfB~RtEfSh1G}3sn&?rxB@$b5p6aI#>C&fx-XaGZ(KViP zID#e?KOdtLM;8%n+082dOhog4sAfz!ShR^?1ml3_rf5M6G2x#d= zNeGDln+iWnDt3%kT>bila!XQMlq_UJcvqJ-V&0W36V~&Xa-NpetOKqSR$~W&%?9Kc zfCeQf1OaZZtnbqFo(-F;fDWkP7Yu@UN$Iyw$%?8HVNym=dCLOV_Tw4;8f}+hu z#fw+0m^pV&SxxQS6HX|utZLtVHRtv;F{ZL|=A2pQUwqN_l9J08UdhX^WM8{!^J(+v zuiQk){Pe=IvJG3eQh~j-wYsUPvc7)y?Afa}Y&iX!^RHOAkP!H?+8XMCY-wTbOVs7g zm6@HpcmL{F*L8Mvhb`-a4?f7F`sbg2@$@s##}YX)>P`(XWqNqXN!o@gt{PF}$SuPi zkB%ya#x)_A`l^VR@y3FA=dwYqLwEWEuM4s|>s4UF7?}a6JEY%=nQOWpF=XvHBJ+Y& z`{ZjGlDHDvC$y`O2^~sQM@3S@JPDlSdc8A7%CK4?tfawMQy)F{mv{obSE=-cj znPpt27KU+9yirb7ElU8LvmpVqI@3(?_6Q4MQ@zGM@(v!!3Wapp3`Or6Kooph`rD0k zvJ9Tz1?6zu?Ft zkC-?AjP(WEkDYnkNvF=+R$M&&=ox36d1eh2WZJpFUe`(`_jzZ0^QsjqXz}!nGa6dk zDr#yeyKdW2R$Wt4Q+?F*sq43IpEYOp;^oT;6xTF26QJHyP`I_Ee(pOV1d&f%T!Z5|<8Qu#*0OEcM44Noy z{LfZmJ9H;%9X&OH| zLWty`j(G@~+b8KlRmMerk%*w*6N;Cjtb_Oj4n5FIj00`zLR2}Vd^>Q_fv9f$6&Ua* z^cT_N3B2NHr5!*k^2ShB@1hr#@g5$l6#->1Cb58;_N#_e%n*NMS#(9If6%P;}M7?VcB{_xyA3pPN>daDd2OA9-V zXl~M7sG?Izg$&Sllfn;Ut8f@MWVCw!r?zn{VB8%bi?xv1M)m&cel0kUSjQ7owqxu6j%T0$xDSq85;|sthWF zR&uye6x@Bsupkpt`CSUWhNC%m*3*(gsQx*~mY5-c|-n7Nztj*CUNfiTwC&H2poQ{Kq9sGJ(c6%j!kpUhyN z0h}MMBS6@RXTu)9jn-2ef`$Lf*HpiQ&?Gb0+REU!3f`ZTf}ELpi?`RY}*t!;H}t+lPKOINPEa`9Em zSFM_L{G6hSiiL|8SJcvW*NXbOEro?MXU{4sFRx>eP98b7ll{Bj``&fe-*Cg8y+gzM z-gx7UuOX_x_lNgyzw3U7D=ch%_eW1klHzk#4@!=saS{%MdYJd+qM_BsL_EAk zm~M6l$8(90-dNW5NbAsr?!_zac;s{)<~PDhtK`Nxi0!sfay9Ceo;s!joZiTk7*||f z(|B%QQTPue5$6-tLxgEYR>NlH-=e=y?(Pr zJn`~zbNC3HBmyHVp)wDSGa!Q4YrM?BN!(c8K_T!WkqkTSA*xIEt|nP0gv-$uHW;a{ zYr4+dkBOgM*I80obHq3P$Bd(=FJ8G~@$wZ@r%#(V|BMY=w;eI{$jcWkTC;J>%;V>5 zEh!~{Of{M2=GB`vUAc70@-=G-_!n2#EV%U2lIog<9c_*6I|%I0oHK{8ZbI6>dG=Y= zjZNg3aPr#Lma^Kq&4oqNk2!kdwrx|7p1x}1MuN|k^$i5uHx?9>*VLSP`so*5vVida z^Ugo7qOPvGv9YS5k-W8F;lh>c))8zkEH7sZL=(mK=4SHP(AxTwpZ?>oetjJQ_X7t< zUU}t}uNA6)^wGx;JoH!urUZ!Dc4=SrTXnlDVE4wnsJf~X_h;|w{{4pwIXOMsBVycYI;Q--%a=lCeAAAamA!1E| zx(&FvURgjllP&~kMTMIf4>4Yyg)4$0?O31D>|MEo49ler3a`k(36v{{oNDFL|9S~g zW@UJV;%HDf3|6J zZY0aZ3bGs=J-x8B^qdPWD5|QeZf>b*ZmFnmIBxdr4ciNjn=|L~E3YJ6ov`%krlyjr zsT$NKN z36=ztKGYyT9eog&ZLO{`2a30>W{kTAJB~DY)##*4sIE~+m2ot1*b^9y%I)i_DT#Yv zv>(P6jz_M;^bLeThFS_h9g1v-e*Aet4*xu5*VcWKo=AE*wn5+m# zZ7SGK2suIKhPJlCii*mHhI7t8|C|fXC+CxMN^7d?+FC0b8j7lG7A;-6rHID4uiv`u zn`fT6Zu4exeFE%Njg8+t?_9DXoO|JgXP$e`=7NGn%a#%{U(?t~QN5{&98}fU5uE?Q zkA6&m{qDQ(e(I^Go_p@OuRN-M@x>RF5#RzMcMXi5qSMde!r{Gm%k z+q@Z_j>J77021NV`8M#zD^-U%#u*Hz1j3_LAfe4Orbi`_Q{um&x&!{4HSa-S2~~;h zZq|W+OG1zK5cZg)LVMA;#DA)TRTLNkVB9YN-^+yKl}(Ir10AF@;f-8C=AQ&wN+iPP z09Knplzx2&IT(PiMm2#1n~X7l6-@ESVHZu#M#@YU^jqa@&zNtqxWqlQACzCY2h}Xa zy1E%k4t~|;)G(OGDiR$fu(Ju*EF6XayCbxha3pR;NT^DpR+6@TTX+1)C$HJKiH5ot6;(Afkh_4&hQ9(~Nw z%T}*Gf5Cz)7cHu3ZYB#vc})$ua!peclWQ8P8tQ8s8-Mn*pWl4*%@05P@Z*m^PT>8k zY=imZA76R(_3Q*4pW(#J>7ovpZD*q--i&P|tH&f`$MhRy>Usuq_{cjs|7xrpBCpyW zZRlpl^FVdikL19@bDls2P~b41fQ?K3=0+2xCtxX)E7cKbp~RYVG-)mw5ebhr7rNOM zqLPHuI|vG!6AAWIVR5&=%*k=$6LLZyG_LD~%)+C?)evnw-%$PkTTV?} zQu+2q@S{Z9EN)hk0|aBhr6b0gU~D%doz0#pA-u<>C5xY{`n{M@>EIjI+;LzirzQ zM@?D0awWm`I9p~)?+s{1zJObuhi;Bt#g>EAJnP7X%v9o6_ zUA5}+MGMb7`z-Rbwz;Xkt+l$jdHt5HRHdJG)P}8FPdxb~@Z;~u@+tC>nR92aTEBVvjOm2uZ!0d|R#IG9U%#ce_>#*m zFRCc7tg9nW*<;<#UAsm{N0Z6qEw|kA;DZl7@x&8fRbcClz0^S`E+i2-r_l!p>&!XN{oC9OU47#3!rW)mh zRG_W6x{sSZ?$ezLPm8h$U$rjql_DzT2rloaej)+*Y&Y>uo5K$&HC~GL>_$V17*RuS z5%4=9ZSZ1`B(T~eZ!tVK7l#0^W))Iwr&m_?NJ7U5D7`3x9QE2uA5r%RK!k}HqL7Ck z+n~2dcW+^frdf%Ot7u9*eF@}hqS3VSAIFkHJuNP%e*|2Qz%qUoOD<@7IG(tah10q% z5Qbn5>~qmIQKDKR=go?@;DlL^krJkvDLjV>1~8G#0>iRZPA?mroeV`p>Q|U>^=Lxm z^m0SHB?R_;W1$sm*3F$eclnz27cN*ZWy+B!%{!%_xMc3}bLY)JV^eX-H>Mo9XvK=f zD^|`q@%T-JMMqAXdKu;I>*t(!!j_WKBc>d2*7@gEH#Ko1VhxqMTPy17r_7j2uzlU8 zO)EF7Z(z>z`nI;!>o=T!<~P@G-FDQpDO(B)w-gr^S5*>hFRZL8tE-)R;t7{7T)5!! z%g;Rj-0DUqurxGmFD+ZWVZ*BR8;(Bq7_u&qU$t@DwkiVSwYB8wv9pewfA-niOG+wg zYAR}LD{Je%bM3Xi`qi)Y@89pb?(MhV{>USbd?m5{5AT0)*S!zg)Y+J|qZtYBStFQN zH9{J5E@%i$ROW-p*%_9r2j^)!cMMn-@t_39lP3Vj;h8wkKnBP`^vYlsbH>JKj8Yk0 z)3}ID8WVt@Pbk9g=XeJ~cU;RU;6>A*V))g)IPdj`GvVE|k+ZdcLUaVcrq+2}kBDTN z%)Jgt!SEGDR}Hoi;CL~9A=Sgy=V;|#WomNf)d53gQ zG4OV3w3oISZ}>o1(hnoC(=i;aDpwO2c%YU7{g&z}OUscn{*db)Rc~Pmr8nguq_Tw# zyAHZ>5HIQr>QXNn3j!u_@Q_|QK7-HH;K5%ZFfWNu(+D~7|L=c&|Kxe|rW|#|yffyn z-?C-q%;RRwp1rA{;M@x?IPuhZn~O`1IO@oS%a;@CK5OorEk(sg&6s}q;;UA!-!S*2 z6SkI?e&fh*oOkg>HB9R!z|JRAm(|o9HGL`p;ig@?Yg*{g4YGU`S5#cIV8O|!ow}u{ z=#*1WEvc@qX>O`&YAmU#nR)zNdgbX;uUxWZ{no9k)~~B>Y^-dcmY7Q}zvA4BF1%{R za&ntcP*z4(gwm?2vg+z9mMl5)h;Mx3i2p%uE(o@lRaFtv{_XF4=O;h;Nmo}_C=|N+ z=9}-o|NciGef06iAO9+$`X`@!`tT!iK>^m)`Ukhz14c~u1`~AE#p@D9+>f7Pf%sY$Z=sf2+_qoq4^R+lWQ?@L| z9tjPEsWD-c`lZ`x{8BRs#$?}(EPZNejk?m3Hj6=P+u>GZx&SeJGeo)5(6YZ0c-%&Y z$V8PApb>jR(PNw>kT9XNRAUfxj{7BMMlxU>>a`T_6-{7$!|Xo^BNYf!WyP5_^~S(P zNBR&NwPLkMuVl=?inEeMU>RVcJ zvX&MU6#|4FICQ9Bc~P6yx^?^Zjkn#}ZntOWU4ZHXw8`{PRaMW>(BM7y^igXfu)jAogs5famT#P~K^^Z@TrCE!*z`>b`UDUZ=OuJuqN# zxi@d$p1pKQ){>j@@^bFHYnzo|d+*!syYId4eeWke@rf^g`OAq!Vs>`+^5x6_o3Q;? zzxvl#Uwth=wGM{roUV&Na-O~w(8p>hJ|CC!rhS?>=8gK2bUzGI#SJuF&XhBQyEt(r z3tQPWZWfdtm;{c`MP8Q#rtT)8gCil;Rk%)q@_R9u<7Og%raCDK=1r&22~!P}itQT4 zN?(e8CBpVFH7fjVACS@M`3cdxtR^>!*j$kp_1)WMDBy2^n~F*yo^&Q6u_0=(Olg|4%CNr3H| zgPn}PqrBZ8{-gIkzHH@+irU)Jeft30_m-E}H@5(`w{}~%@7lBRwp-vND=!BwsBLUo zTU^}faOM{k(Bah0YfFkdZT9Tk?46~10jT?ihCcf7j{zqqQSEmh8@cCRpzH3T;T@%= zR+lFyFT0_oWnV=_byEYO>mx_tDHXMK+jj2)%r7h|>~^{8ni?Iwy}ctNwqCEjx3_Tl zvbv_Gl8x)j4ju%wclCN<;b`gXDqdfbSCE&R1Mi%*a`npH`^uai&++5OAAb1ZC!c)s zx#ymXMx)cy)ARH5|7)=Q_1Ay>?eBaqGBL#prd;mUbr?QQPLxw62usyn_H~*ESZDG^ z3YR;*jVQzLSO`y-j%x}GeHKx7@hp2h_Q;e#g;K)IEuXkeN!2~ML0yqsE}JJ+y_G;Z zI}{oAhm^*SQQep3_v6e<#OQDdXAFFmanY~KAbs>$h&{IjzC`*REPZ{NDL z#Y!-I_x}C0jg9%sidwq6x9!}y;g*}*ZG^WUtf{GPXjoIc7KnO2@b*K82yb5xQ14ip zy>!Rk-QJOr!6Qc=|Ii0JY*vcx)UtT=$l=!3;tlI9Ry(W+z|RMd-Oc)sV5ea9^xSgC z9q`tTZEd%2zSBXR?MHiuhP&*JTkqW5)Y+L^kYC^2ym#L|c%o;Z-_zd@B!A;An~FEC zU%6`Ks@1F3u3NheNW0Z~?AWn~9(w3wAN$yszVxMuiHURP&dtosEG#TsxpL)y0k;3( zhd)V8T~G|13+yq!7#=hx^md8u$}Pj`eT*`31lh3B8>L21Jvi^*Gag{LkL6? zX|BtJuC$x?L4FD8sM||@D&6bu*F7`lZZFgyWb%<}t-E0ro5TJEeYy&#$~|Gt=c9(L zV*pQ!{PksOG{#$oF;f(qNm0RUU#R!evW~6qW76v$GP`KTw3)DzrYM6^lpbaRb~+9< za+*)UL*q@+yrh#p0_i8n0PE1RUp#T-p0`O4+jjuA6W*Smd#JXyvZfY@Iy@!6sBqt*3ZU`p)|YhJ9a-5~JAk)SkIJKe`aYZ6 z4ba_x}N0utwA@==k;B4SvAX(Kkoi)f%N_J*=2bWF1DH;V5-Mqm98Svh1>pkl~8%@bwk zDuLb5ZRAq=HV`;tR?Mu1@*zVYgP{Yv!R?5Mu7}KRO1M48Flj7UEsrG7d_DD}1>~Fy z%`=}sNo8tVfir{+#bXuq_2KnPnqkb1PTb`v{XD`sslo)1fFsSBN*h-sUzu}~c;PT* z@Ay=%X1XC0uM2ULCr9rKi0cF%O`aA1Sa=*QUZ?oX5w%-PXqpVplR@pG*q6?Bqv-?t z_=Fea;nW?B>Q=g6sBA89J7OLe!rvW>LSfl96(2(*<7JYh%xu?yooF)S%nu_Arf@r^ zPp@X7jwh%N^W-Q0PlwfJaX0~EJwwA~2g^6!dJC}Vo3fVf-oLN5sX4E(0I>b8UAq}? z2W&rBU0qdIM@)})VBm!SZb6a0r3VilZf+@FzaD7(lBG*_mX`Jm4ZZc9@9aN*ymxrm z*4yhH9w}H>2rEMAf$}Xowz~%h2ag@^KXSy;>#eA+h8NGt&uM6HzvHfLRSk#T0|Nl; za1FeBX~n@k`wze?TU^dVb+yjkUUz@LtFI5R-ObI&47c9tuUpomz%K#^Nk#o5eLv4ERLiPWaQBSmjBE znyFl6TLDnRD8N zk+}FR#Z8U3QhUKveAN8Pu?$C8xnk1y5kiNF;n*1&6hmiikB`!_DQik%jQvzvlE6uZ z?Y`g_PWc{u_rrjYz>|Rn_YMvB9X(oEfB5FxZtZfomgZ#bEGw;UY|bkxXzA+OwsR+` zrCM#-`FRJcs|dCiuj_I+3ziq{J$SI8wY6m9hHjU;XvMM}d-njg1Hp!)+wCsiu-@wN zEX~cXs;}>`+gdG_z7crnsAq7nvaW8!&711m+6#*E+qx}|KBB9`{S9sHcCUBs`r=)s zrF+ZEx9!~F@OpcO2H+N!11GudwR=2Phr?>M_VkcQgSWr^?eBTddp`d0kAL9{UkHc8 zsZ@#qJ1}+z?ANbffBEH?zw(u@eB&G6_@6XBByQxys*53mT!ghO1FEM@J2C~;GWsMZ3Sq3)sIp0x38@)&lF%Xv zU3tY>9wS1nBu4MhcnW9EC{*Ndn#7X3p>&eCp*NXgd}CHdTuYT|yn#e`E{W)I0pd{t zn8ERsLGuuduvR!=)_Uy|Mv_u~5u1(_vexibLk>=2TasWjsVyiR|GBti!g(Acsm)+Q zTPON~6F#k+E%p)NMEa;cu8>EQ>4`c>3X5SoB^o%Jz#e!srA1pE3=~sr;2|c_gbWR1 zu72*8N$)33m(X!Bl=^Vw2tRhN!h}r$^-7J2XPogw11ICBQM?%A@F+KIg4Ivu{A=2L zN*a`CA$6Q}n=%DvED%wUPE!Tg*i+VX3Rgb!>=*2wo-Vr`KoZc>J3LI?iT56=C3tJ| z^eoBA25hfsY$TdYmu1K9J?n4Y)M2wN&CRK-t*x%FC)nAlbMB5q(mGXCluF|dX-Z4FIFIg8w}xnV z*V>B&Lk@(IK7e~p1w^Z^BGhDLpu(TIuZKTT?_HH?TBegKC>}K7F&~2k=Ff+;_VR8W#6(@z(6WGub*P-9!;8; zD$_I&*&G@~c&qZ+u(MRXwN}rKCiPf`gs#iQWqm=nDkYWOoipbI9#h4cd_=1S`?Vph zdI&I5&eI%;e42^rPE4)YqyDr(BtA61RnH}eYpgyZO0FTj*HyYMSyL*{cvrJFn0;L! zIYD(eM*SkKm$Gz0*J=N$FZA9Ie5l>h-R*QbdU`yA1ARwE`e`CA2?sdbSh8s&QCG5; z?kX#*WqNy;<*r@3Hr#S^ht-x-kaw`Es-mhIP`%UcSiWlI-tq%A4UNScHZ*p2F3ny_ zHS<9-4)5sEit6e$>(=!Q4z_l7lBAcTN8Nq>uD<@F(-Y5fp_-z+o?~+>UIO9!=eKxR+kGtJaF|#9(m-6C!YA!r#|)E zbI{%woEG#TYZ;S-??|=XMzyISizVp2wjK|3M3}D@UoCzRPc~$$T zR9ZOf8z@#w;D1cx;ljkizBL4|mf&oJ<9>|Q5mOjr8n&n5JWnq{GP{YQYvvY>u}fgr z+%KYznUJhrX0{jt`DFvC3<@&@H&!P?1Hm<4-iwNus*%>6WQbwY8q`xls~YxIn53q7 zNEt^IG?S{}8{&RQLvAkg3Z^vGNKFPacEc>K@PdNe%gDvZki+#N87il^!Rifqd(|4G zA4)&LwsvLRmlH{p=O-bfBXx(Q0(mWsIlUhi4_6JT2B3&hSO6% zY!IFj^Ass*(hD_BWA@TM_3jvNjpD&51=$)IH2f~oUC2@${JeR@{04l-P9+u*WEt=uMF@G^d1%k(p7r* zG4GM17LVuV+i&Z1II{AxYZ@A=YwH@?+5p=AimRxAgq?*MY{ z@z{HSrT5r+daN!tpnA8Hpt`fS=WX}h_t;~Pee|Or{qsNn^Dlq-%fVo9a&j`2N-my1D}Gus9FL6t?q+;(jrxND_N4 zyff2ySSBdO5U-YnPVtcFLN&ssDRrnYiVbh#Vwt{TUKh~BQpvr8Q4DU%1rdB+rNp7gZAdKvMmQ7g*VDa>sFWr$Db*r+D-!^$ z%nN>-lty=UU^xXlt~F_!6tSJ5n~3q09u#lhn3yUxIDY_l-KM8as%U6|;W!pR&YUt6^^o}~YR(7_ z@G;GhV&RkFxIfeMz%f&cQ&?H$m6opO#gmsP*&Tq5wjK}g zvuDGtH@91@!~;odsleOYZMOVnMZ5Ry18iTrzNDqwx@751TXt;k9UAT#9P$p2cm@W5 zWA}}Wz}q={`)V7TR+E%~?xK~;+Pk{}@ZAH1wC^Y_ZMAmay7|sqZoj>;y<^*syKHWc z%i9OQZttN)ouImt0eeqh-@6}r=mQ`4z*A2>_1VvU_T` z9&7B9u>-LG_{Tr~o4@&+-%nKkyZ`(57iJeps0*8O7v#4p=0z&)QkfA`GZ2B77s%`5 z0_w@L2u-Dooe3R&A+|`tnZ2eVZxO(n$F6CJjW1vZNM06HV@c6;X@6KEFlr+W;g6x0 z8nHPfgWSR2$j>$TB!WJ@#u`CU?P0;s_2MSaoQWp%JlnXDCefhJ5D!EZVV3khpt0x# zvWTlag{1Bny-lLGIanC!?YavH$u(hZc!zw!U^IoJSGbfE(JRgotrJ!*h-SvFx%3k< z`b;yWYyyl0Y%i~> z1nRze-P(4Wy>R7{e6a{HFeRkgJw_-lQM zohCiH`ulr_NncVoO?|IzYT9(`tvmMYbq@?MT^$af>+mQXR&n$V4L$VGLm&Fkhn{}= z>F1w+-skf%f&I*xGXU(;?g)$>fc=$MUIAbS#{Qk}eCG#0_yGg<-@}=DKmWx)E?#-j zPcWPuW9Yyj?+a-$?2_0s_RIW`GQ5jHI$XfRSOjSoK+TiB{6Zne$%keho^fWhaNHTn z+!&M5xJ+X=bP_9zstCF@)kR9~2;`Mv!=$>H(os~45Etqdx|-B`e>n33fp|4?4C?Z` zOo`-Kkr6G4MHXA-L$V6&=TeeZJoQU#56RDCCfj^z&|6cb-Xe1*r60yLiOH{c%TyHNs@nojp4_Ek0Yr>I zngWlymgEt~(hWNih^jeTl+O?kj}~hI#(5D1An}%56C`4C%*5mk%mYQ_7Y7jRxL_Vg z-KLVB<*3S(nVO9JdIc6s!9t(WJ`es8q>a#TDubd(c1`XO-KpA&Ly(-U1!ylIUXX21 zh~b34SCTi(BFRPP!yxN7_ahY(h_FO71&4|&&%ee(jXpeJ;7#VGhnBG-4mm{DT!ELbTdrIti!tjMwiXyWN%!g>uzGsB-5yvV))ud;X>KZ7vAnsX!!tN&@9Aa!M&^Wpk4+AT z0~ou@<2iQh*uxJ$%o?5siQwbx$z<~P3yj2(deM?d5^-EV4QSrNxU{BYsOKh-aDopu6%D5W*>LE%i@2bFgWRhoKD{I#DGslgHHq_g+r(hif$h4nCCEYjh&+ECD zh8~i}!h1QAM-ytwlAdob1JGn(qbz*Lf+-&1O8zt?n9I&k;aW8Df1LfU4@FguN3%+! zVY`T4R|Bjk<%xTCHxkv%k+fJPcqC z=nZ&2bnI9kQA-G<_tPvdM&055ruKH?OSIdwa0&K55+;CIYO?wX)3?y9=_<*Qc$p08Z9s;#@*J2K)K z90FE<>z#MjG&Jtmvv>WbjU6_7*}-!7kPfdGz@Hri*d0!C0Jhuho}Qk!zV)qt@+W`t z=}&+9)TvVw6BANh2f7Zxjw1yauz%}Y-}>%%zbmDfpZ)A-4A_71i(mYA+hG3R_kZ}~ ziTD{!S`Q*=okRMh2Jfh@s@oJ}W12oA<@ZVMDo3)sZd_62QB&2Dode@ydbk`UDprbE zy1?!iZg#O8Bn)JI@hj3EPYb-&o7_=;FY2RLoRHB%TsPDW>SzO2y2OHp(`Dt}8Cjfm?}vb;}kDC2#&BJkEP!p(Sk zq?nhDDymXlSDElU2NmbBE1*`WJ}Saw3~g*Hn#Y&9%LxzEGdUYINY^3-f_%gV(P7{M z?s5z=@A|00hb2i7Mw(&hVC(QxpZ<)+X76@593D^4&;S!*7+oJCJ)uVjjO!eXo>)UL$?7W=qd-nok&nwKYZ)@AWdw21M4TQJn=N_m$bf~^|)tc3<-PVF- zMSJ(}uWV=leqLFB7}!31>lqrpee2e;^74HL53VU8Ap8@`3zU zR_@xjZ^!Ok4%%(XAl>FBjGb8=*3&4A_~2eSUtP z0lTc6GGPDS_rCYTAN~+aF$~!M>7V}TzY*Af`nP{~?!ugpV>q=qhGR-m$67if?aF7U znvB%kI%GH!P5T9{NF7aLay}M9&8nFe7oLG229#iU=co%I--fpvz;nx)v6*V<0R;}!?*>1i4_S)v=gH)5LqMFQ}{riBo=jG?_E-S07uisr- zO3J1~LxAnT^8xA`+uD}qWL4JH0-x`&b~}1|>=e&!ZnupVObMjB2(UYx&XJLkcfIRf zANj~fSfV2mKp$Ov;eDy3aebX6)<6g?C(^qF*K*;AdP$d^z&eV!4XK!kmg_;mtm z-cSMy_)NDk(i&t;mPOoZgpBTSytP-pN3_8YsC6Np0jR^8l|?Bk5nU>YBHdU>%^7@> zT01K5n#ZM85l4_rM>8y>U@Hr|KZtruabXmX_BO)Uc#}jTl|pj5jxd-_;fa2XNQ>1| zxq8@Qlws0SSYPQ-pRA$jSNgIW;$&OuGgvCeza{x=mvQk18u?_JJfaKfrpems#L$f^ zQaqQb@9Z}}7E-QwbBAfj+*_LFV2`7!D;}t-atua;lRo5T9~J8QslfPYt@AXBwe(SR zt72hj^g8?YFQ0qC(>G{wIDi1NZd1Y730;SS2``koAK`+`(Yr}hq@?DKj^Yg^ ztyU|;_PW;Ayn_6?mX^DA?<(22q0I`|p0~f^;Gw#@<*Qaw`8|JESy_2aEqq(o)B>P= zpt2GecvenUc~vDqy1lp8H89X-wYFNj%d2ZvtXb92*0y5x%2rDkpuMx#OVo7=>{bHl z0PGGp=_VTv&%O8F`=0l_=M$g!#EBCpm=1%>rY3=%RZhS2o$p9s|LISE`gec#cP3!} z8$4Q@_6{F8QRjP|hi45W}nG69kLV-a& zr^2`{=WEcA-ViIBj-s-uX>RoiO4m>M!%sZaXL>sv z#3XZ+Fm{IXtgZ^Tt({%#N{ZWnw`XSow%0T@0dEIpzN@qpu$^Z7=IlRIQQg$MYTX)u z`hsOeyY`hGtgQnY-_q3uw~Za0?!m#;#p_zTExm(-B;BijVAGvBYjDPu@h`(z)m5ZcpdHb{{H@VyyG43d*AzH@Rt%TSu`#=8UKQdtdmw)+}|I+apUwthY0r-_LK8Z$APb$e>v=p&#F_Lro&D@MZ zbPrkrjIb~q3XR>+3Yth}LDft@x&Xh9C~GRkM$I15=G?`M^!6XrIx4ky)9^dx%?P80 z(@2I8Em6|NSeMYPfD*^z0RiIyoGqq{DyDOPByKXjgvL`+k>H?%mN8xiFKSYn!wwv_7fAmXmuoba zWui&VX3xAXAuYI!r^iPVCWtmAz2m4!v7Vw?v8Gn0P+SYo7jvL|5iw9(o8p(=&6>c| z@i@arDKVxz8IuUFb(;nzB(RI1m~kHM$Yz@oR1Y#aU2{3&nyD}N!l?1wiLvANJ8y&%y)j3Rl6FxF{#27WMiuzG+qx`kiq~~IU4ZSt)$5vD3YQlF zZ{NOq_nMO8cB?J7Ag`>voYYd+u5Pk)=NA?3EGw(1t1n!>tlQbwv|Gi}F@Wp`rSHJqze^GA0cfUU#n_`xAe@G!Y^E_+L?(W&H2^9M$18%+H{#j_cr6IWBqnDJ zfy5C3T8E}SVA_wJGnfG)k}nY^kfwf1KJQmQyUL$QBk)PIj>L^OQ1V&aRzT<^K_ou= z(OQF0lwT=R83Te#YgbBUt}g^qY)OMn`gSx}%rLDEg0cHezI|G6WGBmTJ zkEi^~x1Z$rtgnm|)swie>rZPIFs*b134=^sNlJgCUrYGWW?C7MOtHW?d`z1E1;!fE zPQ$JYYfgTtkaOK8qOTo%$w(me#%ya;IgO#o3=e5f!P0t6KanGoCQb{k&VilZ;%X@Y zb}~?7l%%hJ>N9_3aky+QpzFP^{(kSs2+>{`r1J{tJw%o{O3s0|GuZDxaqMHCHGSiW?#j@imGaW`eus-c>9jh zy_JU>0NY!;yMeJg`+%tTy9P*XV@qe(^3^NhMY3~q57tyWy?xy-myMu0>q~NXv$Cm! z=r926F1P#Md+&YZkw^aQ&;IPhi4&8PlTwF~Mn@JAV{)*YDyIzCfBy5IGscdA{l5U) zfBfUWPEMVt()zf7?g?#mGo0K@qS(eghjoscG*A`itC&PK^gRg_aGt}EMdtjw6; zPIEto6el<3s0etEu?vFORi4(SYDizSw4;aA9syS;apDTL(*)33U=~%vnvg=Z5gi+& z@-5MMc(AG6MEqPY4Zk|xxP3;f*B$ncPTNUkX{b;V>jksE~IxQW24oCFT< zQEX+@I-xL;#{NU}f;27?H6^i1sNC%6zhToaGpU3!@x$WO`hc?ih*d021mgxv+07&y zmsmfPIkW+pWJIE-{PD#tZ(K6OxF|e~8_lat$k*2>y5_XhMzzY^8$KTd4HQd9cr}|t zPU}O70n+X$+mxsoWQ1E?s>u-2PLOV1230mhPhE%XXBO9;~S?T)w=;VgX=xc>4gus}48R zHa5a#%T}yt?Y6F7yQa0Pi>T{7M!-XX-QDG&83-lpZ>*P{Dt4| z2fBXd%o&-%&W7Siy3UM_SYVf4$2S6YhVB3QumAd=of|M}j7tT^$9qdB#7xpjj^xVO z$PixCMg>d9)l%Mqq$KeKCfh8@B!Id^Rme<;H5Mhb41tKoS8?*Wp?eww5zU(J*C>6$ zloG@IjoM0~+ibL^S6r>*&rM=aIL_3Q$W%S8jgZww*hGau+Nw zs;oZ@cur<>5KSh3|DlQll~t?Pt|k8VWktKnh~8ebVtG?%Ct$m?ug~4zzoxi&&%S-| ztaT;DK+fIXKH_h5djQofP8YMUciHV!jd3|#u91e)F5G=k!NE`Vp&~GE2;F0QUbpY=^g6y!@gsFphkTEN)%q2CyjgNfq|O zMHO)kQrczQuHx0Yxe?{S#0??5Py(#dx&ksg1$UULC;*%!pjpMf;)9xsDSu9zrl1BuYf1~7X!YaNL|T1o&H8892i)A6uvUe+Ha+B4Oi*h@4V zrr#z)6H^&AqVyi6^ztaq2R4V#n`9GI{giAOD45?KY>&?(q;EW_XxNE?k6x^Zt<|vSvEOT2PN2>!)5vaze!R5%18j zcNpOP2mtbZ58Pi`egJ5EyUj)nFm^|NQQ@|oJDDa^+tjpk&)(vV8``^pw-*3nA0U|n zYk{a26cJ6PqOKmE)!f<1@_2!eXXPv{J+Qy7si~~uASs)AC|7s7tZp~!Hf7mg7Q5Z$ zb{{`}{Exe*JQTf;ftek#UtvEWPe%Ezo-6B6u}H0e5INu5PwTjD>KPZ$eB^ zoy39+Eh122A5__8*bgbgVJKaXo}`W!lgv(SFagfnjqo#{eePgYO#v-jRv)f!w^#re zZEkn(;2?Fm9ARb{rmGK94-CO}dO{$b$}&W0r(LMj+#w0CbM&IDam!WS^@LR4jv@fzGh8xS6AWkWjo7C%WG?wty}@v z&a`y+Y)f;q4%Sq=2ZsRdd5|NmnZhCHy3=B_!G`0$`|f-1d*A!?(@&3%j>C@I6&_FeL!6}>VXlfZ zX&r0n($h|58Ii2Z=)KA7h&<{no>xMj=1b&MJf^!=D5@(E))>1_E)d8}f_;xT5rsFR zMr83cj*W;S`IfhuYSl?xcohP;lw2fj4hbyEM0ZVoc&P&;B#$Q3eJ>JYrLN9eb%GL& zIb=-*ql$P-OeUIx2JBML$B50bJ&1lHZCRo3E;w__tQ|#lGdwcPBQYnH?#VRL#_FNp ziAL;&XrIJv99LIyK7gqJDz`S0%$u5m1Df|fkuKWnJ!Km0m+h$O?O@tSKAvMHd@r&c zRd+l}HO7=MrV2w*yj{|^7|IWi?2#1Pr4uHhg$xVpqfbAfj|zuOK-5f?x*j^E7(3}U zMZvrQ(vIX0-T$tKtxo6m9XqnJvsSKNRo~QPagebZJwt;$ef=1Lan^ZCi8@es>U$YE z%Dgem55p`ma6buPbUB~+;1kX5?Oq`8!y_Ht-JO86!^6$(odDOJPS@(SYq#y((b(2r zxV)&Qv2j;v>H19@+brF{+xHweP+nENYTeqF?rykvS6S(Ss_KH}Ma`WZ#P{MRq3d^U z-P&gDwuyvZAnHt7@3Px0ta9pb3=9lB_~3(2Jn_V{&psOn1ehO&=`c)+VZmS6!OrM< zdgau_*cqy)Gj{lT{q@)XLxBBsfoU>Q@==eH$%jxs6zXgm69Wat#QkE#0QsY)a=NIuGKVA;TA34us4>F3&JL2e zZs1H9-fjB1FP^lzd-Dr&_mq_#Zf;(>WJz9r-j=)W0=`QaIE{rFIC@k@3Xl`P_PdYu z4byfcLfVfGh-`rYT0(^b@Vwh$|L8|Q+T7OOcjPEQI*IlgBz4tBGQG60+wEDgYSq@A zJDNH=fT&j;KD?dI)NAjy=H?Th4AW!;Z!asatOB;*X0b3^BVfCGV8BAdzPgzF0toNv z>2?uIjKywux?IPO9ee1Zhn{@$$uEBKi@4#G`C+6E19Uy3gPjTN(h_3=cFEY&f&Jf) z?LYnL&(2NHjv3Sj!%>}REMwg6C@Q1@Cd*6;bd3u+ojfXvo*eTj{f-5MB}OXk%5W~c zk@9}cvZ(ro@Uvoa2?&V5Mg!?BlDeDSgGk@TJxZAdiN@q=62R5fOyjEM%PNOq*sP@l zc)>1dHo9|^h^M<5<$@JJ%v{q(v{fT1IXt`?dn3%-*##j9`?O{%MIQe7$AvO4OTZ!l zfOUXkGmmLFsp8=(bH==g=mLnWrDpKb2l-wj71UIHB^k-`uF#{@CIxHY6vI<#78>RJ zluMq7h)Ky$E_VdxWra6GXj5%IbpmM;h6}-{4nf# z@5m8%PtV)leqT#xr+1jB?!9!B1{_W89e~mR$Yc@Ou>-!%FDj_2KfGuE{$kRXYR%5e zD=jaFPqK3D>XxpqWh++zZ?CGa-?n`_8+%7ty36kA;n+@fm~NM=(`F@Vj19Pa&wcmZ z_voXKKK=C5r%#_|^OCS1#-zi@sY&SqJ2tW7&QlER65C%FU%z|M`pmB7MpMc_;{fuL3T42cPcKAnCWPIs!urSn8LsA%+CE-O5hg(t(9 zLmhG22{Jlrz{p%NL8a#>k%S`diAe6vACi4K0C5DIBdSagNGrt#MVo2>?HbT70CW4K z$@neMGL9;?W>oiU#aXq)$hXk?wsd()#S7?r4YV$(bOr2<2~DJs8&kx*u+JG){vSgx zj4BOE?~r0?#@c3NoP039zLp`E4wKpGpztUz@`^1F65(+1VeM#iR7(a<}y+}?kZAxP5Iul{wNL6S zW#~OT%)Bvh+cPx$;io=!sJhx>cL2__ifSLdt!->vMFyeTb8>SwZ{Ob3(Fwer#KP>` zU%Y;OYd6tk_8vHJsIH!6{H|QRYG+xg)#D-g@Kk{zy1Gl$OaapEb}q2PVY4wE<^v!2 zz+e95UmAvib9yDPn{*gCH3_#SVPI#B-306=js11>^}7VE|MHhFUVqu3V9wQbWn7nx zT`B7L@Z&szunGq-LSjBqNC3Nd6oa{;O{R-s1}K z<1^j`NIe-voueZxWpOs(`^Ds(2crKM30qMHf#ZP0E%^ds53Eko$`$ zatR_AjY>@sJB6U6<)~?hQC}tm1u^rFB!jwM5tJ?()SzVcH%i%D&GOdLeNARab1PF? z1wn!*x>!jxSg_KkilkMX#X{y!b3#&Ar}*Z!Vr(3%|DoJ=;E`{bP-pE>sB^n$fqcoY2^1xtVm$rFsk7QGcL!7jWVM!BW*2Xv& zTLiGQBh$|PR{Oq`hGt# z{TNFXV6>bnFl5LPak<}ptaoUbAU45sfOi7v1jFe8CxE?`wRJs%5|Rc?;`o_1^JbA1l!kd+SuiA@r_=6mjEs!@(I5R0(_tc!2%eY3{4mn!$mlxGU}pk5w!~zt zoTfV-O~C%^U;p~IESSFjwXc061PBbE4V+x+>R4K5(h7=*k$5hEI)(r_CN*}!v>B?? z>t!sA2wgPvWB^8z{kmwQ+EK*|3O@|HjKO=tK#5+#C_9q4@ES<7K#M?fO*5B}E>9%W zlm2rNfkmznJX~DK3clk>P5svK9A^#?$c+$K4nBh^h?)ZB=HmI$Tn~=$njoXvnwWi^g*sA~BS{Hh83L!N z#(s*(GDMjL(UU=YsvY*YAla1bu8ZfID& zc1^p@wlr%g@b*@VH77r}qNb+2sv7nSfb9VFd-m_IKHNa`_KwcNWy^N#-NWfR8>K;~ zX)r0K!)EQY*}7~t8T|FhPkwTAbX4jvrX&IBU}r;4r4Ex`Ih9gOIRTwOMJ8YEF9{^95s%qO@Mz>>p8GTF85!#4TEe*&xa+nn`V{2!?%>6{9D% z$;nN^~M72ZCzB2>9*VY`ugs_ z|9;kRY8VDg4#R1i@X&zuIn6^HOIwHh#wkU|1qygb+3E&>m2$#o&`H-nD zNsXNIzjUqbG!RaRPE4xOMD=*XNF2RyLWe<)mQ<`xY6*%$eo-hI)s_;e%&5V0nx{q3 zX^E)noTEAhTMoZy(6-{HZCyi41DATxUO?^_GWcgi=~m0niI`L`_VcDpJx3@NSp_ni$_fUqO;ZjKnw*jX zh|GUb_N1uJ+sCQ@XPhoTQT8qOf12ir2e{0hl%)shPUo;6#W@BD^HG49m|GoV69lv* zNfkJN!fGTHS2|2uW;^EU6xC&`DN7O%be$Y5Nq{>WNqD2U-yizeC;z;nx@P&x6?F}b zRrU2*OP8!zv%0dr{$NdQ(eh=D9qk9Is@ASsXYc9BFUVg_K)x4{oWQ$)bn-1T%pASj zJ2c!!Af5PO7{Yr9q$?T^7xWGedHM&ubgC)g?L?3PK0kb@rgr&?<@TQ5btNTtZrj%F z@?_`b9;~UUtZ&$`X=8`O2}FI*{(W^#&9KDOx3(56C%m1-!cbs$N(Z|IfZb{x85w!! zJKy<{k9>p$e@Q{wt=H?jYl!2WMyJG}hd{AE9Yd2qrn zQhB8jT?#44^uje3%;7m9HwAy8YN-aQQ8vAFlG$VA#XkNNp6eo&b6G+a=0j;jj7!T3 z{Uf5QKm-di9O`9iVjwDz9EtEe#2~6JFa>#OPDO;_*spG4&KU3+{F=NgxV=ar5}h~4 z$T=~kbJU#*AsR1;v4D4y6)?qC0fNa9EZtC?XI-TdZ^e><7A(%RLu$W}lG}%Xi02Aw z`yK6xSdAAyY?4(ZgD9Ft)Nr*9P+2q8)=loxOyay3@xCe4!^M>lL&Zy~@@~5M1ovwB zl|@!%{|1F0N$N<)|hez9duGvCQr_Gj^6C5F0hc2r!Ku4mwcd#3)1Zpu+P}#^LGx zzQ7kxjU74uHd{~6%{On#$;1K4hLyYuq% zR;^p(^7aiLBf$a#M+mAD$0NO^qWUl&mPbRtfQ<{HK148|0XscsklsUw+_8J$+nR>P zJGX3h_YdB3`yF>|+v@NRWas4oZ$DIbxMah6i^o$?RK&1-)!H?O+uE0}TCu;PqFdHX z8L9)k+iVV}^PYR|VFBzXPoA8Zm`Em*GWaW9hhYt;={k%_U}tpwjii`=6WD(PwzGn% zFEGwf-OsYt&G4?OsD3S6eNx1*pnEvHb4aJMiRNQxFwXhEfN^0vjN#l}(M*cCdW2R& z!36!dE-@w zz8Z}oGqo^GF)&oh3`0mExiju9FGFT^LCaHNir)OrD5CVyWJu6&^x3e5CLz`PU=;5N zQh{*7yiQTv4vnWUIVYcUTx#sHG$4MQFp{dGW>aE7QE{R9@RcZGwsfijF)HSY76YW@ z$UJ;aZ&Bwsh)fkjnc^MCv5j8jx+Ly;KN!<}#f zbp4sne!ix@zMvrgz@bC+O-r3GM~9g*LtvaHfH4CkW8)OwX$h60x0k>;kze4pXK=8WVmokn zculy{>FsN^boJkTZ1eUV1lxQ2vvRW!R##Wn)vw>UvCV4BFDl%TF&!-k+HT?Yk2|UJnjJsu6M=Cc>F*dFgo3MGR zsjRWGco~uII4S3lBD9Ygh_{={qeMB6WUv$lMK2QHL32@5adK?igX_8App1FC`vvs@ z0V0JbQW*zW1fvRYq=P+O16Q{KT|%YoO_HAlA?sQ~s^Mv_>fkrh?^cET8+(kzVUGORWgeIMZqj zv36j&-h3it9MecXziFJ43E@qN?i}-DXhyakBg5*dqA5v^$&;DAQe7wK#`q~;_$19~ zq(q&DI{Jcyx{tD8UIQLF;R`s172p2Q8-WJ7e?2qLuR;- z-cNviV9?Xw5Ae>9fdO{n85|fqc5M5u-FM!#&EDIWlb2IoT~$@z0KC1;YR%2h+go0~ z_rQS-n>KaY9gbeF6k)n-b^vy(%_albKli!M1%pABBmj(^jjm?FU#0+dQ^Tng*fXZY z$nK;!Sv>vC*#4s*|70RI#DSUN=U6?sZqFRaz;`5xh3)v(grS+iB@57k>Srvu`;h#9Mp9yd!z8+ zRQVaSvZfG@*gsHcLa*mW&8cEIS_eDrxq}5~fua$Ffv718ATBw)ISF5P#pvD}^j-q4 z*{cO9yvt-TDW1qNOv>Mm!q~OAu(W(g1BvP=F$@iLis0EFF`sF&Qc%@TxqUsrIs9p3 zf+0Mi>!TtoU@UlAi(4lIo}l_@;0q_lhK?M|%E{Wje_umuOHol_etzB^Tefu2Np^7J z?Db}4W$oEl*3xAuC@MVM)>d9!4ZI!LaBf}>G0gPzlKLqHcA~}*+#aqy+|bg|;T$ul#tJH$|8(4^vHA%twvTZpFZnq|Z{doR1YTS}DP5HEQ6DqgNSPf;F|sgf=yh0AYf>g` zSMHZ!RB^ntx+kxAYNMqU=#iztWC#?B1jk8(+F+>kk;IxgMl);K7FBgoUAMuApFJeD1|cfc2T($n{L#YWQ&NgoqB`a6(mY9lUC{e5 zc5-6GmV7&fM|B`Cx~R#D-3J~N7|;WFQHVrR&w*E!kzkt3CCy8z=hbA+hm7lW*f=(~ zOJJAIAGIGu&V0Z0%m@ixN<)4|GZaNfQ3Fw8P{f&L(!MVHk_@ea-s4i_ zk#m$Nj8Ec1Dwkz~A{<7PO;6LNBsRU2$uA`Gi!*jEu#>^2{?MmC`*~OIKvivRc1~77 zVZpvb6*UcqsnWj5c69eW_w*0;*ETlv5A!Z0RxqWH4)-Z%I{|#sg-W#=O4J3m_xHo$riXWU zWYcZ8-LY+(wWlvTJL_O|^<(5lrG6NaH2n6rzg-T( z!;>|b4rA&|!obe_Fmie|Hafmh<@Ddr*kSpIL?=>b&Yd}T;q3VtdR#nves=oe!ugr` znYl|BW*2AXFJHKL>DEM)3Te? z`i#UHhjQJyeaO_@6i6FfV#r8@^gv@4xf6ZEF&tX9nD7uXcxTgTgL-(TB=fkDS?c+y zh>*zOtB>ko3$g)a$$WDq@9ZGL|_0?L9M<&O{ADVeCR#-`T2Kk-_g+0vV6sg zoSf{9H{WdQ_1^Rcf3UWs#OdwJ&ds@F>lT}*Cp#~9S6Nv@YkMx$+smt}*A^FB-Ja~+ z?2`5C-F^K;hanI>q^$`FE1y7?YYF?e%H>O>q?3{?e;siY;Lnyh$V(XdZ*P2hsA1@I?U%k z|M_q@Y?^S2br=ThEFT6poSJ|g>o7PaCZpH!cK~+y`s!D|7KaendA z%Eit5*@de!bC+jkFHg@bo;g34ICBv& zKN33=nV4cMR7^OH`Lq!mF*QU_ECehZ*pT-4uvU|m9(8&ild&@b;o}VU142}naytD3 zSAKHoVNm_@QcI5t8X47^^yL;n+84RsV_b7TN@atcgs_AjPMF-1CRa&FGVMs3$s|lA z7sk~kV@Ej5beIr&mVkF`dP&K(L#m1dIYn}UH_zCl_1F*yK!H<3NaAR{`er|4F&d$=(>W0Hhmn>Pm zZmq@bF5b9NV0-TETQ*x16`Dt+TruP`%4$v)S#(jvagW;fFu|@sGdo!VAm~ z!^)<35FXCyWfM-NABLfN#v}ogz@AZu`Q3mWzFxX{5(=?mx1PoKXq1Gn=F zi?9?;UzmZD#Y;fiXU|Pvn4X!PzHssUG(RrRE&#(ne_`&z#RY(RVE7m3ugor7f!mq+ zD;MT2PhSL*4}d>Sgq_$q_D3!Hj9BqhR%WFvGbw$NvV_WAk)plSK#$5aFuwqN=|4w7 z?lLPZuJm(NNHzC_2Gf-1fXp8d0HS&xh4c|ZPDrVNV{R|mue2|QL_HLD6)A9*HBfG4 zq^KC3VmKer2(wmol}AADGc^IGp%)Rj`yH!5dUh^Gb*T|41xd5PB+Um4@6tY`YK)Tk z_9${8L&$sp+l_?(2Ss#>2={RmZXn(AQB4lgEv!j%c758uAfRvPaQ*-~Po%#>z`QzW z?i$%N!3CwLoXQcG-})j*PLE(gMoqHDE_b{N7)X0(zISebPlxxAOcIzpWsHwWb$u*! z;xs^az@)J=lMEab-UBb3@{a|gZJn0GEv@S}Y|PHeA{^M^Sh;G|sx_;vy}g@myKQYr zu@&e#@b)cREDl#rULIh3Q%6@`K|y^B!S;0}C2&Cw@b-=Cfm-(r4z+Yyc9)d_I0J8g z?7ffu;U7K-s7pMJ63GWycao4_NZ2Da#thJNs>2An4qUyTOk4$Q_j=**4h}jzJ+Q3g z<>i)FRaG56T;15v$!eyAvD><=)@~a7^|rUY?Xkxmd*+#EMn^|uu^7;G0Cr&P8RFn?e(LY6eH=k!geu0iWLQzu4152N4bc|hNdyy z^r&^7hV>RyqN{T=%t?Rb6a#i9q*Eu1YBd!GNTBQFR zf!qiL-aRk?y!}v34X|$3ZQ9t<+(TWC0Ol?rW zbQoraNzaFoeM#wlm^VY$-%RE7w*_|idimv7#wTI`?115C&H%KZO{G#(si|@DH8B~B zB>?fKre-c)WR(6q>_mXG&&|XC&yfFJfP>Nd%a^af&BEekSONh2;X%NB!uH8AM;ZP+ z!Ti}pCh5#AUW2uQ@cg;UM9Dut7fVe~B+f-9r|1aIBrkd*imsW}Lor=WR|x~Mt;v)y zz+OQbY3M4DQT|QH*p{Ff{FU7T$rp-yXD~V^CW_8U;mlRn|QNx=+$jlPPd_ zY67cU*e9vLJgPPY++!p4c2ne|a>d8>^afqV(b6Q6+QeA2H1JSLEyz8AV$*b59#*>p z(^S5In(C5B&yDnB8gI&?$0bqGe=0rdI4)kzzZUUdax}c`GbMyvaCMv*!}WF{!f=6I z)J#wLqo;gfO4o_$g?Awd9frHv>HRNIV29)R6Jrg{EqOWF%T}&v?e4y9%VxmvE{Aj5 z&Ru}*7LRAs?YFO6U(!vmJ@1aKTbL%ZyR5XO(*pO@x3nCrss?N)v+A<5Hr}$y+1Cdc z{?3OV+Oc~V;4_h21{sp`6DFZkrDe!X2bj`QDe=H?S*D-4Vo2rGMS-0_dQT5vJD|GF z?Y7bEuWqLkwg&B1YZtXR5>&U^I<4IfhvUeRBab}t$dgY#$#fW2Hf4kGm=42odI8n3 z9|nLOtLvtGnBSno{APjucK~*3lKIN`_#|Na*>mTwz4+qwmw?FMfaAuEm*MvEmCHcb zVX1;2>de#`*pfuT5rF*3SR9@JPno8G54Y2l=g$&`zW~TSzi{cw)oTlvNB})heYOMu z?9a|Gp1*K$=HmRh^D`G_7iMM`fae3+1IcF$f8p|VIGF|5U${!Dw=)aLbF;B2qU47s z81j%}sLTY$1Fwb0hI4zF02YiY5gwb>H613bP@Q#L2BQgcz?XU7Eo-2{vKUPuFjvlrRZU80V$DmL5cjO|X>tCxe;|hHnl0p}3JYxK@gO=&U6^ra4G}XnIA^R2rwN6)Afux%p3J3VN`!JI?S8Njrr(^g`8vy#N*RH`gaQ~~Xz6vW8LHw6rfm>Jw=H}`2=W8k!#6l*ZW;3@B>%!J><)nBPhXtB zFt>Pdfl4}ySLZLkICtq9@O%pUS1-(7N}ZjJC8sA7=O^N4f#-*)=TOQuLeh_MwFk-d zsJT^yKt>ZN>4jy^q-Qf~ee1aAh;e%qv63{=a=i&u<)Uz9gFiQgY$^%nEfml_#VNWf zsxtIWV$mL}E6N!jPH^SN{P9vUb4&_Brhe5BUo1E*huOlxtEdT9HPA!GQi`{S(DfH6u(MtyT0BK`UG$u?<4dQE`yPB(Yexr3R&luwx3=XM794JAsjR7i zlje?&Z98@VZ|`(EZ@&HZHGu7IPi|h`?OV54-JYzR>^=L+n%X)6?Hk%!4^p2@cTew4 zOKxJ=4iw$t^#aZ24MzauLR5G65l9CZXYfu)JH2)F^)u~-b)hgZnIdeeSLioJn+E#-~WCV{Kfn*Y_djrUlOD1IHyJn=sKnLH^gNxF@_I_ z4~xLu+&mC>VECz23YdK;6rPxjC8y3L;g>_XJ-|HC@h{F234fj__<-u9BC)V=?fP}V z`77{#FTMy%0FZv*{PT;KsC#D?t_FrrRGnE^8m`P=x<=4`@!I8UFE3nviBSDZ*QPHn zp1ZJ+JUcr{OSc^GIcO)8ERW_{2!nK-?F9m2&?*+mrG|rJWDGH;2b&(1D+bLi(i>V8 znbbS_IZ87DoJ-t%q$y|VG8Tr0Ju+OCtQfg5$C1%p;ban2zS62Y(sSQ)40GhdE{N;;9UZp#@W>s|(&v==%S8_6s(5 zZ+mw)U?b3A&%lty;R3o|-`sMjrlzo{u+3uGcGq2i?Oks7EqC0preqyJdVWDZ!S)`~ zF|@n1tfjLnCqECC19%ExyT#>Rvh=3nO&b7;sr)k7!yPZw#7J%G49Vf3N(-UrE+VH> zRHsE!mpGwBoeJz+hw;EI&0u$1<=kqUjhSIAHoMJkKYH}24F1AKM>$!;z%?fBr>E*%@wMA(Wk>_e+GO!#6L#@(OwA8o85RMWh>Y z{u2Kps{mp9*Ma1}L@7Spxp--Dc5d$M*>eE+@pxilVj>og!;v5y{~Q24q4zTv>CG(c z1?EV__9EN@!ox?ne3dYK;Q55=Q^22{Uz}UG1XoPY%wL>aJU=rxyKseI{^HezD=#iy zxel;Df9XYl{rOARXXdX=U06t+n@dd1Op@yD+3+N_<&R5>E~9DCP}GdwPioYu@OTgb zM=`^Ypu1R^mkmThmqxB{CChVn4bEnfvPKA7U&2YADx=bU6HF}+rlk|eM1l}D-YAEp zLT^K~ATiM*5yYa&OKWIV z))yJxrRS|_7A7vdi@ifgI1+VfC61>rG4y61p4NR*hK#-9Q-53aM&phTg|ypx6P{`XMJV$wns@4o2h`(VBFUMt;3O z4eG2liAgS!x6Al1O4p4S#)9vC;v+5XgsuZ%I=sCkhH>Obr`-Y2UEA1HURez%EnQt( zw-apdbU1Il<4)l1T~23CZtm?{x7vHXS=m{D?M>|+xdr((jg6Ic_0%otS+eA&4YzCp zSf);O7WT#E7ti2;LUk|U=d2Nl0J{*?30Lp+a-vSlrnF{Ch`Nntuv@9dPKQ<#VDDf? zM=Q}`?z!il#~yo(1%I&s_Ok$6=gu);XGTXnFG zWH=$G{G77*8w~B?+iNdU?58vy5dIpCBW9t*@bi*e3g+-X@C14pIfn)AW%Bh3TtvQk zg=jmlsR6*Bo}PwfF_BCX89y2Yz=vPu*>l9DLuCBvY0B|QL6*977B7)nEkS%B_XO>) zUSsE1V9T(uxIn#{fczI{7iQ-#U7Wu(M+}*l8Ri4kXUM;JE=n%3pq>Va2OFWJU%{56Nfd9J)UKC{f^dK{`C7H}V*`9x z(B`o6w1jj!icE=-!V$ZNYwSXJ4@I?7tN`<5Pz&`<;*M9@ro{Dm?wn7dZ3Xk;vt;-w z!N#Y=9wDiV-s;n0<7j#>fWAda8hX3{?lMNj;47@={iit zM8`Kz*MHlYO5gs@cLCc;C3Sk5@o)g`s}$ea0YFXfxyH~Q0Q`j)PKLwLOP8)N^^$62JX4+r_oFI@-Nhx=hQm|wg+GYflxON{CR z&j;9FynGFye(~x{6zZ=pT)w_|^~T)di?j1r&d)5IIX{;=doh-}03<&;c^09bgj7XRl_bV}FE~<6sp351CM7or z0$r(3hCF(Pvv+>kl*t|`TaW@s?GHs&$P8)7Re?4sBaGw45;zlHM&GE_hrX%!{iN8p zlFaj0j+%P7aKYCsv*R2I?4QIw^Pou75wSKYz0RJ(vjT&tm6aD1X^Sb>Z@5O&y&(_mmbc zE3!D%lDVZqIJ+-`BZmt-y7T~-Fy&%DL4zrx&MwrFWZVbUFSG4X3{YsIug zfQ(oys8}6Jp!QV>s;N)}*&~tTF{2owg|UyTi$f}#o#z81m%ip;H-z(FFz{4JUq1Aj zX@V~z3^`2$L{OI&QreX!!;>7M+T4&Z-ChOFsmQ{Tq$&cc??Rj9x;cPEkLpp~oEv9*#p2Qqs`KT$iT#sy;O8T1oL? zHSkpQoKDhN)e~a@IWH?5 zj<65_E1h;)RbO9TU6Wr>(9&huzI*qwRV!g3*u3qobtNS>kEdwavW>Ug0>t~KrAtU( zYFlS+VL^36Lj}S14V`x9Ti)^qBv{7N!^|-5{sAE5%-`tY)V+^d8NEz|QR=#fd0^a3 zgrNmfx0M?mU92OilLk4qc6HG~cqI7i-h1!;<3Il6PkriBr%s)cItFH@1zz)Ek zQHKG>Zc1N&llJxB)(`W$0XuyC;0HepN5)gBGm^IxlMJhw5=bYEoxv?bY(U-TzwkVO zbdQT+%`Ae`oP{6-7 zyKv?5wHtu;m#^Nq^5QE%^-25f!qw^7OJ}F&Q)ey`yH4yJRduMa!_gjLbyS;ho!$?H z=X5CKRBc2FT(88YcQkYlk?`>per`ZE7Ma7_(dZ36r!OTMthB5fslagUWjv*_4kAhH zmPvEGAj{==DxlP%serEe2ele*0_$4o;y<1PrDcMp1wrsRPv{Z;^fJ20#6Sy&|p)B^HNulkp&Ey@tkWGh05@mX*)g~RvA_aGZNBGa=L0+ z6{+kzxtCdD{88z0JRzpw34}K!u%D1F$Faa)JojZ!-(ZKO+vae(dc3`Z!!%j_s2n^E zAPgr~CmAGNefaQ!s_KHmg2wiat=qR3Enn7YciejCookENSv{WBYuDbo`OZ#>IZ`!-b(J!Koy+WfTw`}rqay=$ zg6(dG?LDkoO3W}+U1yBFlax(uta#dKvB2u|j(5C+4Z;fsgG`5+re88ifCYa^9Y)gi zH|jRUQ}BK(y8fR5?C=H4Pnhs_B6Ksoo!KB?qS6Xw^6ZP81BVBYpGutx1_CkC*c6XO z$AQL2!qG2&@k=jWyUuD2RIYy!*!5|j52$-&Jn9b^fXOFLys${Dke5dTzR6ge*=)FI zLpcA9mxQ~XDfRN(SR(np4?OUz%TprQxN^*Iow9CrbY8X1xvEEOV;Zn>1sACoUMMHj>=wd2ss5KP8V4YR6?N(GwX zFdwZV;BHH@WXZi341^RQ z2`vFaZ>D2|al^e=S&}7NR<&$PmMz;Vw%i~jkUl9hlSyVWC3*ke`<$a=lbJjB-goD= zGbb9^7P73e_S)-T|N7Nz;RSDJbP`tIs|)kT#TTfhY!j4A?ROdSCrIMVq*u0~5j)s5 z6q9Fb@@yV1qd^;+TUafqv~DA7rKc&WD03rw+y;Sk8rW;+BX&vajHphdJ%jC7 ztC5{Nf6<@A4GE73kB*LxPe@4FibqkSvD7$^k%ITQl&wILXU>}C{+6Ss0E8&nD_Mju-Mr7&piG7;zc1*(UaVeCIi?G%fV(pUk@)dn}aI~18j#I zAjt)@bnJLc#Afw`XxiKu!>XJTXCtBO0OMg%h^PZ;C#X&t*AcLX1`CC7@`b|Ca1_9P z@ZdqB!^q`wjYcy;UH@x2z07#i33Q#P>;E>o{vQPFaD4XJ=dvaRfj(3r#ju727)ohJ zY#PhsaIM?ief`Fb!s24FM5;9yfCOU+#o5;fMA}Tm_CZuCMQ$1Z()^-A_*Y$Kv)*9n zw_2N(EdxGc%K4~6a7Ut`w-HO(4(i!`F&P1D%bY*AbQ_t?&(LE-v=83 zN59>PNWRV4XGK?fP~L(K03VV3wl0;XQ=tUF*Aw+vLdvoLiBvg~=J0Hu&uHmvHZC7G zT$SZ-bY&n+7;?>6MA#WJESn7*KeZFA@(h1w&DwJfnPPWExxAfJdlb7%>!Be~&030q zH*2Ni4fbrc-?dJ$nRzq408PAqmt=%tnU#s~yt5ZqEsOaMHMBU|yYkPQtkg%vIB$6a1C#7yn#*CfLOUJX2 zQnmu{0+~nHK6|#OuaAe9_w*Ul0oz|(v2yyX8341-FI@EG+^2+*QI9?G_<|*i1>uoD zoAk(v)vE)zJhSVML`IqlkY$~|#Ok_0B!aC6EKsk!^2(t@hpt||T2WCkVO|pHOJdvC|ArstVPO9k zGX(wtIt=@O%>~kAP~Vk-fHOA0Fq%1q_Do3>RMJ;GOOL;93E~`DBvF=52V2Wcham>+VCEyuAyOgWP~(Bp~k3@5u|91 zj1VyfYcp8A$6EmS=fNR-4xlw|dZqBC9rp+i!lt6vVu77k2eRU8;Pq{82F!;;0SsS{olor;^MT=a8Yvkc z#VPbyu>OWU|9EQw$d8q!A#BUH_S@`T=ALd#Ux(4$V?k)&ZLuPTj{(2W?zB3FYy-pn z_Mx6$I}rY^9;>0Vhp0Npli$KfA{1|@s}w_m~@4$?d^krG!$Sp`{^_RdUwWoI482#cmeZ%C0> z)~ubd`;f9a1*GG$h{p-|)PyXhPTD*^%!l^gkop3X*(e>~L_9GgLZNMBwYak8l~3?M z5=mb}xH@}q(m3kQu7}E0q#`gbm7PF3KI!Szs&ONeSjAJ<{8KtcpiYX;TCt*%Vdk}s zH59N*8PZ-!HKI~&r&aaR>$h@w0%1s4cxYr4;3pYrN2C}soH_xA=*DkFkpAS{xnVJ} zp)s-3X3YSgcE_5GKQH*Dm8+&spC*ioes0mCx%214mD!KZd2aDSet7t#$&**EUE>$T znKpgeW*;BFpuk5Tf1DSJuzm5er2y0g-p}$0QJ;v2%NfiV_8{Q4Gj&ggy7+ZQ{r+YeM!Xi@i)e5{IzhHpA=#K!8#24 z_|>nzkjWItY~I#}Ikk&FBVflTQ)4AHQ;Adx--H!TrP098G+GU=W_IM}$N6n>0cn*B)LF?RI;)i;@Y0q}v|1Ih2R z4)oic=(G=6?Zc>m+dt6VVN&!Kh|Qpb~X z%JDcZWQKuIiA%cCu?m_lmpiNEI?hdL?4;oapv! zO-9BzXBd&6z6Vzq679NSPa9zsb}9LY+(7Co%ew5BlJNm$u7=t1O|n$6mA*ZzUx|^; zUG>w3@pN6xDuc3Y>Mm@j^m8c{z+R6BR*LD#sti|W(%0*$5qK!_tFl@QjJ>i}%yz;s zbe&3usi#t64jewl;RTDrBg3PjW0R85eA3iy2-~+KR8QW%orLSgrEHB)O$Ew5edcsQ zctmJ)?3C$KJ$-yUy?k&JQ_u#F&2S|+EbRHki=Ub|7h(Hjk3PS65mzWg{`R$NeFK94 z+daI!;a@#9cWz*a5U~A)WlIrn$C?a<>U5Yu6t=HNqK>3^lKKT)9kv7H42g*3pgJiY zY)U32!DT2)bPNp(OHN99>#euWojX@pSV%tC@G&Q4QzjpVXwiSozW%Vw@oz`3|0kk4 zIbeSwlgU+T9sHG~;S?k45Gkip`ZF%960sd&yG#aT6<`fu4}PlFXaIiUOL3!wU^T!X z;k3Yc)oOKZO-*iY&V>tU2M+E#dFIsh%$palUTIOO+l@v=a|@vT(C{!pLgx^PHE@zn zD6(IG#WXuFmlRtmSss1g0T`=nRo2#`J3n#q_|Bc%MPWj}K))bfV8)FMKxsIEpO+LB z_VrqFvv0MuDAX!di$Y#mQCU)4tZZq4JAp@zx?=G`N+-CA>>x`Fz`oUHH5xnH+i~wz zYb&PrazJ~nPKW3{?z{qi50|i^gEtA>3A|5wEEagI#C~t5eV%Zq18B(_v7%?shD*Ar zhHJ)>j-?MtIsp5?@X?7F{)p8vV!>j5SC7ru)z{Y9qt+Q)HDoplA^D7quXfpWGCMe-dh_cTr$y)I4GtTn_-ZT9rE-U||T6V!|ULcI?>k_S79$$em;ufP9xK|XTt*ZwZ2l$4S3vha9m}KeLdV4JZFt#pFLuA;?NMbPm-PM zJH8(3S~3(92b4(YG({<^xapeKJ?_`hW*!AKo6j{vgjp}-;}Yzp5BVp5%8;X#JT!@w zT1T441)WK0N07_OgTS92jmNs;s3U;Dbwfo>0|o5t&~*ycfu*CmY6bB5 zdg+;q*8_RH5CFrdXyC^2DXEFLY?^=>J5poda{CTAW0SY~bGTEcP2q<}Jp26fk3Rl* z6mIRGHWOj{I`>U8fwyxwYuz`^nll?%`r@U_P}^x#3}E~7ixvXf1GcYNyVj2vJPqmX zKI=Al%z5n5071w<|IWXh&Yi~ynQq-@I2btXgL zU)yT>k5tzmK7Rf6uch#@(dx8XosAA1AV5l}I|cX%(-1%dniZ531Jdbq`tr(3_+fQz ztwh!YNCkuzo;0|Vjt*nJxUt_xIpmpKf|AT{;UJLQJJ894+vIa5I6G0wu zH81}*6;Mep0r-(3y~x^ch4r_rtn|W#^J!`4&YwGT?aC!!@^Xc|-OvW`ZtUzZ=(PsD zuDY_k%VgAR)s^LCYPIU!L+`-7SCp3(7Z<@E4eqwGq5`S(HYB3MeFks?1GqtcLH>ck z9KI-I>yGV5jvc*mE3>4$v|ii*yuHWLi;5BWaN_P;c%Q%<24!aI^{`=)D-;0uBpYAf zW&oTwpoHWu6An)U9Ph>qzaNYC`01j`*25zsunt;LrNapenAHy32iRitq0<56)k#t2BK#CRBLwY<#=&s+;!JX zSZaD8s~ky(ZMwQ^nf4#bR7vw~S+h%%VeIQH+oy&-xs{eyNU4{OO=EhdXwuHipJI#r zwBLrpdB*+D^eD0Cp}3}pjBBbQRNp1VP<>S_vnbUFOj~H!1b#xQWFwPE!-{cZn0ezk zRHx@|5JMweN>yxoB$Lp~26^0M>H>BmtzbWl7#Bv#>8hX7B~(h5DXpsC@!Foi;9yZi zWO#IRY+_<*r)4Vb<)~96`vUrOSY~^CKbw+ZQZeEQ*Ty+0Xv@rL}8(Io#

l=SACZ=OASwxFN@KI8C_By=5k8A)HCFjnK?ZqvUJz5bJ^ z{-3VHun$;{q*4XWlj$I?7#r<)#BO#cDWNiDRy(qhYVu1F{BMe8Zp2Uwisoqs5#rf^IxAW)~futIs z+hdj9(caOKlYJ{U`{vE`i#b_0E}S`%pOY>VS4zayg@pwgwW_zbhX8z+sngQa4JUjJ zOuyUQWwrKqbhK-6mL=SIU2UxmS5o?|{hh{6{~$l#Ab+1gKkon^pFm%4e{U~;FW*2P zzaT%qKwr2L#0!c|N_hLwJ6Eq?Z&EY^Lc@b1MG1JTpf0x2QTU<{6=8dTC%^`$6(4Gi zrn$KVwn{i7ndB;%F~7IK8xGJOo)g%uU|kC}2%xM6xWnNQd}Rdwess?ccxDEXU8koH zE_*Ef@HF>g4IfSd^$raC*prVE)l8`I7DZ@k^rjYdyIiSPDD^TIgJlf|WaSl%qvfpL zTeg9pA@eS|h8Y4&2}eH>BQF~#vuoJ_I80tKbGHu#UAm+a`o>JmmzJG%HhztGIQkM- zf!ToX^5JM%+mP`)1-fKBE^~fd%PO@zHPR%!aeQP#DuXEFt5SQO4alz4I0%^>Q_cqK}aZyw+)Mo0`470=92OPLJ~b6^I4&hc6d48B?&0m@;pK&}J(#y@ z!$yE^o+xzDl4VcMn=6Qjn*Hdb&n;LG5*hi(BR^ZUe!Wi+hgjl)w@;rnLl_z5?H?eD zj6~Rut&gN&%Ea@cCR1#N5n=nfFf!8HKXCm9_hm1>^!VeC&ze1JorgQ3>mpHTSXgRm z>cN8tFI~D+T3QOUlL2;ioFjV*9sv7ab2){IcVf?7>sKD-R5 zEv};rL46n2bC9yrhpRluhl9iLne0tq8t`1f+Y(-j(XlbC?GIQ`FRmSUeqX<>-|7I^ zM@3s3kbmUTaX3c-^8xL#q(9u#iy{|{=Ki*hZjIik(sp8DN8iNCZ=uC-ip;Z4?L)0t z%(z$$OZ^z{t8t<0_*PjKbW>RU6Sm25;{vIiOeTn4F~LQtmC(4|kU{xcbV908>Ccv0J*HC@?k3LrH7843gU2u;SoTFqvI1|l2fn^CY90E z30+UzzGL~CHKOR~jhnYjcAFF=5cqSr>o%;9!D;Hq1DUc_6cz0@b&98tFY-XnobJov zAU6K!9IjA^c>5Di04Bqi3l}dA4h@|&dD6;t>wGwz8Cb?y>%Iw=1Nc7N4-oa3ghVFG zF_Mzj5m%?WO;J-)By1U$zVy>1Oi&z(2d%hyLJLVlRnUVH86(WB|< z>DATMWWp)&!vL@|jGdHCi64e3n@-4b{MQCK{^yD?6ApOb5_qd2pNxUZc%;mSv@Ao} zV-U2~)YQV43VAcY4jR4D(@XSu_=gz$aTyX?>FJGP zu~aI7m7}V%QYLG1-9M>Z4$zrnG}IGrp9R?N92}(5#)j}OK{wFrv^AAwd0FXYMcHNf zH|nd3jqPf^s!^q=6IT_K73b)6%B-wguxhvIb;gc%ld%IRJn;7ZK4hT*VDIfkc2-l!E$mLbl)n#R6Rn=83$`+kot5UT#it9^?i*96GJ$~$+U9ayDg$DZv`uGO; z1O*2L@`8ZFzjNpv>W{!4s+_z$t{|Ah=LH6Hc|v|{V!|8y_noGj4-5|sjZ)f|o4hdT!Lj^5uAYWHT$cKt8_H>Y*v& zY|<_zpv`(DOg)rks%L%+GlfJ)7jShnV!KdUIzGDDHImh}L7=t(1pHa^q%`A_XU3m& z6_tRzmPvYXjn$)+87k48AUX9NthWP=r=oggt{8zjJXV9)*DGrqfv8v1U_T5pv9r39 zCiHUGOKOHg5bup=K!{cys&)vqmMlXBz(rKS2Is+|AvmFAOBGYJZ!ADqktR|7eHhW;(H|Dp#&M5UDeuZG@7a_Ds!{4Z|CGz zR#dbom2$a4j}n4Abb13Ryb}K;u>~?NN(@}RXv((P48$JTyGE_0>@jrZl!!AVSOBGs zVK9e(emx`IPOmj&(IHlu+Ug2bv&7u4mQ)qwrX9>XzC(HY*w-J8e){4226aOcsOAT(%IQ5l}Z7?uUxut_40+AH?C*h z%FN5n$;-`EDC8z%r=bmKwa(mSgnK|bPkWnI-6|H>7Z(@o-S^hE9ov|xRe;qyUwaj~ z@dd%igwNvu!oy_{_UFT8uu#AY5rjoYZQc3u(Nib0a&t>7DikeBAQrIX3=R*Cjokr; zKRPxF&j7p|foTAylTaNvn_F76IvoOhEa|{f3vXJu1k6Vp68!c>+#U-$@CJ6GjVD?` zMn+LX2E3n%m=E+GRs}@zQM#H9wg_Da`hnzQ%pV*caE=WOjUmSlqWVL?@HGK%9y;$acN-V0_2&9VyE^$uPpmNOVR-z!n2Qe#6F%D_5^xvUJI! zMT?d%e{uc#_1@k-p`oEfhq-X!0?}bq*u9K~KX-Oc=u2V`ttKu<5)SkC(Di>$fWSWz z+u?yrvAa`3?0A1-J9- z>g!>pKnd+_hJLKPkg6&ZEJys@$D&^mkh?r-mRe*d2GyN_(&eEqSqsW$!Ug@Xs)NJ~54h~Qm~WEpc;57K1% zX+Z|DUii{z?5wS+F1Vd{>LF6 zT)2YJJ{Wx&gnxv78q5=f3X`{OJ9zkTdS)i9xMZ<#((BzIV&Mugz(;I6Axf+dC~f12qgwuGBZN5Yh#V zR9w7@P2DA~cpMj=k8`k(M``vf*YU%x#^1)Zm7oi+O;qeWlP5`e<7q*LnS?m5^w6wj zr`)icn3$Ql61w$?IBFP+J3C&6BIo1HGc>BxCP|mST`eAe*&t)3uQ!tDb!BaXqN+}c zfgMP@xPpWU)HaSI?X1pIGTU^=tGl?oU{OSb2;0}=DY~AD&TTGu2W$_Iigt5z^A7O$ z4hWn)8A&loJ9Yq<#=uTSASI+{X2d4MMI|H(fwxa}bKkt#)7u+OLFMw+Y(N##K!E@V z{F8H^3WMHqd)JA5Jq(8l2=Ra<#NKg_ zl82|~^5x5yEnBu`%^EK+FAj$j85y~A=guQXj$~wHR903tH#ajn49XWVn;QO9Y*9Z!R?%ww^Opr0Nsm9c>5sD z;o-P??J9%n1V4dq>ou)CCPTrw-35o%oAcwod0+G655M{G$G`me!*^d=3XQVtiu~*6 z&m4bcNAjU}4oD;tWpi_1F92N+(qVwxA`u&fEZ}}sYooX!`{s?Z;)3e(qVl5b;=G&n zRRxO1DoI0mX8MITUF*&3SL*8O6~X20=O(PPiVx4I=a&zR3&W=jP?Y zGB-Rr3R@3ZQ&V?$Pe-SbEQ3zG4wA%7c(0-!fgu#U2EPdQP_VWFX=y=yS7_)VytM+He}+MOTDoB}Gqo-OznRh7UGb8vc`KBX&)!Wi zLlW5|T$u??49;WHPKUQMZW-37Q#vTd)yl*GyO`0~(fm6_O??yL>bNPXk(o?QpVXJ6 zWr@r`y`FWOFAC#@2!Z-W#KgoTCdH>9`30#lTT_#8fI!l=9mzXh4iE@JA|eBM!IRx4 zdHQ&BLWIvg`)m{){}_*&Qj<|zQ&Qsj%NJ93?ud+w4~>qUI&JDEFRv}WzEh@7@#O$- z-#BabtROyr;R{R9SS5t*v!7kCfF~49n*0c0yDx_`W!h9vU%wS=*3Nl!4o4t}AU&t} zM8#8FFvWdI5h3AdQj#DXwaRYXxY5%S)(~$lmkV?~DJh8re~|$8*49=4b}}ysP#t*J z!|CfkSvLK9)b)RSEX=?8fJY9zU8UAypA1zPCDuoTy2La?f1k>1#JTHK6_u85Xnmgg zx6Ds%s4Ei%v$yF{Br%l#OLI1(&O{ zPxWeR{_ySBUHaxL=Z@{&omyX8dj8C*`uaL$OAAw+?MH7LKz9W1r%s-mP1cf#mZ9!NCGPPk^x9 zfz0;3uxkK_mP#b0@{02O;*y&BI+a!nZ)n(gVi)De7%H=( ziZcpEGnotqg9;cv!h9u3S0FAOGfvTg*MLN2!UIFQS2`;RJ_|@4!r>b4;bVmU5@m9t z2xt`P39#RbPpe}PU>}(?2Zo))cLs;=0NOhSM{SOgKI>4o#bGjA_3hontAm6cl>tLN z26NK!3eXC8C{r0|2rB`$9BvW9nvaZ%=O@xZ=+XUbTJ$ z5OqN8MR*oA;4{#8!1iE_?JL)<^$G}tTY7kV0nX3Hw+zQdN9=e+j6F1p8ml3|3BAl< zQ$C*$e?($p;`Z&^-+Jq<Eyj+I7d9AS9oiN_?ui4ih&Jg%Xy8iE}nf_-1 zJI3}uVr<7dtpu@|KeT$ z04%9!ls5cgtxnR|NEQN;+)i%AkWx6WT)je?RT1nD4q7Zd>BrwFKM`PWJo@`jdw%@k z+aG`Y^N&CL_RqhzkIE0Vob$N!%JQ_Ay=(H$UrIau`YS1EXHVR`c@u!K%VY#phd+sk z?GCg@8-OdV%?fjewyQ%^TbPk~B&O)FPj~UFpL7>|VH1D#z?yyi%$0M;-`@B7ts7T? z7yxx|Z)-D|I=jtXeSN*eX#<#kF73R7euCgZo=-bZX1~(0Jot7ff`I(LofvCL`xXAF z)rp`ImJ18)Zs51T>L-;-QMZ)MR$5w`o1fn(78ey3D3!|m+xfu98^mJxeenF8K6{2A z8p0Lwc|tx%z!OG88AxY>W#}A8W|W4?75_-jt*&isscS?o$Lji~3QX5g@K>#vT_I&h z^)gnOntDloNo7LHHZGr!;v8dQW0DdRaXc^buG4-P0`H>e=+KxLz)v9FYd35N;tS@@ zn-BklbT9$7iy{$#b3=r{+v8G_W0R9IZs!K@xKZ&5fWT9*CgU9tIBoj0K)zt*`VGjn z9wJ=y!jif3=K%u;8vopa1zbVMnKNg=-69ivG_k}WKTHUj zYDxpUAQa{F3d6#HsK5H^t9$qEJ$m%$rAwFKQ(03}Lv$FD=*W(9WXA}whgSb>m*Za( zVgBpWb>@Hv57@4T55J+E5l4t2jz*A(Nz&jNqMy&!)%<6IN6~lNx&Vr+}jYgh{G*`G+w%Lnat*chi2*N7N@`5U%lhY?n{6E zr1{4me*fc-fBMV!p96c>T=dR=V{yi|C*@~08g7PbYBDpgT{wL3jngNOX5PH1P{^?w z(@(hi08yG82&}qI9sQQB${R;Zj<_3c^1rYa|L}*8;ko(Yo6#>U`QoCqjLT;(oH=^^ z%Ed!(AB0Vx!2qP)hzqj)$fROJVFed1U7%d|s1?h3_WapFIwygoB$FH)^nSA=VvL84 zlV$;`;(!^x4TC>2zx1Q1v%Ws;)r3bblge<44IC!eI}{cbWoKuRebl+Mb3CDdgKarM za0YWZd?fV{VJBD=0+%7-qU3F<2aX(0yK<$ttW4h00_!=Db^D-mWNZu>eDB;L6%gdr z!6Y9(DQdN*r9}ytj|X0vj0E&?tP(6+XyOUp?V_+{v{M*z(wV4mAn?C)2Pi&lfngJY zm+WB_v^F@@k1RTlUL2cg9~^c#M*;1JM(z%cya#~aYjav1C{Yb(Cim+NW)!EULQPlz z_;PA86gzELEBmQlT2~-^6EWmZh_4@)7|bNC(d|g%CYU$U69&l*s4=YaaWnO3*<8(z zg``sA*|7txL|C9O$RosTo(*)QluD*3!0_N>F4Q%_A88h6scm)RYCr_T_>E)G}nko>A z&}_Sut%1S8Q3;7&zW#2LCkOKRSkFPspBE~Mh>HW>E{cqFn=;wc$HzM$2<6G}ct}Nm zbT+W@1&bB~wg-oY&zd#s`9%u>+eucKm%l$?yQipFVx<+O@*M!p6o%0Cw2e8c+;KJ84ZK`7jd%_P?RS z{5^F2zp}di@Bxop)}&}vYunlk16V}|SZT+jtJ@6*3zlRD2dJVagYE1Cb5R>JM3sy; z>g&T!aZKh(^QMD}g(uynOr!wbCJ>DsLpl*&2!$uh0APFC#S5ex2r%=GHsiOQ2YzQS z`}Uss4TQlG1F&q- z0(nzYL1F&IOKE%ey%ilB#Rv9|4LRHpKCGWyfIomdR|vEoogC!V;S0iq(Ft+8 z-+J>#Ru(A@5XozJWEk5iN748z)FEr_M!7pk*wJcGawgvSw&8HpPJsI^e824% z$3T!~2kgTfh5H=4Gxq)m?*n%l8@mHni0nCxbJZN!vD0U@_oIsKfThpwaE>^K#|DRi z-j5BBzBhX3eSm#z(Ht>b>_#&x-D-5ER-B&+Cop`1`7-$gv*m;ttXfw7n0f-pvzCX&I3XdiNlD1r9v6=iz2f8H&VjeXKlk$W z^YHQp-tNl_UcF%>fILSKvT*SWPtBhv2#=UKYvzK*i{YQ+%z-uDfkAF=lRbRAH+p)) zHUUqp#&fH2o&YO-JuFxxf=2}pDLygjz<~om*DqYSkeQiTR#qmFNEiouXJ;p4bY#-k z;VsAbVIIzM{EwjP{}q584tUH>@@5sn_IB8W!zUEB=S2ktrNu=uiMUB7gU>I4Wdi%i z<$^-P&`>1yTx=^IQL54DZ|CP$^`zzx}}S-FvEm%B1|aSKN4INl$L@ z7cD!!RPXwYZeLe!LYuU>wWP2Imbpv;WxmmUtd{Ncq&?T zEA=yn_{YC|gQ~Hx5%~RsPr7sKk8U`#b@|1&1o;_f^0Kd;IerM%iJa`5t}YV+XFKkD zA~oJ?*RK-sX%I(2o9ycknjV6keKgL)C026K zlMGK0&OPXYKUOYpDk>_1M|I@g!&_5RMB$Lu z#2Y0N-3FAqv8m~1R#tI&xumH{XJ|KdcLN6+8687nKJG7rzrGu1EWn!th3Y62a0%D- z2BhShvB-~!K9P1Tcqh^i^qxpb@VUG9{ykjSx_{@+UHA;%z55=#^c3KucN*%w>gh$X znf+E+0^lt-JOCtr`0mi~UAP=T3J>yUTKWgN%+`)h3y^%Z7UgFWNr!}0N?c{xadQco z=wp{HlPRsrCx$b~n%Qag6KAI~Suqk;R!k!+h=3;TtUPx4_|8*T%%ckH>dJZv-IP=( zCF(k`LcMjnSQHi+91;S&H!?0BpcqgZmrA!2#*T111wnV>_8s$o z@r$+Y?i{`Vz!_jRerswVUl5a=oRGRr6cZbjn6$;)cgmE>K0$%*n>Ro6%U^`YBC8B> zwnt)kkBU#=i9`U@p5ET>1lzehlqWNLb`W2%@P#Gw=Fj7WhEAO}6?l6k1~)OkW7FC;`D67ATrfz&l|3<*S!R$423&_iZiT zm`;DG+xxrsE#E${cb?;Y(cgHd<#^{U?t|6?zcroswSM21s@-4f_SRl`v!|og)Yb~v ze&X1>DwP_Rb(B{&_GQ@rOVB_`{!n{NdZL#x$1l z)PnslUfQ|v^2;yey%SQCbEdL1H!tVLiKB<%eTCOMB<#T7@37m5wsbw?`T*Vll3MD8 z3u(9ubr=9mr`2?Jb|{(xWBmBeYxklC0pEI^7Go15Fc~s@Y`3fUWQksuC7L*karq85yM9S zkDgwH^SG&&$c&V{gC5=h=_)gsjIFK8%Bsq&?5xwLPrbhT_2{^0L8uS_AFw?-HioRZ zn5qvqE0rN(BCO%VTEGY9FANvOB*yQ1=k0SBFBTLRH%KIEowmbhB0-n%$BrPj4_w`f z=U_Vp2N`WcdU8?q78h+vKo|lwsn{+I3(ZLs_9Sw z!$+8}#mLV>^6@?#$+$QLjcfFFlbUUqp)%WXoFhK9><}=i%Lb`t%Qdb#DUIi16coeg zFc{dex{e~h>gCAXSWT5pu@vJHUg&^FF)hf5NyF)}bC)Ifv?hs#~LcHQhbvjceiMN5{e@A1e32#t*iPjML`D&#BjM^O?+Y__L1?HbJYx6m-A9fbIeYeOMn*wgzed;peqjIag6a&mH#fHuY}aXY)s@xT6B9Gjua*_& z_4RaJO*?n!;J&J=D&SyDos_s`7=;}EU*4?r+~o1%k|oQR0kALIvUzh#>W&jf&zw7Z z30UrT-+enaJk-(N-iHNe2UU%AV0+^bao`Nm2l@`SxRY7f1ZvKwoud+3j5WVApVM6R z|L$JLw;wsbb|}An&-jU@31 zmEB}Cj?f3%tc{Fx%d&sfcI4N6*}rwx|LMb)zx?j~KmKO4t7>o7?&mMQ{PXiEKUb!Q ze%gLQmy;?lJm1zTNxzbI;r!XlmoKT+YS_s*aeT}G{zKs5rQb+*V77n);YUU;U%7;H z8|?7Lv)lUb-5u7nG@6ZVBg2Eh+rRqi3qZXa>DQ$au|h7bsVuvlbMt2UrK=ZCoji8n z@PS>sUrBmxd-S#hQ9?vejL1*O_2Bt!2;8#D+x?|YYnFPhdvW8Mr9PhPqocy#d~^5t z^Jihkhguw!@(IHI5*JDTj|DaTCPMprtJUDJYgoJUYSy94*{;w& zo8ZZ!#WIcIhIw`lX*$xWRe7k zl^sJpmEwzsCDo+9{HlLYpdd61pb{80;p&N)rDIe_@Q!AlZh!gt7Z!W?c=N-;C%H{p zv1Sb*`KHaABNO5iQd6Unk|Gllf&_voQ`|hgeS8Cho_OL3A?yG!-~(Of2tsDeo+Stm zr;^p<69C(%U~J#u;R*cQmxHh!`P+l}&n{T-Yk*qNMO zGFIbZ9p)$L`hU%^uYczO4-BwfrPd<9gjO%EsnNE!v?`r0tA+IZHAzLz_qJa2l@M-I(jra^JZp7#`P=LGSY8expw33-8=9s!EbqR z?>((Xjimz{DIk&vUn)odOEH-AItOs4D!?N#){Kmdo=ZDN%#e0d%O~o0K55ukQZoi?J_kl@F9}e${#M*T&-y6mRLvPj_e(eLcp?vf_+uS8}s%!Nv{1WPlEQ zBgY-P>1*TRKlG=4^PcIuk4Jw0k^S@D!j8Pi8+%uuNPec|i08eQeZTIz`i1#|v0}fn zB3&V=I&$b>=8g25nKyyAJ6*esA>z-xm6hojaHW}DPrnAVzO7CF(TDfH`qjt3{_3+2 z?~iq8747=g&h|E7*=J9mK7an4LN4p?vk*Ri@4dT#R%4^Xc5APxqfH?bSCkbL=H1G= zaph{-iIYbU9NhcrzSmP;O^r>B6~u)FMuzx>a6E$jH~MT^;pe$(^TuU99xM1ko{8}h z2M@e;?);go>`b*rMQR-+o!&;8g)z6mu{?Ihv2*OiF<5+uQA_L?d|6Ujvgge`g~f&N zhagpF+t%=iuwWqYA^}i+0j|&Tu|GdpB;bb$f!kNtRHHo|PUZnhZZ?@ved4*+)) z*j=*^u*C-OAHEMa06yP_haRd>Y@1rGK@)DS-pCFExzyIXPk9hg{ zhsVYH`Uk{eJ|7wr8=IW6*4-T_Hy}KjOdS;$AHd_exlQu&^WC_4%k=5feK?#ItJlE& z1oDEPeg3(*^XJ1NGHu56=NB*X;~{KcwQjA4mp7~(o3?BrMn_yWjlgD@P(GQLBqZ~a z;$DCK^}~k`U%h&@yu6$Qf9Z5O#=%YmcCue4Wz!En_+Uc%`h>FS-=^#TiJ|NNe-CAg z8nC_H(9zk^*(8xDqz%P6=^sD1qmQ$$X95`|KfKu5?W(*N;ByoUXQDtb~-hF<) zzUNM#l8EaI@^X(KJ+lAJH;%mh_N|Qcy4tGWfA=l@%=~4*+6%<8r^kZxTWrLpPSBCe zdm5m#!^kiTlIsp2fA;Jd4E_U_9`jwz`9BWa{PFvNAHTo*`;WVR_d(|e+S6Zlp7@pF z$-T>$}@qYH~8K?|XAk*3FFCn%Z`Z z?HJfyt+H9!w@9HG^%V^dU%Ph2*rAsXv8|hbz3-ao!%hfGS#*Vf@hjnPs@xlA|K6wAV`ybr9J2vXD^_e=` zTI7v&6-5QPH*ejzcscFFnd1i!?SF0eEAiWsgeh^s3DH4GvE1N3E~A3Xk&(o$H^NiB5@C*HtDpxfM~RJPRD*Jb5o zoji4N=PNHqMMv_5d>-QS!F6@Dc9P6vv%)PK>gxci%SwykRRDMwi^VO?&G1Pyc6JWn zOi_5+hOqYuRVa{sa)fNw;4a$R4SKy!qd{ZMT=oDSzGfV_QhWN_pzruQSg zR%aKk+XCS0+Pct46x4y$#yIWiL9tqwJ%&=(T~N=$c9euHmQkc#Oh|iEEA59t*}T-G zBt+L6%c~kHs>KXl$74*9gPlY>x=fFl#=}qd9eS6;4F*&XkBo{=NT6NosqrbPq%{e? z1Ed{*{iW5b-M4sgg`&xmCaqet8t{MZ#tkS^COIW8bz4+oVz4OG%?-I3eS?Cg&zK$@ zB8tP)u49s6MTi637Dh!cUa}NeI`C>VAPG&-i1+7kfrM}I@maUg9eBGBhr4_g%8Cr& z1us~p!W({Fj=M^dEGnR9dA{Z7{SWb6s<@t-o8{EcxU2 z-x)MbUF}+Nb?Nz2@5-Cx)R=5L6%Gj}Jeh5J{n=9|uU)0V@PrGzUs)AeVM=M z&-`ugm2dj58!L8e8Vg&S>W?2eeD)0dr5AxSz&i>7J4qqNy9~I`%*>k%!T?OQ%EcWz zg|ewuDXseC!Kl;LV>B9yi*CQMYiH(-YwsM~@4b2RCU^JcOP6}MZ-Ud)!^3^!Mz77A zH+y<;0t4b=qxZhK=kler-0Yi$x3jCtidqzs&JH~=;vuKw?w!$lckd9)fA7wS!`f@m zsTv!q%1ZJ}i}Ol~a>`2bTIF@+#hFnd{#<|eYu7FV!@*5dcH*&tKY@5GnM=TSSiXs@ z1W!~!QK8Xf!le)@qK)*FVF_f2Y0H9@8t7A_w6UVHT%~G-Pno5s+iLCWHk+y{%B79s zHodN>u)x~i2d_wFd3kM34M08Ie{D^5Lw!B0ELx3Lp=d$2dF+H5z`ja-dwVaC^ARA} zXc!8TnELw=svBW5{cR=X2mA6xP70PF+i6YxjQ%wD_MV(&EdYV{^MIkSz4DI+j0 zVWwSUNN1+s66%hxP{TDCx?b1V4DgQWdIJV_iA#M`}nrq7(=6Bt0I zSEDgWc(MjxBm~AT6bec3*U6J7b8~Zn8??5z0$pd41lUGL(r`K<&hcUU`oD^<|MybY zfAY|1^vYIs8_xRzgjXw@jRv*2qCnnQ0|dCXyeRGTah*=jq(l<34VSP=Ha66k6x`OS zRgLv^ZCZ^1o_VcCuTeW}){pML|H=Eqz3nYufB8AEcc6Y*+1a~Ze;syJ7Btm@3>c;T z?nIw)5)FQc1c;HDAaE8H7k2kps3{oEK}TQreTQna?e=I#*&TEBP+uGD)p44ZNvl>C z7v$&P&V!4p%1UuVLr+gPmhq`7C++eZ8g487wkK`0D&-IN&EJ1I^2g6dzW;3OqpsXf z+s}P%&H2Wf`5W{3!N&bMd8N5Sm6v_(#cgDzFjo{5dc1||Y z3djm&>1wm}8s&|Z7mmGEl6T!{Hy=Cn)|U0lcI`}s`+4`^K7jETmo1z7*qmiAEZMSo z^U4(~pMLVuHLF$u$gf|wZuzoha0MNkHo<>z12}n{psguMM-IPpGyQUYUM9eJeQlXa zDetp%4Gr3W*#p#n{NaPoKK=O4*l zml@4W#O@*sCis+=I6(G>#C{JTPq_X4`v@7}`kgy>VJ(15H2fW{5d#?T9sTw}tHTMG z14B4M4Tb8Um<6hC+hgl6_2~>|4X)cZs|<3bUP?^~p@5wMe8Si%x-L;-fn8BmD=n|8 zFQ)}|3e{OMJ1ZpyNi@~<($i^IfvyWgVWP;$sJJ*>HbtdUbOmR^0M5s!q$F?Ov2n{5 ze_pU4JOZfllI6?8V&fMqTo@W14Rjq)JrXyTKJv)V)^6PB&k2Uxa6&>7Qn$q>C w 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

~FwDb9KadCV0?0NUycW>RgRa;xD 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

E#X8$mq^I8 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 8OGa(wI=z}AUq2GijR+ngBbZ?`0E6o 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 Y^&tfKP$pLrCL;xd(^0IGS2gJV4OV+H$^ZZW literal 0 HcmV?d00001 diff --git a/doc/testbenches_doc_resources/5g-nrue-bench.png b/doc/testbenches_doc_resources/5g-nrue-bench.png new file mode 100644 index 0000000000000000000000000000000000000000..c167591592ad4219ad349bb7ef111d4745ee1412 GIT binary patch literal 24001 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 ^z)b4-7dIG~9~JSo>=zJhes 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 Date: Fri, 9 Jun 2023 14:53:51 +0200 Subject: [PATCH 052/119] Configuration files for nrUE created --- .../5g_sa_n310_nrue/docker-compose.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml new file mode 100644 index 0000000000..2a12e4cd51 --- /dev/null +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.8' +services: + oai-nr-ue: + image: oai-nr-ue:latest + privileged: true + network_mode: host + container_name: oai-nr-ue + #entrypoint: /bin/bash -c "sleep infinity" + environment: + TZ: Europe/Paris + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.20.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --nokrnmod 1 --ue-txgain 0 --ue-rxgain 65 --tune-offset 20000000 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 + volumes: + - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 From 1f181a5956be64c84d1da8937dc38c72b3c3a041 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Jun 2023 15:19:24 +0200 Subject: [PATCH 053/119] Configuration files for gNB created --- .../gnb.sa.band78.106prb.n310.7ds2u.conf | 270 ++++++++++++++++++ .../5g_sa_n310_gnb/docker-compose.yml | 17 ++ 2 files changed, 287 insertions(+) create mode 100644 ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf create mode 100644 ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf new file mode 100644 index 0000000000..cffa15e110 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -0,0 +1,270 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ({sst = 1;}); }); + + nr_cellid = 12345678L + + ////////// Physical parameters: + + min_rxtxtime = 5; + do_SRS = 0; + force_256qam_off = 1; + pdsch_AntennaPorts_N1 = 1; + pdsch_AntennaPorts_XP = 1; + pusch_AntennaPorts = 1; + + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + dl_frequencyBand = 78; + absoluteFrequencySSB = 634080; + dl_absoluteFrequencyPointA = 632808; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + +#uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant = -90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -70; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spar e1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + +#tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "172.21.6.100"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "eno33np0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.124/22"; + GNB_INTERFACE_NAME_FOR_NGU = "eno33np0"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.124/22"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 180; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; + ul_max_mcs = 16; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + #pucch0_dtx_threshold = 150; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + sf_extension = 0 + sdr_addrs = "addr=192.168.80.52,clock_source=internal,time_source=internal" +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="debug"; + gtpu_log_level ="info"; +}; + diff --git a/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml new file mode 100644 index 0000000000..30cef6b62b --- /dev/null +++ b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.8' +services: + oai-gnb: + image: oai-gnb:latest + privileged: true + network_mode: "host" + container_name: oai-gnb + environment: + TZ: Europe/Paris + USE_ADDITIONAL_OPTIONS: --sa --tune-offset 20000000 --log_config.global_log_options level,nocolor,time + volumes: + - ../../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 From a648b9ed26e0b9cb2ea93bc8e4c170ae67f6282f Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:12:23 +0200 Subject: [PATCH 054/119] Add caracal OAIUE to UE infra --- ci-scripts/ci_ueinfra.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 8a6c76645a..6bfcc86af2 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -126,3 +126,11 @@ oai_ue_obelix: Host: obelix UENetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 + +oai_ue_caracal: + Host: caracal + AttachScript: 'docker start oai-nr-ue' + DetachScript: 'docker stop oai-nr-ue' + UENetworkScript: ip a show dev oaitun_ue1 + IF: oaitun_ue1 + MTU: 1500 From cc71018ef7215af08f9414bbe602f905e638b2f1 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:32:22 +0200 Subject: [PATCH 055/119] Define server where to pull OC images - if the server is not specified in the xml file, eNBIPAddress is taken --- ci-scripts/cls_cluster.py | 8 +++++--- ci-scripts/main.py | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 56c60f7551..24b0c8902e 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -82,6 +82,7 @@ class Cluster: self.ranTargetBranch = "" self.cmd = None self.imageToPull = '' + self.testSvrId = None def _recreate_entitlements(self): # recreating entitlements, don't care if deletion fails @@ -195,12 +196,13 @@ class Cluster: self.cmd.run(f'oc delete -f {filename}') def PullClusterImage(self, HTML, RAN): + if self.testSvrId == None: self.testSvrId = self.eNBIPAddress if self.imageToPull == '': HELP.GenericHelp(CONST.Version) - HELP.EPCSrvHelp(self.imageToPull) - sys.exit('Insufficient eNB Parameters') + sys.exit('Insufficient Parameter') + logging.debug(f'Pull OC image {self.imageToPull} to server {self.testSvrId}') self.testCase_id = HTML.testCase_id - cmd = cls_cmd.getConnection(self.eNBIPAddress) + cmd = cls_cmd.getConnection(self.testSvrId) succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, CI_OC_RAN_NAMESPACE) if not succeeded: logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 97bc6fbef1..4fdde98774 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -431,10 +431,12 @@ def GetParametersFromXML(action): RAN.command = test.findtext('command') RAN.command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes'] elif action == 'Pull_Cluster_Image': - # CLUSTER.imageToPull.clear() string_field = test.findtext('images_to_pull') if (string_field is not None): CLUSTER.imageToPull = string_field.split() + string_field = test.findtext('test_svr_id') + if (string_field is not None): + CLUSTER.testSvrId = string_field else: logging.warning(f"unknown action {action} from option-parsing point-of-view") From 8ec1e639c0c072707e7f3884ed67adbbadf9eaff Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:45:44 +0200 Subject: [PATCH 056/119] Bind interface IP address in iperf3 test --- ci-scripts/cls_oaicitest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index ed04b34aef..14c3f2ac5a 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -1062,7 +1062,7 @@ class OaiCiTest(): cmd = cls_cmd.getConnection(ue.getHost()) cmd.run(f'rm /tmp/{server_filename}', reportNonZero=False) port = f'{5002+idx}' - cmd.run(f'{ue.getCmdPrefix()} iperf3 -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5) + cmd.run(f'{ue.getCmdPrefix()} iperf3 -B {ue.getIP()} -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5) cmd.copyin(f'/tmp/{server_filename}', server_filename) cmd.close() if udpIperf: From 0f3ff028ac78ddd72c33adbb8acd24e93d2b7cad Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:55:52 +0200 Subject: [PATCH 057/119] Modifications in cls_containerize to support deployment of oai-nr-ue - add oai-nr-ue to image list - add oai-nr-ue sync message to check - skip oai-nr-ue log analysis in undeployemnt stage - add UE log analysis --- ci-scripts/cls_containerize.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 520876ad06..f26fdc01cb 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -52,7 +52,7 @@ import cls_cmd import sshconnection as SSH import helpreadme as HELP import constants as CONST - +import cls_oaicitest #----------------------------------------------------------- # Helper functions used here and in other classes # (e.g., cls_cluster.py) @@ -838,7 +838,7 @@ class Containerize(): mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) mySSH.command('cp docker-compose.y*ml ci-docker-compose.yml', '\$', 5) - imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s'] + imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue'] for image in imagesList: imageTag = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge) mySSH.command(f'sed -i -e "s#image: {image}:latest#image: oai-ci/{imageTag}#" ci-docker-compose.yml', '\$', 2) @@ -877,6 +877,7 @@ class Containerize(): else: time.sleep(10) cnt += 1 + mySSH.command('docker inspect --format="ImageUsed: {{.Config.Image}}" ' + containerName, '\$', 5) for stdoutLine in mySSH.getBefore().split('\n'): if stdoutLine.count('ImageUsed: oai-ci'): @@ -903,7 +904,7 @@ class Containerize(): cnt = 0 while (cnt < 20): mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) - result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) + result = re.search('got sync|Starting F1AP at CU|Got sync', mySSH.getBefore()) if result is None: time.sleep(6) cnt += 1 @@ -993,7 +994,6 @@ class Containerize(): mySSH.command('docker volume prune --force', '\$', 20) mySSH.close() - # Analyzing log file! files = ','.join([f'{s}-{HTML.testCase_id}' for s in services]) if len(services) > 1: @@ -1005,6 +1005,15 @@ class Containerize(): HTML.htmleNBFailureMsg='Could not copy logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.exitStatus = 1 + elif 'oai-nr-ue' in services: + self.exitStatus == 0 + logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m') + logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(f'{filename}', HTML, RAN) + if (logStatus < 0): + fullStatus = False + HTML.CreateHtmlTestRow('UE log Analysis', 'KO', logStatus) + else: + HTML.CreateHtmlTestRow('UE log Analysis', 'OK', CONST.ALL_PROCESSES_OK) else: for svcName in services: filename = f'{svcName}-{HTML.testCase_id}.log' From 5cd74ddf72dfe6b2a30252565dd3665829052dc1 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 12:03:46 +0200 Subject: [PATCH 058/119] Add xml files for OAIUE test and cleanup --- .../xml_files/container_sa_n310_nrue.xml | 146 ++++++++++++++++++ .../container_sa_n310_nrue_cleanup.xml | 46 ++++++ 2 files changed, 192 insertions(+) create mode 100644 ci-scripts/xml_files/container_sa_n310_nrue.xml create mode 100644 ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml new file mode 100644 index 0000000000..309b2860f7 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -0,0 +1,146 @@ + + + TEST-5G-NRUE + 40 MHz TDD SA + tasks + 1 + + 010000 010001 + 020000 020001 + 000001 + 001000 + 002000 + 000100 + 000200 + 040001 040000 + + + + + Pull_Cluster_Image + Pull Images from Cluster + oai-gnb + avra + + + + Pull_Cluster_Image + Pull Images from Cluster + oai-nr-ue + caracal + + + + Custom_Command + Reboot USRP N310 + avra + ssh root@192.168.80.52 reboot ; sleep 45 + + + + Custom_Command + Reboot USRP N310 + caracal + ssh root@192.168.20.2 reboot ; sleep 45 + + + + Deploy_Object + Deploy gNB (TDD/Band78/40MHz/N310) in a container + ci-scripts/yaml_files/5g_sa_n310_gnb + 0 + 0 + + + + Deploy_Object + Deploy nrUE (TDD/Band78/40MHz/N310) in a container + ci-scripts/yaml_files/5g_sa_n310_nrue + 1 + 1 + + + + Attach_UE + Attach OAIUE + oai_ue_caracal + + + + Iperf + iperf (DL/20Mbps/UDP)(30 sec)(single-ue profile) + -u -b 20M -t 30 -i 1 -R + IPERF3 + oai_ue_caracal + 25 + 80 + + + + Iperf + iperf (UL/5Mbps/UDP)(30 sec)(single-ue profile) + -u -b 5M -t 30 -i 1 + IPERF3 + oai_ue_caracal + 25 + 80 + + + + Ping + Ping: 20pings in 20sec + oai_ue_caracal + -c 20 + 1 + 25 + + + + Ping + Ping: 100pings in 20sec + oai_ue_caracal + -c 100 -i 0.2 + 1 + 30 + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/5g_sa_n310_gnb + 0 + 0 + 20,100,100,100 + 20,100,100,100 + + + + Undeploy_Object + Undeploy nr UE + ci-scripts/yaml_files/5g_sa_n310_nrue + 1 + 1 + + + diff --git a/ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml b/ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml new file mode 100644 index 0000000000..0bac1e010b --- /dev/null +++ b/ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml @@ -0,0 +1,46 @@ + + + test-aw2s-cleanup + CleanUp of test servers + trash + + 111111 + 222222 + + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 1 + + + + From fb7343284262575e358cd0d3727ef9b004bf9d50 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 20:02:42 +0200 Subject: [PATCH 059/119] Jenkinsfile for oaiue pipeline created --- ci-scripts/Jenkinsfile-nrue | 242 ++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 ci-scripts/Jenkinsfile-nrue diff --git a/ci-scripts/Jenkinsfile-nrue b/ci-scripts/Jenkinsfile-nrue new file mode 100644 index 0000000000..ab5fe0747d --- /dev/null +++ b/ci-scripts/Jenkinsfile-nrue @@ -0,0 +1,242 @@ +#!/bin/groovy +/* + * 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 + */ + +// Location of the executor node +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the resource +def lockResources = [] +if (params.LockResources != null && params.LockResources.trim().length() > 0) + params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]} + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess = false +def eNB_TargetBranch + +// Flags +def scmEvent = false +def upstreamEvent = false + +//------------------------------------------------------------------------------- +// Pipeline start +pipeline { + agent { + label pythonExecutor + } + options { + timestamps() + ansiColor('xterm') + lock(extra: lockResources) + } + + stages { + stage ('Verify Parameters') { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + + JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' + JOB_TIMESTAMP = JOB_TIMESTAMP.trim() + + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + if (params.LockResources == null) { + echo "no LockResources given" + allParametersPresent = false + } + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_mergeRequest != null) { + eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + if (params.OC_Credentials == null) { + allParametersPresent = false + } + if (params.OC_ProjectName == null) { + allParametersPresent = false + } + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + + stage ("Deploy and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage ("Log Collection") { + steps { + script { + dir ('ci-scripts') { + // Zipping all archived log files + sh "mkdir test_logs" + sh "mv *.log* test_logs || true" + sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/" + sh "rm -rf *test_log*/" + if (fileExists("test_logs_${env.BUILD_ID}.zip")) { + archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" + } + if (fileExists("test_logs_CN.zip")){ + sh "mv test_logs_CN.zip test_logs_CN_${env.BUILD_ID}.zip" + archiveArtifacts artifacts: "test_logs_CN_${env.BUILD_ID}.zip" + } + if (fileExists("test_results.html")) { + sh "mv test_results.html test_results-${env.JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html" + } + } + } + } + } + } +} From 99e0291dbdf32141ce542680c9ae0510559c06d9 Mon Sep 17 00:00:00 2001 From: mir Date: Tue, 4 Jul 2023 22:33:05 +0200 Subject: [PATCH 060/119] Fix bug --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index d92c0124f1..cb53e682b6 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -934,7 +934,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); - totalDecode += nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + if(tasks_added > 0) + totalDecode += tasks_added; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } From cd3ecd61f48dc990f1046d721924c03e73855243 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Jul 2023 06:55:22 +0000 Subject: [PATCH 061/119] Clang format --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index cb53e682b6..b97bf1748e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -935,7 +935,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); - if(tasks_added > 0) + if (tasks_added > 0) totalDecode += tasks_added; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); From 7a2790ba68e8577c6ba3962217e8ed576e82be25 Mon Sep 17 00:00:00 2001 From: Angelo Athanassopoulos Date: Wed, 5 Jul 2023 23:28:45 +0200 Subject: [PATCH 062/119] NR SDAP - Bugfix for entity deletion This commit fixes the implementation for removing either a single SDAP entity or all the SDAP entities of a UE. --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 85 ++++++++++++++++++-------- openair2/SDAP/nr_sdap/nr_sdap_entity.h | 20 +++++- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index bc3ea0ad9d..25254e0905 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -468,41 +468,74 @@ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id) return NULL; } -int nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) +bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) { nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; - int pos = 0; - while (entityPtr != NULL) { - if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { - if (pos == 0) { - sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; - } - LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); - free(entityPtr); - return 1; - } - entityPtr = entityPtr->next_entity; - pos++; + nr_sdap_entity_t *entityPrev = NULL; + bool ret = false; + int upperBound = 0; + + if (entityPtr == NULL && (pdusession_id) * (pdusession_id - NGAP_MAX_PDU_SESSION) > 0) { + LOG_W(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n"); + return ret; } - return 0; + LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); + + if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { + sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + free(entityPtr); + LOG_D(SDAP, "Successfully deleted Entity.\n"); + ret = true; + } else { + while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL + && upperBound < SDAP_MAX_NUM_OF_ENTITIES) { + entityPrev = entityPtr; + entityPtr = entityPtr->next_entity; + upperBound++; + } + + if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { + entityPrev->next_entity = entityPtr->next_entity; + free(entityPtr); + LOG_D(SDAP, "Successfully deleted Entity.\n"); + ret = true; + } + } + LOG_W(SDAP, "Entity does not exist or it was not found.\n"); + return ret; } -void nr_sdap_delete_ue_entities(ue_id_t ue_id) +bool nr_sdap_delete_ue_entities(ue_id_t ue_id) { nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; - int pos = 0; - while (entityPtr != NULL) { - if (entityPtr->ue_id == ue_id) { - if (pos == 0) { - sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; - } - LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); - nr_sdap_entity_t *entityPrev = entityPtr; + nr_sdap_entity_t *entityPrev = NULL; + int upperBound = 0; + bool ret = false; + + if (entityPtr == NULL && (ue_id) * (ue_id - SDAP_MAX_UE_ID) > 0) { + LOG_W(SDAP, "SDAP entities not established or Invalid range of ue_id [0, 65536]\n"); + return ret; + } + + /* Handle scenario where ue_id matches the head of the list */ + while (entityPtr != NULL && entityPtr->ue_id == ue_id && upperBound < NGAP_MAX_DRBS_PER_UE) { + sdap_info.sdap_entity_llist = entityPtr->next_entity; + free(entityPtr); + entityPtr = sdap_info.sdap_entity_llist; + ret = true; + } + + while (entityPtr != NULL && upperBound < SDAP_MAX_NUM_OF_ENTITIES) { + if (entityPtr->ue_id != ue_id) { + entityPrev = entityPtr; + entityPtr = entityPtr->next_entity; + } else { + entityPrev->next_entity = entityPtr->next_entity; free(entityPtr); entityPtr = entityPrev->next_entity; - } else { - entityPtr = entityPtr->next_entity; + LOG_D(SDAP, "Successfully deleted Entity.\n"); + ret = true; } - pos++; } + return ret; } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index 4b5303a5b6..b90da9d380 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -44,6 +44,8 @@ #define SDAP_CTRL_PDU_MAP_DEF_DRB (0) #define SDAP_CTRL_PDU_MAP_RULE_DRB (1) #define SDAP_MAX_PDU (9000) +#define SDAP_MAX_NUM_OF_ENTITIES (NGAP_MAX_DRBS_PER_UE * MAX_MOBILES_PER_ENB) +#define SDAP_MAX_UE_ID (65536) /* * The values of QoS Flow ID (QFI) and Reflective QoS Indication, @@ -167,7 +169,21 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap /* Entity Handling Related Functions */ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id); -/* Entity Handling Related Functions */ -void delete_nr_sdap_entity(ue_id_t ue_id); +/** + * @brief Function to delete a single SDAP Entity based on the ue_id and pdusession_id. + * @note 1. SDAP entities may have the same ue_id. + * @note 2. SDAP entities may have the same pdusession_id, but not with the same ue_id. + * @note 3. The combination of ue_id and pdusession_id, is unique for each SDAP entity. + * @param[in] ue_id Unique identifier for the User Equipment. ID Range [0, 65536]. + * @param[in] pdusession_id Unique identifier for the Packet Data Unit Session. ID Range [0, 256]. + * @return True, if successfully deleted entity, false otherwise. + */ +bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id); +/** + * @brief Function to delete all SDAP Entities based on the ue_id. + * @param[in] ue_id Unique identifier for the User Equipment. ID Range [0, 65536]. + * @return True, it deleted at least one entity, false otherwise. + */ +bool nr_sdap_delete_ue_entities(ue_id_t ue_id); #endif From 26be073ff9ed0a8a910b879b7e7e8c60edce69ed Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 6 Jul 2023 10:22:15 +0200 Subject: [PATCH 063/119] CI: AW2S pipeline - disable retransmissions check --- ci-scripts/xml_files/container_sa_aw2s_asue.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 7959718eb0..d736dd69f0 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -161,8 +161,6 @@ ci-scripts/yaml_files/sa_aw2s_gnb 0 0 - 20,100,100,100 - 20,100,100,100 From 3256606285c525e4611ea6f82c61f5d04e5ae398 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 16 Jun 2023 21:04:41 +0200 Subject: [PATCH 064/119] Remove unused includes - openair2/ENB_APP/CONTROL_MODULES: this directory does not exist anymore - openair2/UTIL/{OMG,CLI,OMV}: not used anywhere --- CMakeLists.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 214a16b79a..89dc638787 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,22 +753,14 @@ include_directories("${OPENAIR3_DIR}/ocp-gtpu") include_directories("${OPENAIR3_DIR}/M3AP") include_directories("${OPENAIR3_DIR}/MME_APP") include_directories("${OPENAIR_DIR}/radio/COMMON") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/S1AP") include_directories("${OPENAIR2_DIR}/UTIL/OSA") include_directories("${OPENAIR2_DIR}/UTIL/MEM") include_directories("${OPENAIR2_DIR}/UTIL/LISTS") include_directories("${OPENAIR2_DIR}/UTIL/FIFO") include_directories("${OPENAIR2_DIR}/UTIL/MATH") include_directories("${OPENAIR2_DIR}/UTIL/TIMER") -include_directories("${OPENAIR2_DIR}/UTIL/OMG") include_directories("${OPENAIR2_DIR}/UTIL/OTG") -include_directories("${OPENAIR2_DIR}/UTIL/CLI") include_directories("${OPENAIR2_DIR}/UTIL/OPT") -include_directories("${OPENAIR2_DIR}/UTIL/OMV") include_directories("${OPENAIR_DIR}") ########### From 11f4bd9c32ca3fc7ba56021b7190342ef2709ae1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:06:20 +0200 Subject: [PATCH 065/119] Remove cmake NAS_NETLINK option This option is almost not referenced anywhere, and not documented. Remove it to avoid problems in the future. --- CMakeLists.txt | 1 - openair2/COMMON/platform_types.h | 5 ----- 2 files changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89dc638787..37895b1299 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -629,7 +629,6 @@ include_directories ("${OPENAIR_DIR}/radio/COMMON") ############################################################## add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????" ON) -add_boolean_option(NAS_NETLINK False "useless ??? Must be True to compile nasmesh driver without rtai ????" ON) add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????" ON) add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION with max 256 UE" ON) diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index c3d5999b62..6c388c3cd0 100644 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -30,13 +30,8 @@ #ifndef __PLATFORM_TYPES_H__ #define __PLATFORM_TYPES_H__ -#if !defined(NAS_NETLINK) #include #include -#else -#include -typedef void * intptr_t; -#endif //----------------------------------------------------------------------------- // GENERIC ACCESS STRATUM TYPES From 7ebdaf35c588625f8eecc4b381a16c4500a4de31 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:06:40 +0200 Subject: [PATCH 066/119] Remove cmake ENB_MODE option ENB_MODE is a cmake option to swap the order of include directories. This has historical reasons; before OAI used cmake, it was very sensitive to the order of includes. Nowadays, the order does not matter. Remove this option, and fix the compilation issues that arise while doing so. --- CMakeLists.txt | 23 +++++----------------- cmake_targets/at_commands/CMakeLists.txt | 1 - common/utils/T/check_vcd.c | 1 - openair2/F1AP/f1ap_common.h | 25 +++++++++--------------- openair2/M2AP/m2ap_MCE_defs.h | 1 + openair2/M2AP/m2ap_common.h | 19 ++++++------------ openair2/M2AP/m2ap_eNB_defs.h | 1 + openair2/X2AP/x2ap_common.h | 17 +++++----------- openair3/M3AP/m3ap_MCE_defs.h | 1 + openair3/M3AP/m3ap_MME_defs.h | 1 + openair3/M3AP/m3ap_common.h | 19 ++++++------------ openair3/NGAP/ngap_common.h | 9 --------- openair3/S1AP/s1ap_common.h | 22 +++++++-------------- openair3/SCTP/sctp_common.h | 14 ++++--------- 14 files changed, 46 insertions(+), 108 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37895b1299..b2be224013 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -636,11 +636,6 @@ add_boolean_option(PHY_TX_THREAD False "enable UE_EXPANSION w add_boolean_option(PRE_SCD_THREAD False "enable UE_EXPANSION with max 256 UE" ON) add_boolean_option(UESIM_EXPANSION False "enable UESIM_EXPANSION with max 256 UE" ON) -######################## -# Include order -########################## -add_boolean_option(ENB_MODE True "Swap the include directories between openair2 and openair3" ON) - ########################## # SCHEDULING/REAL-TIME/PERF options ########################## @@ -701,19 +696,11 @@ include_directories("${OPENAIR_BIN_DIR}") # Legacy exact order include_directories("${OPENAIR_DIR}/executables") -if(ENB_MODE) - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") -else() - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") -endif() +include_directories("${OPENAIR2_DIR}/COMMON") +include_directories("${OPENAIR2_DIR}/UTIL") +include_directories("${OPENAIR2_DIR}/UTIL/LOG") +include_directories("${OPENAIR3_DIR}/COMMON") +include_directories("${OPENAIR3_DIR}/UTILS") include_directories("${NFAPI_DIR}/nfapi/public_inc") include_directories("${NFAPI_DIR}/common/public_inc") include_directories("${NFAPI_DIR}/pnf/public_inc") diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt index 9e16576ba9..cda9163c9b 100755 --- a/cmake_targets/at_commands/CMakeLists.txt +++ b/cmake_targets/at_commands/CMakeLists.txt @@ -103,7 +103,6 @@ set (FIRMWARE_VERSION "No svn information") add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") add_boolean_option(LINUX True "????") -add_boolean_option(ENB_MODE True "????") # to avoid backtrace ########################## # NAS LAYER OPTIONS diff --git a/common/utils/T/check_vcd.c b/common/utils/T/check_vcd.c index 4a21e4d2f5..33ca58f947 100644 --- a/common/utils/T/check_vcd.c +++ b/common/utils/T/check_vcd.c @@ -15,7 +15,6 @@ /* VCD specific defines and includes * If the codebase changes, it may need to be updated */ -#define ENB_MODE #define ENABLE_USE_CPU_EXECUTION_TIME #include "../LOG/vcd_signal_dumper.c" diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index 2ae6352464..ff492820d7 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -340,6 +340,8 @@ #include "F1AP_Cells-To-Be-Broadcast-Item.h" #include "F1AP_QCI.h" +#include "f1ap_default_values.h" + #include "conversions.h" #include "platform_types.h" #include "common/utils/LOG/log.h" @@ -359,22 +361,13 @@ #include "assertions.h" -#if defined(ENB_MODE) - #include "common/utils/LOG/log.h" - #include "f1ap_default_values.h" - #define F1AP_ERROR(x, args...) LOG_E(F1AP, x, ##args) - #define F1AP_WARN(x, args...) LOG_W(F1AP, x, ##args) - #define F1AP_TRAF(x, args...) LOG_I(F1AP, x, ##args) - #define F1AP_INFO(x, args...) LOG_I(F1AP, x, ##args) - #define F1AP_DEBUG(x, args...) LOG_I(F1AP, x, ##args) -#else - //# include "mme_default_values.h" - #define F1AP_ERROR(x, args...) do { fprintf(stdout, "[F1AP][E]"x, ##args); } while(0) - #define F1AP_WARN(x, args...) do { fprintf(stdout, "[F1AP][W]"x, ##args); } while(0) - #define F1AP_TRAF(x, args...) do { fprintf(stdout, "[F1AP][T]"x, ##args); } while(0) - #define F1AP_INFO(x, args...) do { fprintf(stdout, "[F1AP][I]"x, ##args); } while(0) - #define F1AP_DEBUG(x, args...) do { fprintf(stdout, "[F1AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "f1ap_default_values.h" +#define F1AP_ERROR(x, args...) LOG_E(F1AP, x, ##args) +#define F1AP_WARN(x, args...) LOG_W(F1AP, x, ##args) +#define F1AP_TRAF(x, args...) LOG_I(F1AP, x, ##args) +#define F1AP_INFO(x, args...) LOG_I(F1AP, x, ##args) +#define F1AP_DEBUG(x, args...) LOG_I(F1AP, x, ##args) //Forward declaration #define F1AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ diff --git a/openair2/M2AP/m2ap_MCE_defs.h b/openair2/M2AP/m2ap_MCE_defs.h index 73183e89c2..dc8f9ff5ee 100644 --- a/openair2/M2AP/m2ap_MCE_defs.h +++ b/openair2/M2AP/m2ap_MCE_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m2ap_default_values.h" #include "m2ap_ids.h" //looks X2AP specific for HO #include "m2ap_timers.h" diff --git a/openair2/M2AP/m2ap_common.h b/openair2/M2AP/m2ap_common.h index c144c78dcf..7981eaa2a5 100644 --- a/openair2/M2AP/m2ap_common.h +++ b/openair2/M2AP/m2ap_common.h @@ -52,19 +52,12 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# include "m2ap_default_values.h" -# define M2AP_INFO(x, args...) LOG_I(M2AP, x, ##args) -# define M2AP_ERROR(x, args...) LOG_E(M2AP, x, ##args) -# define M2AP_WARN(x, args...) LOG_W(M2AP, x, ##args) -# define M2AP_DEBUG(x, args...) LOG_D(M2AP, x, ##args) -#else -# define M2AP_INFO(x, args...) do { fprintf(stdout, "[M2AP][I]"x, ##args); } while(0) -# define M2AP_ERROR(x, args...) do { fprintf(stdout, "[M2AP][E]"x, ##args); } while(0) -# define M2AP_WARN(x, args...) do { fprintf(stdout, "[M2AP][W]"x, ##args); } while(0) -# define M2AP_DEBUG(x, args...) do { fprintf(stdout, "[M2AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "m2ap_default_values.h" +#define M2AP_INFO(x, args...) LOG_I(M2AP, x, ##args) +#define M2AP_ERROR(x, args...) LOG_E(M2AP, x, ##args) +#define M2AP_WARN(x, args...) LOG_W(M2AP, x, ##args) +#define M2AP_DEBUG(x, args...) LOG_D(M2AP, x, ##args) #define M2AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do {\ diff --git a/openair2/M2AP/m2ap_eNB_defs.h b/openair2/M2AP/m2ap_eNB_defs.h index 0b30c33d80..4cc409400e 100644 --- a/openair2/M2AP/m2ap_eNB_defs.h +++ b/openair2/M2AP/m2ap_eNB_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m2ap_default_values.h" #include "m2ap_ids.h" //looks X2AP specific for HO #include "m2ap_timers.h" diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index e35fd30adf..9535e9fb69 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -49,18 +49,11 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args) -# define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args) -# define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args) -# define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args) -#else -# define X2AP_INFO(x, args...) do { fprintf(stdout, "[X2AP][I]"x, ##args); } while(0) -# define X2AP_ERROR(x, args...) do { fprintf(stdout, "[X2AP][E]"x, ##args); } while(0) -# define X2AP_WARN(x, args...) do { fprintf(stdout, "[X2AP][W]"x, ##args); } while(0) -# define X2AP_DEBUG(x, args...) do { fprintf(stdout, "[X2AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args) +#define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args) +#define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args) +#define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args) #define X2AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do {\ diff --git a/openair3/M3AP/m3ap_MCE_defs.h b/openair3/M3AP/m3ap_MCE_defs.h index 4dcb2b4db0..c90ba38a66 100644 --- a/openair3/M3AP/m3ap_MCE_defs.h +++ b/openair3/M3AP/m3ap_MCE_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m3ap_default_values.h" #include "m3ap_ids.h" //looks X2AP specific for HO #include "m3ap_timers.h" diff --git a/openair3/M3AP/m3ap_MME_defs.h b/openair3/M3AP/m3ap_MME_defs.h index 6608587cc3..7d3186915f 100644 --- a/openair3/M3AP/m3ap_MME_defs.h +++ b/openair3/M3AP/m3ap_MME_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m3ap_default_values.h" #include "m3ap_ids.h" //looks X2AP specific for HO #include "m3ap_timers.h" diff --git a/openair3/M3AP/m3ap_common.h b/openair3/M3AP/m3ap_common.h index cf2189a243..5d40b29363 100644 --- a/openair3/M3AP/m3ap_common.h +++ b/openair3/M3AP/m3ap_common.h @@ -50,19 +50,12 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# include "m3ap_default_values.h" -# define M3AP_INFO(x, args...) LOG_I(M3AP, x, ##args) -# define M3AP_ERROR(x, args...) LOG_E(M3AP, x, ##args) -# define M3AP_WARN(x, args...) LOG_W(M3AP, x, ##args) -# define M3AP_DEBUG(x, args...) LOG_D(M3AP, x, ##args) -#else -# define M3AP_INFO(x, args...) do { fprintf(stdout, "[M3AP][I]"x, ##args); } while(0) -# define M3AP_ERROR(x, args...) do { fprintf(stdout, "[M3AP][E]"x, ##args); } while(0) -# define M3AP_WARN(x, args...) do { fprintf(stdout, "[M3AP][W]"x, ##args); } while(0) -# define M3AP_DEBUG(x, args...) do { fprintf(stdout, "[M3AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "m3ap_default_values.h" +#define M3AP_INFO(x, args...) LOG_I(M3AP, x, ##args) +#define M3AP_ERROR(x, args...) LOG_E(M3AP, x, ##args) +#define M3AP_WARN(x, args...) LOG_W(M3AP, x, ##args) +#define M3AP_DEBUG(x, args...) LOG_D(M3AP, x, ##args) #define M3AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do {\ diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index 8de2542766..41f6093c08 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -96,7 +96,6 @@ extern int asn_debug; extern int asn1_xer_print; -#if defined(ENB_MODE) # include "common/utils/LOG/log.h" # include "ngap_gNB_default_values.h" # define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args) @@ -104,14 +103,6 @@ extern int asn1_xer_print; # define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args) # define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args) # define NGAP_DEBUG(x, args...) LOG_I(NGAP, x, ##args) -#else -# include "amf_default_values.h" -# define NGAP_ERROR(x, args...) do { fprintf(stdout, "[NGAP][E]"x, ##args); } while(0) -# define NGAP_WARN(x, args...) do { fprintf(stdout, "[NGAP][W]"x, ##args); } while(0) -# define NGAP_TRAF(x, args...) do { fprintf(stdout, "[NGAP][T]"x, ##args); } while(0) -# define NGAP_INFO(x, args...) do { fprintf(stdout, "[NGAP][I]"x, ##args); } while(0) -# define NGAP_DEBUG(x, args...) do { fprintf(stdout, "[NGAP][D]"x, ##args); } while(0) -#endif #define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do { \ diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index bdfc9b9f6f..65baea44c6 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -52,21 +52,13 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# include "s1ap_eNB_default_values.h" -# define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args) -# define S1AP_WARN(x, args...) LOG_W(S1AP, x, ##args) -# define S1AP_TRAF(x, args...) LOG_I(S1AP, x, ##args) -# define S1AP_INFO(x, args...) LOG_I(S1AP, x, ##args) -# define S1AP_DEBUG(x, args...) LOG_I(S1AP, x, ##args) -#else -# define S1AP_ERROR(x, args...) do { fprintf(stdout, "[S1AP][E]"x, ##args); } while(0) -# define S1AP_WARN(x, args...) do { fprintf(stdout, "[S1AP][W]"x, ##args); } while(0) -# define S1AP_TRAF(x, args...) do { fprintf(stdout, "[S1AP][T]"x, ##args); } while(0) -# define S1AP_INFO(x, args...) do { fprintf(stdout, "[S1AP][I]"x, ##args); } while(0) -# define S1AP_DEBUG(x, args...) do { fprintf(stdout, "[S1AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "s1ap_eNB_default_values.h" +#define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args) +#define S1AP_WARN(x, args...) LOG_W(S1AP, x, ##args) +#define S1AP_TRAF(x, args...) LOG_I(S1AP, x, ##args) +#define S1AP_INFO(x, args...) LOG_I(S1AP, x, ##args) +#define S1AP_DEBUG(x, args...) LOG_I(S1AP, x, ##args) #define S1AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ diff --git a/openair3/SCTP/sctp_common.h b/openair3/SCTP/sctp_common.h index 024feb8b09..3708ae52a0 100644 --- a/openair3/SCTP/sctp_common.h +++ b/openair3/SCTP/sctp_common.h @@ -34,16 +34,10 @@ #include #include -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# define SCTP_ERROR(x, args...) LOG_E(SCTP, x, ##args) -# define SCTP_DEBUG(x, args...) LOG_D(SCTP, x, ##args) -# define SCTP_WARN(x, args...) LOG_W(SCTP, x, ##args) -#else -# define SCTP_ERROR(x, args...) do { fprintf(stderr, "[SCTP][E]"x, ##args); } while(0) -# define SCTP_DEBUG(x, args...) do { fprintf(stdout, "[SCTP][D]"x, ##args); } while(0) -# define SCTP_WARN(x, args...) do { fprintf(stdout, "[SCTP][W]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#define SCTP_ERROR(x, args...) LOG_E(SCTP, x, ##args) +#define SCTP_DEBUG(x, args...) LOG_D(SCTP, x, ##args) +#define SCTP_WARN(x, args...) LOG_W(SCTP, x, ##args) int sctp_set_init_opt(int sd, uint16_t instreams, uint16_t outstreams, uint16_t max_attempts, uint16_t init_timeout); From 5b534c957ffd3731a85c57db5088da8dee740765 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:07:23 +0200 Subject: [PATCH 067/119] Remove unused cmake options and commented code - LINUX: option to optionally set a sighandler for certain simulators, no practical relevance - LINUX_LIST: not used anywhere - DEBUG_DLSCH: referenced in the code, but those files have a separate (commented) line `#define DEBUG_DLSCH`; probably never used - LINK_ENB_PDCP_TO_IP_DRIVER, LINK_ENB_PDCP_TO_GTPV1U: commented in cmake, although they are referenced. It is likely that code behaves unexpected if re-enabled; we therefore remove these options to avoid future problems - Remove some more commented code --- CMakeLists.txt | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2be224013..644360da7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -642,8 +642,6 @@ add_boolean_option(UESIM_EXPANSION False "enable UESIM_EXPANSIO add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME False "Add data in vcd traces: disable it if perf issues" ON) add_boolean_option(ENABLE_VCD False "always true now, time measurements of proc calls and var displays" ON) add_boolean_option(ENABLE_VCD_FIFO False "time measurements of proc calls and var displays sent to FIFO (one more thread)" ON) -add_boolean_option(LINUX False "used in weird memcpy() in pdcp.c ???" ON) -add_boolean_option(LINUX_LIST False "used only in lists.c: either use OAI implementation of lists or Linux one (should be ON, but it is False" ON) ########################## # PHY options @@ -653,7 +651,6 @@ add_integer_option(MAX_NUM_CCs 1 "????" ON) add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator" ON) add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options" ON) add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures" ON) -add_boolean_option(DEBUG_DLSCH False "Enable debugging of DLSCH physical layer channel" ON) add_boolean_option(MEX False "Enabling compilation with mex" ON) ########################## @@ -664,22 +661,10 @@ add_boolean_option(NAS_BUILT_IN_UE True "UE NAS layer present in this e add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)" ON) -########################## -# PDCP LAYER OPTIONS -########################## -#add_boolean_option(LINK_ENB_PDCP_TO_IP_DRIVER False "For eNB, PDCP communicate with a IP driver") -#add_boolean_option(LINK_ENB_PDCP_TO_GTPV1U True "For eNB, PDCP communicate with GTP-U protocol (eNB<->S-GW)") - ########################## # RRC LAYER OPTIONS ########################## -add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the RLC mode to AM for the default bearer, otherwise it is UM." ON) - - -########################## -# S1AP LAYER OPTIONS -########################## -# none +add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the LTE RLC mode to AM for the default bearer, otherwise it is UM." ON) # add the binary tree to the search path for include files ####################################################### @@ -1340,12 +1325,6 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c - #hack: include these files to compile the nr phy simulators - #these files should not be here, will be removed at some point when the - #computation is done directly inside nr_pdcp_integrity_nia1.c instead - #of reusing code of osa_stream_eia.c - #${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c - #${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c ) set(NR_SDAP_SRC From cd6dd99d439a5d748d5bcfe0f990332bcad7618b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:32:41 +0200 Subject: [PATCH 068/119] Remove CMakeLists.txt reference to openpgm: it is not used --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 644360da7e..5b27b251d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,13 +88,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") endif (${RF_BOARD} STREQUAL "OAI_USRP") -pkg_search_module(OPENPGM openpgm-5.1 openpgm-5.2) -if(NOT ${OPENPGM_FOUND}) - message("PACKAGE openpgm-5.1 is required by binaries such as oaisim: will fail later if this target is built") -else() - include_directories(${OPENPGM_INCLUDE_DIRS}) -endif() - pkg_search_module(XPM xpm) if(NOT ${XPM_FOUND}) message("PACKAGE xpm not found: some targets will fail") From 439b6027cfc734debcd53b5406d8ab44c390903c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:32:55 +0200 Subject: [PATCH 069/119] Remove CMakeLists.txt reference to xpm: it is not used --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b27b251d2..8c189c5e7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,13 +88,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") endif (${RF_BOARD} STREQUAL "OAI_USRP") -pkg_search_module(XPM xpm) -if(NOT ${XPM_FOUND}) - message("PACKAGE xpm not found: some targets will fail") -else() - include_directories(${XPM_INCLUDE_DIRS}) -endif() - # Atlas is required by some packages, but not found in pkg-config # So, here are some hacks here. Hope this gets fixed in future! if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") From 25edebb593e48e3a2352ee30a424114ae3415fbc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:52:05 +0200 Subject: [PATCH 070/119] Refactor CMakeLists.txt OpenSSL handling First, we do not include openssl globally using `include_directories()`, as most modules don't need it. Further, it is linked into SECURITY, and removed from all other targets (they don't need it, only SECURITY). Finally, remove a header include in NR PDCP that is not needed --- CMakeLists.txt | 21 +++++++++---------- .../LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c | 1 - 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c189c5e7b..da0e80fff1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,6 @@ include("cmake_targets/macros.cmake") ################################### include(FindPkgConfig) -pkg_search_module(OPENSSL openssl REQUIRED) -include_directories(${OPENSSL_INCLUDE_DIRS}) - pkg_search_module(CONFIG libconfig REQUIRED) include_directories(${CONFIG_INCLUDE_DIRS}) @@ -759,8 +756,10 @@ set(SECURITY_SRC ${OPENAIR3_DIR}/SECU/nas_stream_eia2.c ) +pkg_check_modules(OpenSSL openssl REQUIRED) add_library(SECURITY ${SECURITY_SRC} $) target_include_directories(SECURITY PRIVATE ${OPENAIR_DIR}/common/utils/ds/) +target_link_libraries(SECURITY PRIVATE ${OpenSSL_LIBRARIES}) # Physical Channel Procedures Scheduling ################################" @@ -2117,7 +2116,7 @@ target_link_libraries(lte-softmodem PRIVATE ${NAS_UE_LIB} ITTI SIMU SIMU_ETH -Wl,--end-group z dl) -target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp) +target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2178,7 +2177,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES} -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2219,7 +2218,7 @@ target_link_libraries(nr-softmodem PRIVATE x2ap f1ap m2ap m3ap e1ap -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2281,7 +2280,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH -Wl,--end-group z dl) -target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${ATLAS_LIBRARIES}) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2420,7 +2419,7 @@ add_executable(nr_dlsim ) target_link_libraries(nr_dlsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2432,7 +2431,7 @@ add_executable(nr_prachsim ${SHLIB_LOADER_SOURCES}) target_link_libraries(nr_prachsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl) + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl) target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulschsim @@ -2469,7 +2468,7 @@ endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2507,7 +2506,7 @@ foreach(myExe s1ap ${OPENAIR3_DIR}/TEST/test_${myExe}.c ) target_link_libraries (test_${myExe} - -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB + -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} CONFIG_LIB ) endforeach(myExe) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c index a005bbbdf6..3dbf15136b 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "openair3/SECU/secu_defs.h" #include "openair3/SECU/key_nas_deriver.h" From 25f2a48265e529d459b68bbbc2d732d56bc61ed3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:15:05 +0200 Subject: [PATCH 071/119] Remove targets/Makerules: it is not used --- targets/Makerules | 59 ----------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 targets/Makerules diff --git a/targets/Makerules b/targets/Makerules deleted file mode 100644 index 3488c54762..0000000000 --- a/targets/Makerules +++ /dev/null @@ -1,59 +0,0 @@ -CC = gcc -MPICC = gcc #mpicc -RM_F_V = rm -f -v -PWD = $(shell pwd) -export CC -export MPICC -export RM_F_V -export PWD - -OBJS_DIR := $(PWD)/objs - -SVN_REV := $(shell svnversion -n .) -DATE_REV := $(shell date '+%F %T') - -NUM_CORES:=$(shell cat /proc/cpuinfo | grep processor | wc -l) - -OPENSSL_FOUND := $(shell if pkg-config --exists openssl; then echo "1" ; else echo "0"; fi) -ifeq ($(OPENSSL_FOUND), 1) -OPENSSL_LIBS := $(shell pkg-config --libs openssl) -#else -#@echo "package openssl not installed" -endif - -PGM_FOUND := $(shell if pkg-config --exists openpgm-5.1; then echo "1" ; else echo "0"; fi) -ifeq ($(PGM_FOUND), 1) -PGM_CFLAGS := $(shell pkg-config --cflags openpgm-5.1) -PGM_LIBS := $(shell pkg-config --libs openpgm-5.1) -#else -#@echo "package pgm not installed" -endif - -LIBXML2_FOUND := $(shell if pkg-config --exists libxml-2.0; then echo "1" ; else echo "0"; fi) -ifeq ($(LIBXML2_FOUND), 1) -LIBXML2_CFLAGS := $(shell pkg-config --cflags libxml-2.0) -LIBXML2_LIBS := $(shell pkg-config --libs libxml-2.0) -#else -#@echo "package libxml2 not installed" -endif - -XPM_FOUND := $(shell if pkg-config --exists xpm; then echo "1" ; else echo "0"; fi) -ifeq ($(XPM_FOUND), 1) -XPM_LIBS := $(shell pkg-config --libs xpm) -#else -#@echo "package xmp not installed" -endif - -LIBBLAS_FOUND := $(shell if [ -f /usr/include/cblas.h ]; then echo "1"; else echo "0"; fi) -ifeq ($(LIBBLAS_FOUND), 1) -LIBBLAS_LIBS := -lblas -else -$(error "libblas not found, please install it") -endif - -#Export common libs -LIBS = \ - -lm \ - $(LIBBLAS_LIBS) \ - $(LIBXML2_LIBS) \ - $(XPM_LIBS) From be4c03c90cfdf5ca033f27f6659919d2f210bf20 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:13:41 +0200 Subject: [PATCH 072/119] Properly check and link (C)BLAS and LAPACKE dependencies Instead of using the adhoc code for checking and including (globally!) BLAS/LAPACKE, use PkgConfig to correctly identify libs (see deleted comment: "Hope this gets fixed in future!" -- you are welcome). Next, only link into those libraries that need it (PHY_UE, SIMU). Note that only RHEL also needs cblas, so it is a non-REQUIREd dependency that is only linked in if available. Further, take out linking into all other modules, as they don't need it. In the source code, take out preprocessor directives to correctly include headers -- that is cmake's job, which it does just fine now. --- CMakeLists.txt | 85 ++++++------------- .../PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c | 10 +-- .../linear_preprocessing_rec.c | 5 -- 3 files changed, 30 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da0e80fff1..18d46ffdda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,42 +85,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") endif (${RF_BOARD} STREQUAL "OAI_USRP") -# Atlas is required by some packages, but not found in pkg-config -# So, here are some hacks here. Hope this gets fixed in future! -if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") - include_directories("/usr/include/atlas") - LINK_DIRECTORIES("/usr/lib/lapack") - LINK_DIRECTORIES("/usr/lib64") - LINK_DIRECTORIES("/usr/lib64/atlas") #Added because atlas libraries in CentOS 7 are here! - - if(EXISTS "/usr/lib64/libblas.so" OR EXISTS "/usr/lib/libblas.so") #Case for CentOS7 - list(APPEND ATLAS_LIBRARIES blas) - - else() # Case for Ubuntu - list(APPEND ATLAS_LIBRARIES cblas) - endif() - - if(EXISTS "/usr/lib/atlas/libtatlas.so" OR EXISTS "/usr/lib64/atlas/libtatlas.so") #Case for CentOS7 - list(APPEND ATLAS_LIBRARIES tatlas) - else() - list(APPEND ATLAS_LIBRARIES atlas) #Case for Ubuntu - endif() - - list(APPEND ATLAS_LIBRARIES lapack) - -# for ubuntu 17.10, directories are different -elseif(EXISTS "/usr/include/x86_64-linux-gnu/cblas.h") - - include_directories("/usr/include/x86_64-linux-gnu") - LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - list(APPEND ATLAS_LIBRARIES cblas) - list(APPEND ATLAS_LIBRARIES atlas) - list(APPEND ATLAS_LIBRARIES lapack) - -else() - message("No Blas/Atlas libs found, some targets will fail") -endif() - ######################################################### # Base directories, compatible with legacy OAI building # ######################################################### @@ -1228,8 +1192,16 @@ target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs) add_library(PHY ${PHY_SRC}) target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +pkg_check_modules(blas REQUIRED blas) +pkg_check_modules(lapacke REQUIRED lapacke) + add_library(PHY_UE ${PHY_SRC_UE}) target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +# RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` will +# be empty for Ubuntu, a no-op +pkg_check_modules(cblas cblas) +target_link_libraries(PHY_UE PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES}) +target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS}) add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) @@ -1971,6 +1943,8 @@ set (SIMUSRC ) add_library(SIMU STATIC ${SIMUSRC} ) target_include_directories(SIMU PUBLIC ${OPENAIR1_DIR}/SIMULATION/TOOLS ${OPENAIR1_DIR}/SIMULATION/RF) +target_link_libraries(SIMU PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES}) +target_include_directories(SIMU PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS}) # Qt-based scope add_boolean_option(ENABLE_NRQTSCOPE OFF "Build the Qt-Scope" OFF) @@ -2001,15 +1975,12 @@ include_directories("${NFAPI_DIR}/nfapi/inc") include_directories("${NFAPI_DIR}/sim_common/inc") include_directories("${NFAPI_DIR}/pnf_sim/inc") -list(APPEND ATLAS_LIBRARIES lapack lapacke) - - add_library(rfsimulator MODULE ${OPENAIR_DIR}/radio/rfsimulator/simulator.c ${OPENAIR_DIR}/radio/rfsimulator/apply_channelmod.c ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c ) -target_link_libraries(rfsimulator PRIVATE SIMU ${ATLAS_LIBRARIES}) +target_link_libraries(rfsimulator PRIVATE SIMU) add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c @@ -2174,10 +2145,10 @@ target_link_libraries(lte-uesoftmodem PRIVATE lte_rrc nr_rrc s1ap x2ap m2ap m3ap SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES} + ${NAS_UE_LIB} ITTI -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2218,7 +2189,7 @@ target_link_libraries(nr-softmodem PRIVATE x2ap f1ap m2ap m3ap e1ap -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2277,10 +2248,10 @@ target_link_libraries(nr-uesoftmodem PRIVATE nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB - ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH + ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH -Wl,--end-group z dl) -target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES}) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2310,7 +2281,7 @@ add_executable(dlsim_tm4 ) target_link_libraries (dlsim_tm4 -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${ATLAS_LIBRARIES} ${T_LIB} + pthread m rt CONFIG_LIB ${T_LIB} ) add_executable(rftest @@ -2331,7 +2302,7 @@ add_executable(polartest ) target_link_libraries(polartest PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_COMMON PHY_NR_UE CONFIG_LIB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl + m pthread dl ) add_executable(smallblocktest @@ -2343,7 +2314,7 @@ add_executable(smallblocktest target_link_libraries(smallblocktest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl + m pthread dl ) @@ -2360,7 +2331,7 @@ if (ENABLE_LDPC_CUDA) endif() target_link_libraries(ldpctest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl + m pthread dl ) add_executable(nr_dlschsim @@ -2372,7 +2343,7 @@ add_executable(nr_dlschsim ) target_link_libraries(nr_dlschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs) @@ -2385,7 +2356,7 @@ add_executable(nr_pbchsim ) target_link_libraries(nr_pbchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2400,7 +2371,7 @@ add_executable(nr_pucchsim ) target_link_libraries(nr_pucchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2419,7 +2390,7 @@ add_executable(nr_dlsim ) target_link_libraries(nr_dlsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2431,7 +2402,7 @@ add_executable(nr_prachsim ${SHLIB_LOADER_SOURCES}) target_link_libraries(nr_prachsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl) + m pthread ${T_LIB} ITTI dl) target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulschsim @@ -2444,7 +2415,7 @@ add_executable(nr_ulschsim ) target_link_libraries(nr_ulschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2468,7 +2439,7 @@ endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2485,7 +2456,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ) target_link_libraries (${myExe} PRIVATE -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${ATLAS_LIBRARIES} ${T_LIB} dl + pthread m rt CONFIG_LIB ${T_LIB} dl ) target_link_libraries(${myExe} PRIVATE asn1_lte_rrc_hdrs) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index fb0484a5f9..416a5dbf39 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -41,14 +41,8 @@ #include #include #include -#if defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796 && RHEL_RELEASE_CODE != 2403 - #include - #include -#else - #include - #include -#endif -#include +#include +#include #include "linear_preprocessing_rec.h" //#define DEBUG_MMSE diff --git a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c index 83c74389cf..59da43e564 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c @@ -14,13 +14,8 @@ data storage. */ #include #include #include -#if defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796 && RHEL_RELEASE_CODE != 2403 -#include -#include -#else #include #include -#endif //#define DEBUG_PREPROC From 28ec4944a54656d8103abcd6ad8557020d99e029 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:58:01 +0200 Subject: [PATCH 073/119] Fix minimal_stub.c It uses definitions from stdlib.h, so include it. --- common/utils/minimal_stub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c index be9c1b399d..64f2e3faa9 100644 --- a/common/utils/minimal_stub.c +++ b/common/utils/minimal_stub.c @@ -1,3 +1,5 @@ +#include + #ifndef T_TRACER int T_stdout; #endif From 387f5e4118b530baf2b8d89f0fc511d1d2cc67c6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:15:53 +0200 Subject: [PATCH 074/119] Make shlib_loader OBJECT library to prevent multiple compilations Including sources in targets makes that file being compiled multiple times. Instead, define an OBJECT library (i.e., it is only compiled, but not linked), and link it into each target that uses it. --- CMakeLists.txt | 68 ++++++++---------------- cmake_targets/at_commands/CMakeLists.txt | 2 - 2 files changed, 23 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d46ffdda..2ae2cdaca4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -450,10 +450,11 @@ add_library(CONFIG_LIB target_link_libraries(CONFIG_LIB PRIVATE dl UTIL) add_library(params_libconfig MODULE ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c) target_link_libraries(params_libconfig config) + # shared library loader -set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c -) +add_library(shlib_loader OBJECT common/utils/load_module_shlib.c) +target_link_libraries(shlib_loader PRIVATE CONFIG_LIB) + # include RF devices / transport protocols library modules ###################################################################### @@ -1910,11 +1911,6 @@ set (NBIOT_SOURCES ) add_library(NB_IoT MODULE ${NBIOT_SOURCES} ) -# shared library loader -set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c - ) - add_library(LIB_5GNAS_GNB ${NAS_SRC}/COMMON/nr_common.c ${NAS_SRC}/gNB/network_process_nas.c @@ -2076,7 +2072,6 @@ add_executable(lte-softmodem ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) add_dependencies(lte-softmodem oai_iqplayer) @@ -2084,7 +2079,7 @@ target_link_libraries(lte-softmodem PRIVATE -Wl,--start-group lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${NAS_UE_LIB} ITTI SIMU SIMU_ETH + ${NAS_UE_LIB} ITTI SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) @@ -2101,12 +2096,10 @@ add_executable(oairu ${OPENAIR_DIR}/executables/main_ru.c ${T_SOURCE} ${OPENAIR_DIR}/common/utils/lte/prach_utils.c - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(oairu PRIVATE -Wl,--start-group - SCHED_RU_LIB - PHY_COMMON PHY_RU UTIL + SCHED_RU_LIB PHY_COMMON PHY_RU UTIL shlib_loader -Wl,--end-group z dl) target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB}) @@ -2134,7 +2127,6 @@ add_executable(lte-uesoftmodem ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) if (NOT ${NOS1}) @@ -2145,7 +2137,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE lte_rrc nr_rrc s1ap x2ap m2ap m3ap SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${NAS_UE_LIB} ITTI + ${NAS_UE_LIB} ITTI shlib_loader -Wl,--end-group z dl) target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) @@ -2178,7 +2170,6 @@ add_executable(nr-softmodem ${PHY_INTERFACE_DIR}/queue_t.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr-softmodem PRIVATE @@ -2186,7 +2177,7 @@ target_link_libraries(nr-softmodem PRIVATE UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY ITTI ${NAS_UE_LIB} lte_rrc nr_rrc ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH - x2ap f1ap m2ap m3ap e1ap + x2ap f1ap m2ap m3ap e1ap shlib_loader -Wl,--end-group z dl) target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) @@ -2212,13 +2203,12 @@ add_executable(nr-cuup ${NR_PDCP_SRC} ${NR_SDAP_SRC} ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr-cuup PRIVATE CONFIG_LIB ITTI SCTP_CLIENT GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH - z sctp dl pthread) + z sctp dl pthread shlib_loader) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) # nr-uesoftmodem is UE implementation @@ -2240,7 +2230,6 @@ add_executable(nr-uesoftmodem ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr-uesoftmodem PRIVATE @@ -2248,7 +2237,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB - ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH + ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES}) @@ -2289,16 +2278,14 @@ add_executable(rftest ${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_scope.c ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/executables/softmodem-common.c - ${SHLIB_LOADER_SOURCES} ) -target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m ${T_LIB} ) +target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m ${T_LIB} shlib_loader) target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_executable(polartest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(polartest PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_COMMON PHY_NR_UE CONFIG_LIB -Wl,--end-group @@ -2309,12 +2296,11 @@ add_executable(smallblocktest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/smallblocktest.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(smallblocktest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread dl + m pthread dl shlib_loader ) @@ -2322,7 +2308,6 @@ add_executable(ldpctest ${PHY_NR_CODINGIF} ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_parityCheck) @@ -2330,8 +2315,8 @@ if (ENABLE_LDPC_CUDA) add_dependencies(ldpctest ldpc_cuda) endif() target_link_libraries(ldpctest PRIVATE - -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread dl + -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group + m pthread dl shlib_loader ) add_executable(nr_dlschsim @@ -2339,11 +2324,10 @@ add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_dlschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs) @@ -2352,11 +2336,10 @@ add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_pbchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2367,11 +2350,10 @@ add_executable(nr_pucchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_pucchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2386,11 +2368,10 @@ add_executable(nr_dlsim ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_dlsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2399,10 +2380,10 @@ add_executable(nr_prachsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES}) +) target_link_libraries(nr_prachsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group - m pthread ${T_LIB} ITTI dl) + m pthread ${T_LIB} ITTI dl shlib_loader) target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulschsim @@ -2411,11 +2392,10 @@ add_executable(nr_ulschsim ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${PHY_INTERFACE_DIR}/queue_t.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_ulschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2430,7 +2410,6 @@ add_executable(nr_ulsim ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) if (ENABLE_LDPC_T1) @@ -2439,7 +2418,7 @@ endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2451,12 +2430,11 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ${NFAPI_USER_DIR}/nfapi.c ) target_link_libraries (${myExe} PRIVATE -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${T_LIB} dl + pthread m rt CONFIG_LIB ${T_LIB} dl shlib_loader ) target_link_libraries(${myExe} PRIVATE asn1_lte_rrc_hdrs) diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt index cda9163c9b..3891af37ab 100755 --- a/cmake_targets/at_commands/CMakeLists.txt +++ b/cmake_targets/at_commands/CMakeLists.txt @@ -102,8 +102,6 @@ find_package(Threads REQUIRED) set (FIRMWARE_VERSION "No svn information") add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") -add_boolean_option(LINUX True "????") - ########################## # NAS LAYER OPTIONS ########################## From 187519052161a34beffd7c95a7b756908eb786a9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:24:08 +0200 Subject: [PATCH 075/119] Repair rftest - needs forms library, so link it - fix warnings --- CMakeLists.txt | 2 +- openair1/PHY/TOOLS/calibration_test.c | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ae2cdaca4..1083c18c57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2279,7 +2279,7 @@ add_executable(rftest ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/executables/softmodem-common.c ) -target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m ${T_LIB} shlib_loader) +target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader) target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_executable(polartest diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index 5d03d68c57..4dc3d658fe 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -50,7 +50,6 @@ int main(int argc, char **argv) { int N_RB=50; - int subCarrierFreq=30e3; int sampling_rate=30.72e6; int DFT=2048; int TxAdvanceInDFTSize=12; @@ -325,17 +324,8 @@ int main(int argc, char **argv) { while(!oai_exit) { for (int i=0; i Date: Sat, 17 Jun 2023 17:05:30 +0200 Subject: [PATCH 076/119] CONFIG_LIB: do not include libconfig headers globally Use target_include_directories() only on relevant targets. Remove from some targets that don't use the config module. --- CMakeLists.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1083c18c57..63b69e6c3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,6 @@ include("cmake_targets/macros.cmake") ################################### include(FindPkgConfig) -pkg_search_module(CONFIG libconfig REQUIRED) -include_directories(${CONFIG_INCLUDE_DIRS}) - pkg_search_module(CRYPTO libcrypto REQUIRED) include_directories(${CRYPTO_INCLUDE_DIRS}) @@ -440,16 +437,20 @@ target_link_libraries(f1ap PRIVATE ngap nr_rrc) add_list1_option(NB_ANTENNAS_RX "4" "Number of antennas in reception" "1" "2" "4") add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4") -#NOKIA config enhancement set (CONFIG_ROOTDIR ${OPENAIR_DIR}/common/config) add_library(CONFIG_LIB ${CONFIG_ROOTDIR}/config_load_configmodule.c ${CONFIG_ROOTDIR}/config_userapi.c ${CONFIG_ROOTDIR}/config_cmdline.c ) + +# CONFIG_LIB is a wrapper around a particular config implementation, default is +# libconfig in params_libconfig below +pkg_check_modules(libconfig REQUIRED libconfig) target_link_libraries(CONFIG_LIB PRIVATE dl UTIL) add_library(params_libconfig MODULE ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c) -target_link_libraries(params_libconfig config) +target_include_directories(params_libconfig PRIVATE ${libconfig_INCLUDE_DIRS}) +target_link_libraries(params_libconfig PRIVATE ${libconfig_LIBRARIES}) # shared library loader add_library(shlib_loader OBJECT common/utils/load_module_shlib.c) @@ -1234,7 +1235,7 @@ set(PHY_MEX_UE ${OPENAIR_DIR}/common/utils/T/T.c ${OPENAIR_DIR}/common/utils/T/local_tracer.c ) -add_library(PHY_MEX ${PHY_MEX_UE} ${CONFIG_LIB}) +add_library(PHY_MEX ${PHY_MEX_UE}) target_link_libraries(PHY_MEX PRIVATE asn1_lte_rrc_hdrs) #Layer 2 library @@ -2029,7 +2030,7 @@ add_library(minimal_lib ${OPENAIR_DIR}/common/utils/minimal_stub.c ${T_SOURCE} ) -target_link_libraries(minimal_lib pthread dl ${T_LIB} CONFIG_LIB) +target_link_libraries(minimal_lib pthread dl ${T_LIB}) add_executable(nfapi_test ${OPENAIR_DIR}/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c @@ -2047,7 +2048,7 @@ target_link_libraries (measurement_display minimal_lib) add_executable(test5Gnas ${OPENAIR_DIR}/openair3/TEST/test5Gnas.c ) -target_link_libraries (test5Gnas LIB_5GNAS_GNB CONFIG_LIB minimal_lib ) +target_link_libraries (test5Gnas LIB_5GNAS_GNB minimal_lib ) # lte-softmodem is both eNB and UE implementation @@ -2279,7 +2280,7 @@ add_executable(rftest ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/executables/softmodem-common.c ) -target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader) +target_link_libraries(rftest PRIVATE minimal_lib PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader) target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_executable(polartest @@ -2299,7 +2300,7 @@ add_executable(smallblocktest ) target_link_libraries(smallblocktest PRIVATE - -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group + -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group m pthread dl shlib_loader ) From 47da0a024d443c3a2b7d56cf83aaae5782e4cf9a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 07:18:49 +0200 Subject: [PATCH 077/119] Remove libcrypto, correctly search and link libcrypt - libcrypto is not used - we use libcrypt, so correctly check for it, and link to the corresponding targets --- CMakeLists.txt | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63b69e6c3c..952fdc0d3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,6 @@ include("cmake_targets/macros.cmake") ################################### include(FindPkgConfig) -pkg_search_module(CRYPTO libcrypto REQUIRED) -include_directories(${CRYPTO_INCLUDE_DIRS}) - # Check if asn1c is installed, and check if it supports all options we need # a user can provide ASN1C_EXEC to override an asn1c to use (e.g., parallel # installation) @@ -291,6 +288,9 @@ add_library(nr_rrc ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c) target_link_libraries(nr_rrc PUBLIC asn1_nr_rrc asn1_lte_rrc) +# S1AP and NGAP need crypt library +pkg_check_modules(libcrypt REQUIRED libcrypt) + # S1AP ############## set(S1AP_DIR ${OPENAIR3_DIR}/S1AP) @@ -312,6 +312,8 @@ add_library(s1ap ) target_link_libraries(s1ap PUBLIC asn1_s1ap) target_link_libraries(s1ap PRIVATE nr_rrc asn1_nr_rrc_hdrs lte_rrc) +target_include_directories(s1ap PRIVATE ${libcrypt_INCLUDE_DIRS}) +target_link_libraries(s1ap PUBLIC ${libcrypt_LIBRARIES}) # NGAP ############## @@ -333,6 +335,8 @@ add_library(ngap ) target_link_libraries(ngap PUBLIC asn1_ngap) target_link_libraries(ngap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_include_directories(ngap PRIVATE ${libcrypt_INCLUDE_DIRS}) +target_link_libraries(ngap PRIVATE ${libcrypt_LIBRARIES}) #M2AP ############## @@ -1920,7 +1924,7 @@ add_library(LIB_5GNAS_GNB ) target_include_directories(LIB_5GNAS_GNB PRIVATE ${OPENAIR_DIR}/common/utils/ds/) -target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY ${CRYPTO_LIBRARIES}) +target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY) target_link_libraries(LIB_5GNAS_GNB PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) # Simulation library @@ -2083,7 +2087,7 @@ target_link_libraries(lte-softmodem PRIVATE ${NAS_UE_LIB} ITTI SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) -target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) +target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2141,7 +2145,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${NAS_UE_LIB} ITTI shlib_loader -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2181,7 +2185,7 @@ target_link_libraries(nr-softmodem PRIVATE x2ap f1ap m2ap m3ap e1ap shlib_loader -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2241,7 +2245,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) -target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES}) +target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2456,7 +2460,7 @@ foreach(myExe s1ap ${OPENAIR3_DIR}/TEST/test_${myExe}.c ) target_link_libraries (test_${myExe} - -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} CONFIG_LIB + -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt CONFIG_LIB ) endforeach(myExe) From 52cb72c0eed2a14383aee28f99efbd6c02a75eb1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 03:41:27 +0200 Subject: [PATCH 078/119] build_oai: allow to only build radio/transport libraries --- cmake_targets/build_oai | 101 +++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 58 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 1d4c55da20..a548cd8ced 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -569,66 +569,51 @@ function main() { #################################################### # Build RF device and transport protocol libraries # #################################################### - if [ "$eNB" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$RU" = "1" -o "$nrUE" = "1" ] ; then + if [ "$HW" != "None" ] ; then + rm -f liboai_device.so - # build RF device libraries - if [ "$HW" != "None" ] ; then - rm -f liboai_device.so + if [ "$HW" == "OAI_USRP" ] ; then + compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif + ln -sf liboai_usrpdevif.so liboai_device.so + echo "liboai_device.so symlinks to liboai_usrpdevif.so" + elif [ "$HW" == "OAI_BLADERF" ] ; then + compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif + ln -sf liboai_bladerfdevif.so liboai_device.so + echo "liboai_device.so symlinks liboai_bladerfdevif.so" + elif [ "$HW" == "OAI_LMSSDR" ] ; then + compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif + ln -sf liboai_lmssdrdevif.so liboai_device.so + echo "liboai_device.so symlinks to liboai_lmssdrdevif.so" + elif [ "$HW" == "OAI_IRIS" ] ; then + compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif + ln -s liboai_irisdevif.so liboai_device.so + echo "liboai_device.so symlinks to liboai_irisdevif.so" + elif [ "$HW" == "OAI_AW2SORI" ] ; then + compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro + ln -sf libaw2sori_transpro.so libthirdparty_transpro.so + echo "libthirdparty_transpro.so symlinks to libaw2sori_transpro.so" + else + echo_fatal "illegal HW option $HW" + fi + fi - if [ "$HW" == "OAI_USRP" ] ; then - compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif - - ln -sf liboai_usrpdevif.so liboai_device.so - echo_info "liboai_device.so is linked to USRP device library" - elif [ "$HW" == "OAI_BLADERF" ] ; then - if [ -f "/usr/include/libbladeRF.h" ] ; then - compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif - fi - - ln -sf liboai_bladerfdevif.so liboai_device.so - echo_info "liboai_device.so is linked to BLADERF device library" - elif [ "$HW" == "OAI_LMSSDR" ] ; then -# if [ -f "/usr/include/libbladeRF.h" ] ; then - compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif -# fi - - ln -sf liboai_lmssdrdevif.so liboai_device.so - echo_info "liboai_device.so is linked to LMSSDR device library" - elif [ "$HW" == "OAI_IRIS" ] ; then - compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif - - ln -s liboai_irisdevif.so liboai_device.so - echo_info "liboai_device.so is linked to IRIS device library" - elif [ "$HW" == "OAI_AW2SORI" ] ; then - compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro - - ln -sf libaw2sori_transpro.so libthirdparty_transpro.so - echo_info "build libthirdparty_transpro.so for AW2SORI fronthaul" - else - echo_info "liboai_device.so is not linked to any device library" - fi - fi - - #build transport protocol libraries (currently only ETHERNET is available) - if [ "$SKIP_SHARED_LIB_FLAG" = "False" ]; then - echo_info "Building transport protocol libraries" - rm -f liboai_transpro.so - if [ "$TP" == "Ethernet" ]; then - compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro - ln -sf liboai_eth_transpro.so liboai_transpro.so - echo_info "liboai_transpro.so is linked to ETHERNET transport" - fi - if [ "$TP" == "benetel4g" ]; then - compilations $BUILD_DIR benetel_4g.txt benetel4g - ln -sf libbenetel_4g.so liboai_transpro.so - echo_info "liboai_transpro.so is linked to BENETEL4G transport" - fi - if [ "$TP" == "benetel5g" ]; then - compilations $BUILD_DIR benetel_5g.txt benetel_5g - ln -sf libbenetel_5g.so liboai_transpro.so - echo_info "liboai_transpro.so is linked to BENETEL4G transport" - fi - fi + if [ "$TP" != "None" ]; then + rm -f liboai_transpro.so + if [ "$TP" == "Ethernet" ]; then + compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro + ln -sf liboai_eth_transpro.so liboai_transpro.so + echo_info "liboai_transpro.so symlinks to liboai_eth_transpro.so" + elif [ "$TP" == "benetel4g" ]; then + compilations $BUILD_DIR benetel_4g.txt benetel4g + ln -sf libbenetel_4g.so liboai_transpro.so + echo_info "liboai_transpro.so symlinks to libbenetel_4g.so" + elif [ "$TP" == "benetel5g" ]; then + compilations $BUILD_DIR benetel_5g.txt benetel_5g + ln -sf libbenetel_5g.so liboai_transpro.so + echo_info "liboai_transpro.so symlinks to libbenetel_5g.so" + else + echo_fatal "illegal TP option $TP" + fi fi ################### From ddf549b1f38093dc127aef1ba46233bc7b9a668c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jan 2023 08:13:45 +0100 Subject: [PATCH 079/119] Move radio CMakeLists.txt to subdirectory - move following radios: AW2S, BladeRF, IRIS, LMSSDR, RFsimulator, USRP - move following transports: Ethernet, benetel4g, benetel5g - for each: create independent cmake variable to switch compilation on/off, in order: OAI_AW2S, OAI_BLADERF, OAI_IRIS, OAI_LMSSDR, OAI_SIMU, OAI_USRP, OAI_ETHERNET, OAI_BENETEL4G, OAI_BENETEL5G - Remove RF_BOARD variable, allows to compile multiple boards at once - where applicable: remove USERSPACE/LIB in path, i.e., move files up to directories, as all are userspace libraries Note that with the above, it is now mandatory to enable a radio implementation before compiling it, e.g., for USRP: ./build_oai -w USRP cmake .. -DOAI_USRP=ON && ninja oai_usrpdevif --- CMakeLists.txt | 132 +----------------- cmake_targets/build_oai | 38 ++--- doc/Doxyfile | 10 +- executables/lte-ru.c | 2 +- executables/lte-softmodem.c | 2 +- executables/lte-uesoftmodem.c | 2 +- executables/main_ru.c | 2 +- executables/nr-ru.c | 2 +- executables/nr-softmodem.c | 2 +- executables/nr-uesoftmodem.c | 2 +- executables/ru_control.c | 2 +- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 +- openair2/ENB_APP/NB_IoT_config.c | 2 +- openair2/ENB_APP/enb_config.c | 2 +- openair2/GNB_APP/gnb_config.c | 2 +- openair2/MCE_APP/mce_config.c | 2 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- openair2/PHY_INTERFACE/phy_stub_UE.c | 2 +- openair3/MME_APP/mme_config.c | 2 +- radio/AW2SORI/CMakeLists.txt | 13 ++ radio/BLADERF/CMakeLists.txt | 4 + .../BLADERF/{USERSPACE/LIB => }/bladerf_lib.c | 0 .../BLADERF/{USERSPACE/LIB => }/bladerf_lib.h | 0 radio/CMakeLists.txt | 34 +++++ radio/ETHERNET/CMakeLists.txt | 9 ++ radio/ETHERNET/benetel/4g/CMakeLists.txt | 17 +++ radio/ETHERNET/benetel/5g/CMakeLists.txt | 16 +++ radio/ETHERNET/benetel/CMakeLists.txt | 9 ++ radio/ETHERNET/{USERSPACE/LIB => }/eth_raw.c | 0 radio/ETHERNET/{USERSPACE/LIB => }/eth_udp.c | 0 .../ETHERNET/{USERSPACE/LIB => }/ethernet.md | 0 .../{USERSPACE/LIB => }/ethernet_lib.c | 0 .../{USERSPACE/LIB => }/ethernet_lib.h | 0 radio/ETHERNET/{USERSPACE/LIB => }/if_defs.h | 2 +- radio/IRIS/CMakeLists.txt | 5 + radio/IRIS/{USERSPACE/LIB => }/iris_lib.cpp | 0 radio/LMSSDR/CMakeLists.txt | 5 + radio/LMSSDR/{USERSPACE/LIB => }/lms_lib.cpp | 0 .../LMSSDR/{USERSPACE/LIB => }/sodera_lib.cpp | 0 radio/USRP/CMakeLists.txt | 7 + radio/USRP/{USERSPACE/LIB => }/usrp_lib.cpp | 0 radio/rfsimulator/CMakeLists.txt | 11 ++ 42 files changed, 166 insertions(+), 178 deletions(-) create mode 100644 radio/AW2SORI/CMakeLists.txt create mode 100644 radio/BLADERF/CMakeLists.txt rename radio/BLADERF/{USERSPACE/LIB => }/bladerf_lib.c (100%) rename radio/BLADERF/{USERSPACE/LIB => }/bladerf_lib.h (100%) create mode 100644 radio/CMakeLists.txt create mode 100644 radio/ETHERNET/CMakeLists.txt create mode 100644 radio/ETHERNET/benetel/4g/CMakeLists.txt create mode 100644 radio/ETHERNET/benetel/5g/CMakeLists.txt create mode 100644 radio/ETHERNET/benetel/CMakeLists.txt rename radio/ETHERNET/{USERSPACE/LIB => }/eth_raw.c (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/eth_udp.c (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/ethernet.md (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/ethernet_lib.c (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/ethernet_lib.h (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/if_defs.h (98%) create mode 100644 radio/IRIS/CMakeLists.txt rename radio/IRIS/{USERSPACE/LIB => }/iris_lib.cpp (100%) create mode 100644 radio/LMSSDR/CMakeLists.txt rename radio/LMSSDR/{USERSPACE/LIB => }/lms_lib.cpp (100%) rename radio/LMSSDR/{USERSPACE/LIB => }/sodera_lib.cpp (100%) create mode 100644 radio/USRP/CMakeLists.txt rename radio/USRP/{USERSPACE/LIB => }/usrp_lib.cpp (100%) create mode 100644 radio/rfsimulator/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 952fdc0d3a..788deb761a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,30 +55,6 @@ check_option(${ASN1C_EXEC} -no-gen-JER ASN1C_EXEC) check_option(${ASN1C_EXEC} -no-gen-BER ASN1C_EXEC) check_option(${ASN1C_EXEC} -no-gen-OER ASN1C_EXEC) -#uhd 4.0 and iris installs by default in /usr/local -include_directories("/usr/local/include/") -#use native cmake method as this package is not in pkg-config -add_list2_option(RF_BOARD "None" "RF head type" "None" "OAI_USRP" "OAI_BLADERF" "OAI_LMSSDR" "OAI_SIMU") -if (${RF_BOARD} STREQUAL "OAI_USRP") - find_package(Boost REQUIRED) - -elseif (${RF_BOARD} STREQUAL "OAI_IRIS") - include_directories("radio/IRIS/USERSPACE/LIB/") - - set(HW_SOURCE ${HW_SOURCE} - radio/IRIS/USERSPACE/LIB/iris_lib.cpp) - LINK_DIRECTORIES("/usr/local/lib") - set(option_HW_lib "-lSoapySDR -rdynamic -ldl") - -elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") - include_directories("radio/AW2SORI") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_DIR}/radio/AW2SORI/ARCH/AW2SORI/oaiori.c) - LINK_DIRECTORIES("/usr/local/lib") - set(openair_HW_lib "-shared -fPIC -msse4 -g -ggdb -lori") - -endif (${RF_BOARD} STREQUAL "OAI_USRP") - ######################################################### # Base directories, compatible with legacy OAI building # ######################################################### @@ -460,101 +436,6 @@ target_link_libraries(params_libconfig PRIVATE ${libconfig_LIBRARIES}) add_library(shlib_loader OBJECT common/utils/load_module_shlib.c) target_link_libraries(shlib_loader PRIVATE CONFIG_LIB) -# include RF devices / transport protocols library modules -###################################################################### - -set(HWLIB_USRP_SOURCE - ${OPENAIR_DIR}/radio/USRP/USERSPACE/LIB/usrp_lib.cpp - ) -add_library(oai_usrpdevif MODULE ${HWLIB_USRP_SOURCE} ) -target_include_directories(oai_usrpdevif PRIVATE - "${OPENAIR_DIR}/radio/USRP/USERSPACE/LIB/" - ${Boost_INCLUDE_DIR} -) -target_link_libraries(oai_usrpdevif uhd) - -include_directories("${OPENAIR_DIR}/radio/BLADERF/USERSPACE/LIB/") -set(HWLIB_BLADERF_SOURCE - ${OPENAIR_DIR}/radio/BLADERF/USERSPACE/LIB/bladerf_lib.c - ) -add_library(oai_bladerfdevif MODULE ${HWLIB_BLADERF_SOURCE} ) -target_link_libraries(oai_bladerfdevif bladeRF) - -include_directories("${OPENAIR_DIR}/radio/LMSSDR/USERSPACE/LIB/") - -set(HWLIB_LMSSDR_SOURCE - ${OPENAIR_DIR}/radio/LMSSDR/USERSPACE/LIB/lms_lib.cpp - ) -add_library(oai_lmssdrdevif MODULE ${HWLIB_LMSSDR_SOURCE} ) -target_include_directories(oai_lmssdrdevif PRIVATE /usr/local/include/lime) -target_link_libraries(oai_lmssdrdevif LimeSuite ) - - -include_directories("${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/") -set(TPLIB_ETHERNET_SOURCE - ${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c - ${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/eth_udp.c - ${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/eth_raw.c - ) -add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} ) - -include_directories("${OPENAIR_DIR}/radio/AW2SORI/") -link_directories("/usr/local/lib") -set(HWLIB_AW2SORI_SOURCE - ${OPENAIR_DIR}/radio/AW2SORI/oaiori.c - ) -add_library(aw2sori_transpro MODULE ${HWLIB_AW2SORI_SOURCE}) -target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) -target_link_libraries(aw2sori_transpro libori.so) - -include_directories("${OPENAIR_DIR}/radio/IRIS/USERSPACE/LIB/") -set(option_HWIRISLIB_lib "-l SoapySDR") -set(HWLIB_IRIS_SOURCE - ${OPENAIR_DIR}/radio/IRIS/USERSPACE/LIB/iris_lib.cpp - ) -add_library(oai_irisdevif MODULE ${HWLIB_IRIS_SOURCE}) -target_include_directories(oai_irisdevif PRIVATE /usr/local/lib/SoapySDR/modules0.7/) -target_link_libraries(oai_irisdevif SoapySDR) - -# Benetel 4G library -###################################################################### - - -include_directories ("/usr/include/dpdk") - -set(HWLIB_BENETEL_4G_SOURCE - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/benetel.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/shared_buffers.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/low.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/low_dpdk.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/dpdk_driver.c - ) -add_library(benetel_4g MODULE ${HWLIB_BENETEL_4G_SOURCE} ) - -set_target_properties(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") - -SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") -target_link_libraries(benetel_4g PRIVATE ${DPDK_LIBS}) -target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) - -# Benetel 5G library -###################################################################### - -set(HWLIB_BENETEL_5G_SOURCE - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/benetel.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/shared_buffers.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/low.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/low_dpdk.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/dpdk_driver.c - ) -add_library(benetel_5g MODULE ${HWLIB_BENETEL_5G_SOURCE} ) - -set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") - -SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") -target_link_libraries(benetel_5g PRIVATE ${DPDK_LIBS}) -target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) - ########################################################## # LDPC offload library @@ -1976,13 +1857,6 @@ include_directories("${NFAPI_DIR}/nfapi/inc") include_directories("${NFAPI_DIR}/sim_common/inc") include_directories("${NFAPI_DIR}/pnf_sim/inc") -add_library(rfsimulator MODULE - ${OPENAIR_DIR}/radio/rfsimulator/simulator.c - ${OPENAIR_DIR}/radio/rfsimulator/apply_channelmod.c - ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c - ) -target_link_libraries(rfsimulator PRIVATE SIMU) - add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c ) @@ -2040,11 +1914,6 @@ add_executable(nfapi_test ${OPENAIR_DIR}/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c ) -add_executable(replay_node - ${OPENAIR_DIR}/radio/rfsimulator/stored_node.c - ) -target_link_libraries (replay_node minimal_lib) - add_executable(measurement_display ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) target_link_libraries (measurement_display minimal_lib) @@ -2583,3 +2452,4 @@ add_subdirectory(doc) add_subdirectory(openair1) add_subdirectory(openair2) add_subdirectory(openair3) +add_subdirectory(radio) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index a548cd8ced..02379e197c 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -282,19 +282,27 @@ function main() { case "$2" in "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU" | "AW2SORI") HW="OAI_"$2 + CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON" ;; "None") HW="None" ;; *) - echo_fatal "Unknown HW type $HW: exit..." + echo_fatal "Unknown HW type $2: exit..." esac - echo_info "Setting hardware to: $HW" - #CMAKE_CMD="$CMAKE_CMD -DRF_BOARD=\"${HW}\"" - CMAKE_CMD="$CMAKE_CMD -DRF_BOARD=${HW}" shift 2;; -t | --transport) - TP=$2 + case "$2" in + "Ethernet" | "benetel4g" | "benetel5g") + TP=$2 + CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase + ;; + "None") + HW="None" + ;; + *) + echo_fatal "Unknown TP type $2; exit..." + esac shift 2;; -P | --phy_simulators) SIMUS_PHY=1 @@ -436,26 +444,6 @@ function main() { fi fi - ######################################################## - # Check validity of HW and TP parameters for eNB / gNB # - ######################################################## - # to be discussed - - if [ "$eNB" = "1" -o "$gNB" = "1" ] ; then - if [ "$HW" = "None" -a "$TP" = "None" ] ; then - echo_info "No local radio head and no transport protocol selected" - fi - if [ "$HW" = "None" ] ; then - echo_info "No radio head has been selected (HW set to $HW)" - fi - if [ "$TP" = "None" ] ; then - echo_info "No transport protocol has been selected (TP set to $TP)" - fi - fi - - echo_info "RF HW set to $HW" - # If the user doesn't specify the Linux scheduler to use, we set a value - ####################################################### # Setting and printing OAI envs, we should check here # ####################################################### diff --git a/doc/Doxyfile b/doc/Doxyfile index aba95ed7ec..f60031541a 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -874,11 +874,11 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/rfsimulator/rfsimulator.h \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/rfsimulator/simulator.c \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/rfsimulator/apply_channelmod.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/if_defs.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/eth_udp.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/eth_raw.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/if_defs.h \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/eth_udp.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.h \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/eth_raw.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_cmdline.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_paramdesc.h \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_userapi.h \ diff --git a/executables/lte-ru.c b/executables/lte-ru.c index d18e928802..b7734aa9ed 100644 --- a/executables/lte-ru.c +++ b/executables/lte-ru.c @@ -60,7 +60,7 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" /* these variables have to be defined before including ENB_APP/enb_paramdef.h */ static int DEFBANDS[] = {7}; diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 371735110c..1a9060c04c 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -48,7 +48,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index a28c268148..d5b47a198c 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -49,7 +49,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all diff --git a/executables/main_ru.c b/executables/main_ru.c index 2de9ba5d12..b0532024c5 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -46,7 +46,7 @@ #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" #include "PHY/phy_vars.h" #include "PHY/phy_extern.h" diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 857557c9e5..c9d3dab560 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -38,7 +38,7 @@ #include "rt_profiling.h" #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 13ea4b94ee..5381d8579d 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -40,7 +40,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 7896e57145..523038aae3 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -38,7 +38,7 @@ #include "common/utils/nr/nr_common.h" #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "openair1/PHY/MODULATION/nr_modulation.h" diff --git a/executables/ru_control.c b/executables/ru_control.c index db8c24be3f..b7d71be89f 100644 --- a/executables/ru_control.c +++ b/executables/ru_control.c @@ -54,7 +54,7 @@ #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index ca641e4bc0..6fdcfbd96f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -38,7 +38,7 @@ //#include "SCHED/sched_eNB.h" lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "common/utils/LOG/vcd_signal_dumper.h" const uint8_t lin2alaw_if4p5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; diff --git a/openair2/ENB_APP/NB_IoT_config.c b/openair2/ENB_APP/NB_IoT_config.c index 2936549da7..8e6a2fac46 100644 --- a/openair2/ENB_APP/NB_IoT_config.c +++ b/openair2/ENB_APP/NB_IoT_config.c @@ -39,7 +39,7 @@ #include "SystemInformationBlockType2.h" #include "PHY/phy_extern.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "common/config/config_userapi.h" #include "RRC_config_tools.h" #include "RRC_paramsvalues.h" diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index ea2b9f9543..1be541a2bc 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -47,7 +47,7 @@ #include "LAYER2/MAC/mac_proto.h" #include "PHY/phy_extern.h" #include "PHY/INIT/phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" #include "executables/lte-softmodem.h" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 1d4a14ad8d..974e5d95b3 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -51,7 +51,7 @@ // #include "LAYER2/MAC/extern.h" // #include "LAYER2/MAC/proto.h" #include "PHY/INIT/nr_phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" #include "nr_pdcp/nr_pdcp_oai_api.h" diff --git a/openair2/MCE_APP/mce_config.c b/openair2/MCE_APP/mce_config.c index ec192582a8..c0e4c3f73c 100644 --- a/openair2/MCE_APP/mce_config.c +++ b/openair2/MCE_APP/mce_config.c @@ -45,7 +45,7 @@ #include "LAYER2/MAC/mac_proto.h" #include "PHY/phy_extern.h" #include "PHY/INIT/phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 1459d97dc6..0f2dbde947 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -45,7 +45,7 @@ #include "openair2/RRC/NR_UE/rrc_vars.h" #include "openair2/GNB_APP/L1_nr_paramdef.h" #include "openair2/GNB_APP/gnb_paramdef.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" #include #include "openair2/GNB_APP/MACRLC_nr_paramdef.h" diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index dfc82fa017..4584f42f3d 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -27,7 +27,7 @@ #include "openair2/PHY_INTERFACE/phy_stub_UE.h" #include "openair2/ENB_APP/L1_paramdef.h" #include "openair2/ENB_APP/enb_paramdef.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" #include "common/config/config_load_configmodule.h" #include "common/config/config_userapi.h" #include diff --git a/openair3/MME_APP/mme_config.c b/openair3/MME_APP/mme_config.c index b05d78510a..b1138b0a64 100644 --- a/openair3/MME_APP/mme_config.c +++ b/openair3/MME_APP/mme_config.c @@ -45,7 +45,7 @@ #include "LAYER2/MAC/mac_proto.h" #include "PHY/phy_extern.h" #include "PHY/INIT/phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" diff --git a/radio/AW2SORI/CMakeLists.txt b/radio/AW2SORI/CMakeLists.txt new file mode 100644 index 0000000000..d055b374ac --- /dev/null +++ b/radio/AW2SORI/CMakeLists.txt @@ -0,0 +1,13 @@ +find_library(ori NAMES "libori.so" REQUIRED) +if(NOT ori) + message(FATAL_ERROR "cannot locate libori.so, required to build aw2sori_transpro") +endif() +# force that oai_eth_transpro is built as well, as aw2sori_transpro requires it +if(NOT OAI_ETHERNET) + message(FATAL_ERROR "aw2sori_transpro requires oai_eth_transpro, please enable OAI_ETHERNET (-DOAI_ETHERNET=ON for cmake, or ./build_oai -t Ethernet)") +endif() + +add_library(aw2sori_transpro MODULE oaiori.c) +target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) +target_link_libraries(aw2sori_transpro PRIVATE ori oai_eth_transpro) +set_target_properties(aw2sori_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/BLADERF/CMakeLists.txt b/radio/BLADERF/CMakeLists.txt new file mode 100644 index 0000000000..d7a7fc7162 --- /dev/null +++ b/radio/BLADERF/CMakeLists.txt @@ -0,0 +1,4 @@ +pkg_check_modules(bladeRF REQUIRED libbladeRF) +add_library(oai_bladerfdevif MODULE bladerf_lib.c) +target_link_libraries(oai_bladerfdevif PRIVATE bladeRF) +set_target_properties(oai_bladerfdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/BLADERF/USERSPACE/LIB/bladerf_lib.c b/radio/BLADERF/bladerf_lib.c similarity index 100% rename from radio/BLADERF/USERSPACE/LIB/bladerf_lib.c rename to radio/BLADERF/bladerf_lib.c diff --git a/radio/BLADERF/USERSPACE/LIB/bladerf_lib.h b/radio/BLADERF/bladerf_lib.h similarity index 100% rename from radio/BLADERF/USERSPACE/LIB/bladerf_lib.h rename to radio/BLADERF/bladerf_lib.h diff --git a/radio/CMakeLists.txt b/radio/CMakeLists.txt new file mode 100644 index 0000000000..937d8039f9 --- /dev/null +++ b/radio/CMakeLists.txt @@ -0,0 +1,34 @@ +add_boolean_option(OAI_AW2SORI OFF "Activate OAI's AW2S driver" OFF) +if(OAI_AW2SORI) + add_subdirectory(AW2SORI) +endif() + +add_boolean_option(OAI_ETHERNET OFF "Activate OAI's Ethernet transport driver" OFF) +if(OAI_ETHERNET) + add_subdirectory(ETHERNET) +endif() + +add_boolean_option(OAI_BLADERF OFF "Activate OAI's BladeRF driver" OFF) +if(OAI_BLADERF) + add_subdirectory(BLADERF) +endif() + +add_boolean_option(OAI_IRIS OFF "Activate OAI's IRIS/SoapySDR driver" OFF) +if(OAI_IRIS) + add_subdirectory(IRIS) +endif() + +add_boolean_option(OAI_LMSSDR OFF "Activate OAI's LimeSDR driver" OFF) +if(OAI_LMSSDR) + add_subdirectory(LMSSDR) +endif() + +add_boolean_option(OAI_SIMU ON "Activate OAI's rfsimulator driver" OFF) +if(OAI_SIMU) + add_subdirectory(rfsimulator) +endif() + +add_boolean_option(OAI_USRP OFF "Activate OAI's USRP driver" OFF) +if(OAI_USRP) + add_subdirectory(USRP) +endif() diff --git a/radio/ETHERNET/CMakeLists.txt b/radio/ETHERNET/CMakeLists.txt new file mode 100644 index 0000000000..aa2b14ef12 --- /dev/null +++ b/radio/ETHERNET/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(oai_eth_transpro MODULE + ethernet_lib.c + eth_udp.c + eth_raw.c +) +target_include_directories(oai_eth_transpro PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +set_target_properties(oai_eth_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +add_subdirectory(benetel) diff --git a/radio/ETHERNET/benetel/4g/CMakeLists.txt b/radio/ETHERNET/benetel/4g/CMakeLists.txt new file mode 100644 index 0000000000..b0f180719c --- /dev/null +++ b/radio/ETHERNET/benetel/4g/CMakeLists.txt @@ -0,0 +1,17 @@ +pkg_check_modules(libdpdk REQUIRED libdpdk=20.05.0) + +add_library(benetel_4g MODULE + benetel.c + shared_buffers.c + low.c + low_dpdk.c + dpdk_driver.c +) + +target_compile_definitions(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +target_include_directories(benetel_4g PRIVATE ${libdpdk_INCLUDE_DIRS}) +target_link_libraries(benetel_4g PRIVATE ${libdpdk_LIBRARIES}) +target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) +set_target_properties(benetel_4g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/5g/CMakeLists.txt b/radio/ETHERNET/benetel/5g/CMakeLists.txt new file mode 100644 index 0000000000..da957acb5b --- /dev/null +++ b/radio/ETHERNET/benetel/5g/CMakeLists.txt @@ -0,0 +1,16 @@ +pkg_check_modules(libdpdk REQUIRED libdpdk=20.05.0) + +add_library(benetel_5g MODULE + benetel.c + shared_buffers.c + low.c + low_dpdk.c + dpdk_driver.c +) + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +target_include_directories(benetel_5g PRIVATE ${libdpdk_INCLUDE_DIRS}) +target_link_libraries(benetel_5g PRIVATE ${libdpdk_LIBRARIES}) +target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) +set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") +set_target_properties(benetel_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/CMakeLists.txt b/radio/ETHERNET/benetel/CMakeLists.txt new file mode 100644 index 0000000000..1a95d1ec2c --- /dev/null +++ b/radio/ETHERNET/benetel/CMakeLists.txt @@ -0,0 +1,9 @@ +add_boolean_option(OAI_BENETEL4G OFF "Activate OAI's Benetel 4G radio driver" OFF) +if(OAI_BENETEL4G) + add_subdirectory(4g) +endif() + +add_boolean_option(OAI_BENETEL5G OFF "Activate OAI's Benetel 5G radio driver" OFF) +if(OAI_BENETEL5G) + add_subdirectory(5g) +endif() diff --git a/radio/ETHERNET/USERSPACE/LIB/eth_raw.c b/radio/ETHERNET/eth_raw.c similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/eth_raw.c rename to radio/ETHERNET/eth_raw.c diff --git a/radio/ETHERNET/USERSPACE/LIB/eth_udp.c b/radio/ETHERNET/eth_udp.c similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/eth_udp.c rename to radio/ETHERNET/eth_udp.c diff --git a/radio/ETHERNET/USERSPACE/LIB/ethernet.md b/radio/ETHERNET/ethernet.md similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/ethernet.md rename to radio/ETHERNET/ethernet.md diff --git a/radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/radio/ETHERNET/ethernet_lib.c similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c rename to radio/ETHERNET/ethernet_lib.c diff --git a/radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/radio/ETHERNET/ethernet_lib.h similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h rename to radio/ETHERNET/ethernet_lib.h diff --git a/radio/ETHERNET/USERSPACE/LIB/if_defs.h b/radio/ETHERNET/if_defs.h similarity index 98% rename from radio/ETHERNET/USERSPACE/LIB/if_defs.h rename to radio/ETHERNET/if_defs.h index 4df5014bc0..e2acf78a5c 100644 --- a/radio/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/radio/ETHERNET/if_defs.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file radio/ETHERNET/USERSPACE/LIB/if_defs.h +/*! \file radio/ETHERNET/if_defs.h * \brief * \author S. Sandeep Kumar, Raymond Knopp * \date 2016 diff --git a/radio/IRIS/CMakeLists.txt b/radio/IRIS/CMakeLists.txt new file mode 100644 index 0000000000..cd12bf09bb --- /dev/null +++ b/radio/IRIS/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(SoapySDR REQUIRED) + +add_library(oai_irisdevif MODULE iris_lib.cpp) +target_link_libraries(oai_irisdevif PRIVATE SoapySDR) +set_target_properties(oai_irisdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/IRIS/USERSPACE/LIB/iris_lib.cpp b/radio/IRIS/iris_lib.cpp similarity index 100% rename from radio/IRIS/USERSPACE/LIB/iris_lib.cpp rename to radio/IRIS/iris_lib.cpp diff --git a/radio/LMSSDR/CMakeLists.txt b/radio/LMSSDR/CMakeLists.txt new file mode 100644 index 0000000000..d93b84f6f1 --- /dev/null +++ b/radio/LMSSDR/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(LimeSuite REQUIRED) + +add_library(oai_lmssdrdevif MODULE lms_lib.cpp) +target_link_libraries(oai_lmssdrdevif LimeSuite ) +set_target_properties(oai_lmssdrdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/radio/LMSSDR/lms_lib.cpp similarity index 100% rename from radio/LMSSDR/USERSPACE/LIB/lms_lib.cpp rename to radio/LMSSDR/lms_lib.cpp diff --git a/radio/LMSSDR/USERSPACE/LIB/sodera_lib.cpp b/radio/LMSSDR/sodera_lib.cpp similarity index 100% rename from radio/LMSSDR/USERSPACE/LIB/sodera_lib.cpp rename to radio/LMSSDR/sodera_lib.cpp diff --git a/radio/USRP/CMakeLists.txt b/radio/USRP/CMakeLists.txt new file mode 100644 index 0000000000..bcdf2b6a23 --- /dev/null +++ b/radio/USRP/CMakeLists.txt @@ -0,0 +1,7 @@ +#find_package(Boost REQUIRED) +find_package(UHD REQUIRED) + +add_library(oai_usrpdevif MODULE usrp_lib.cpp) +#target_include_directories(oai_usrpdevif PRIVATE Boost::boost) +target_link_libraries(oai_usrpdevif uhd) +set_target_properties(oai_usrpdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp similarity index 100% rename from radio/USRP/USERSPACE/LIB/usrp_lib.cpp rename to radio/USRP/usrp_lib.cpp diff --git a/radio/rfsimulator/CMakeLists.txt b/radio/rfsimulator/CMakeLists.txt new file mode 100644 index 0000000000..512383dcc2 --- /dev/null +++ b/radio/rfsimulator/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(rfsimulator MODULE + simulator.c + apply_channelmod.c + ../../openair1/PHY/TOOLS/signal_energy.c +) +target_link_libraries(rfsimulator PRIVATE SIMU) +target_link_libraries(rfsimulator PRIVATE asn1_nr_rrc asn1_lte_rrc) +set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +add_executable(replay_node stored_node.c) +target_link_libraries (replay_node minimal_lib) From 557e3ba8003b8ac4404c83164077b4ecd7f0c86c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:56:37 +0200 Subject: [PATCH 080/119] Make ethernet off by default in build_oai If it was one, build_oai without parameters would attempt to build the ethernet library. However, this is unexpected, and will lead to an error (as it is by default off in CMake). Set it to off, and build it where required. --- cmake_targets/build_oai | 2 +- docker/Dockerfile.build.rhel9 | 2 +- docker/Dockerfile.build.rocky | 2 +- docker/Dockerfile.build.ubuntu20 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 02379e197c..63bc83845d 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -41,7 +41,7 @@ XFORMS="True" SKIP_SHARED_LIB_FLAG="False" PRINT_STATS="False" HW="None" -TP="Ethernet" +TP="None" EPC=0 VERBOSE_CI=0 VERBOSE_COMPILE=0 diff --git a/docker/Dockerfile.build.rhel9 b/docker/Dockerfile.build.rhel9 index 3aa94d3ade..1a12843ea4 100644 --- a/docker/Dockerfile.build.rhel9 +++ b/docker/Dockerfile.build.rhel9 @@ -35,4 +35,4 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP --verbose-ci --noavx512 -c + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP -t Ethernet --verbose-ci --noavx512 -c diff --git a/docker/Dockerfile.build.rocky b/docker/Dockerfile.build.rocky index 1522844601..468869b277 100644 --- a/docker/Dockerfile.build.rocky +++ b/docker/Dockerfile.build.rocky @@ -35,4 +35,4 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP --verbose-ci --noavx512 -c + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP -t Ethernet --verbose-ci --noavx512 -c diff --git a/docker/Dockerfile.build.ubuntu20 b/docker/Dockerfile.build.ubuntu20 index fd4de7c22a..8186ca06f4 100644 --- a/docker/Dockerfile.build.ubuntu20 +++ b/docker/Dockerfile.build.ubuntu20 @@ -35,4 +35,4 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" -w USRP --verbose-ci --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" -w USRP -t Ethernet --verbose-ci --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror From b896da85e7ca047d25e0d8a388b59e8a2450c719 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 03:41:10 +0200 Subject: [PATCH 081/119] Harmonize build_oai color output --- cmake_targets/build_oai | 7 +++---- cmake_targets/tools/build_helper | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 63bc83845d..b1debfbf7d 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -448,11 +448,11 @@ function main() { # Setting and printing OAI envs, we should check here # ####################################################### - cecho "OPENAIR_DIR = $OPENAIR_DIR" $green + echo "OPENAIR_DIR = $OPENAIR_DIR" if [ "$CLEAN_ALL" = "1" ] ; then clean_all_files - echo_info "Erased all previously producted files" + echo "Erased all previously producted files" fi dlog=$OPENAIR_DIR/cmake_targets/log @@ -512,11 +512,10 @@ function main() { # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, # e.g., cmake_targets/ran_build/build, hence the ../../.. CMAKE_CMD="$CMAKE_CMD ../../.." - echo_info "running $CMAKE_CMD" + echo_info "Running \"$CMAKE_CMD\"" eval $CMAKE_CMD if [[ "$execlist" != "" ]]; then - echo_info "Compiling $execlist..." compilations $BUILD_DIR all.txt $execlist fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 52ae420081..9d1e03dec4 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -222,6 +222,7 @@ compilations() { shift 1 local targets=$@ cd $OPENAIR_DIR/cmake_targets/$dir/build + cecho "Running \"$MAKE_CMD $targets\"" $green echo_info "Log file for compilation is being written to: $dlog/$logfile" set +e { From 4db08dc68a281fa065d266c5e67b5a498108be97 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 04:13:32 +0200 Subject: [PATCH 082/119] Simplify compilations build helper Instead of using ninja/make directly, there is a cmake command option to trigger the build using whatever build tool has been configured. Use it; if there is a mismatch, there will also be a clearer cmake error. Remove build_oai's --build-coverity: we don't use it, and it can trivially be added if required (probably, most users would run it by hand anyway). Add an error if the compilations function is not called with the right noumber of arguments. --- cmake_targets/build_oai | 22 +--------------------- cmake_targets/tools/build_helper | 26 ++++++++------------------ 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index b1debfbf7d..8c9dbccda8 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -49,11 +49,9 @@ RUN_GROUP=0 TEST_CASE_GROUP="" BUILD_DIR=ran_build BUILD_DOXYGEN=0 -BUILD_COVERITY_SCAN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -MAKE_CMD=make BUILD_ECLIPSE=0 NR="False" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" @@ -340,10 +338,6 @@ function main() { BUILD_DOXYGEN=1 echo_info "Will build doxygen support" shift;; - --build-coverity-scan) - BUILD_COVERITY_SCAN=1 - echo_info "Will build Coverity-Scan objects for upload" - shift;; --disable-T-Tracer) CMAKE_CMD="$CMAKE_CMD -DT_TRACER=False" echo_info "Disabling the T tracer" @@ -409,7 +403,6 @@ function main() { shift;; --ninja) CMAKE_CMD="$CMAKE_CMD -GNinja" - MAKE_CMD=ninja shift;; --sanitize) CMAKE_CMD="$CMAKE_CMD -DSANITIZE_ADDRESS=True -DSANITIZE_UNDEFINED=True" @@ -431,19 +424,6 @@ function main() { esac done - ################################### - # Check if cov-build is installed # - ################################### - if [ "$BUILD_COVERITY_SCAN" == "1" ] ; then - echo_info "Checking cov-build is installed" - IS_INSTALLED=`which cov-build | grep -c cov-build || true` - if [ $IS_INSTALLED -eq 1 ] ; then - echo_info "Found cov-build" - else - echo_fatal "Did NOT find cov-build in PATH!" - fi - fi - ####################################################### # Setting and printing OAI envs, we should check here # ####################################################### @@ -612,7 +592,7 @@ function main() { echo_info "Doxygen generation log is located here: $doxygen_log" echo_info "Generating Doxygen files....please wait" ( - $MAKE_CMD doc + cmake --build . --target doc ) >& $doxygen_log fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 9d1e03dec4..d12c63486b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -216,36 +216,26 @@ check_errors() { } compilations() { + [[ $# -gt 2 ]] || echo_fatal "compilations needs more than three arguments" local dir=$1 shift 1 local logfile=$1 shift 1 local targets=$@ + local verbose=$([ "$VERBOSE_COMPILE" == "1" ] && echo "-v" || echo "") + echo cd $OPENAIR_DIR/cmake_targets/$dir/build cd $OPENAIR_DIR/cmake_targets/$dir/build - cecho "Running \"$MAKE_CMD $targets\"" $green - echo_info "Log file for compilation is being written to: $dlog/$logfile" + echo_info "Running \"cmake --build . $verbose --target $targets -- -j$(nproc)\"" $green + echo "Log file for compilation is being written to: $dlog/$logfile" set +e { - if [ "$BUILD_COVERITY_SCAN" == "1" ]; then - COV_SCAN_PREFIX="cov-build --dir cov-int" - else - COV_SCAN_PREFIX="" - fi - if [ "$MAKE_CMD" != "" ]; then - $MAKE_CMD $targets - else - if [ "$VERBOSE_COMPILE" == "1" ]; then - $COV_SCAN_PREFIX make -j`nproc` $targets VERBOSE=$VERBOSE_COMPILE - else - $COV_SCAN_PREFIX make -j`nproc` $targets - fi - fi + cmake --build . $verbose --target $targets -- -j$(nproc) ret=$? } > $dlog/$logfile 2>&1 if [ "$VERBOSE_CI" == "1" ]; then - echo_info "====== Start of log for $logfile ======" + echo "====== Start of log for $logfile ======" cat $dlog/$logfile - echo_info "====== End of log for $logfile ======" + echo "====== End of log for $logfile ======" fi check_warnings "$dlog/$logfile" if [[ $ret -eq 0 ]]; then From b90a469131adde6e8eaba05c1e99eb89b5f724b2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 07:55:15 +0200 Subject: [PATCH 083/119] Correctly build AW2S in dockerfile --- docker/Dockerfile.gNB.aw2s.rhel9 | 4 ++-- docker/Dockerfile.gNB.aw2s.rocky | 4 ++-- docker/Dockerfile.gNB.aw2s.ubuntu20 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index 6985ab2108..c6bd086827 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -34,8 +34,8 @@ COPY ./libori.so /usr/local/lib # build AW2S fronthaul lib WORKDIR /oai-ran RUN /bin/sh oaienv && \ - cd cmake_targets/ran_build/build && \ - ninja aw2sori_transpro + cd cmake_targets/ && \ + ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable FROM registry.access.redhat.com/ubi9/ubi:latest as oai-gnb-aw2s diff --git a/docker/Dockerfile.gNB.aw2s.rocky b/docker/Dockerfile.gNB.aw2s.rocky index 26eabc535f..f13a6f244f 100644 --- a/docker/Dockerfile.gNB.aw2s.rocky +++ b/docker/Dockerfile.gNB.aw2s.rocky @@ -35,8 +35,8 @@ COPY ./libori.so /usr/local/lib # build AW2S fronthaul lib WORKDIR /oai-ran RUN /bin/sh oaienv && \ - cd cmake_targets/ran_build/build && \ - ninja aw2sori_transpro + cd cmake_targets/ && \ + ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable FROM $BASE_IMAGE as oai-gnb-aw2s diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu20 b/docker/Dockerfile.gNB.aw2s.ubuntu20 index 642076163b..321876638d 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu20 +++ b/docker/Dockerfile.gNB.aw2s.ubuntu20 @@ -34,8 +34,8 @@ COPY ./libori.so /usr/local/lib/ # build AW2S fronthaul lib WORKDIR /oai-ran RUN /bin/sh oaienv && \ - cd cmake_targets/ran_build/build && \ - ninja aw2sori_transpro + cd cmake_targets/ && \ + ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable FROM ubuntu:bionic as oai-gnb-aw2s From 0163a52b7adf79a73d904db05fdd8ba02ab57079 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 10:40:32 +0200 Subject: [PATCH 084/119] Add libcblas for docker containers --- docker/Dockerfile.eNB.rhel9 | 1 + docker/Dockerfile.gNB.aw2s.rhel9 | 1 + docker/Dockerfile.gNB.rhel9 | 1 + docker/Dockerfile.lteRU.rhel9 | 1 + docker/Dockerfile.lteUE.rhel9 | 1 + docker/Dockerfile.nr-cuup.rhel9 | 1 + docker/Dockerfile.nrUE.rhel9 | 1 + docker/Dockerfile.phySim.rhel9 | 1 + 8 files changed, 8 insertions(+) diff --git a/docker/Dockerfile.eNB.rhel9 b/docker/Dockerfile.eNB.rhel9 index daf2c6c022..7883f8560a 100644 --- a/docker/Dockerfile.eNB.rhel9 +++ b/docker/Dockerfile.eNB.rhel9 @@ -72,6 +72,7 @@ COPY --from=enb-build \ COPY --from=enb-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index c6bd086827..863f126be6 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -75,6 +75,7 @@ COPY --from=gnb-base \ /lib64/libconfig.so.11 \ /lib64/libforms.so.2 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/ diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index 74916d7888..fc6a6c5975 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -73,6 +73,7 @@ COPY --from=gnb-base \ /lib64/libconfig.so.11 \ /lib64/libforms.so.2 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.lteRU.rhel9 b/docker/Dockerfile.lteRU.rhel9 index e0b126c9b7..81741441ab 100644 --- a/docker/Dockerfile.lteRU.rhel9 +++ b/docker/Dockerfile.lteRU.rhel9 @@ -66,6 +66,7 @@ COPY --from=ru-build \ COPY --from=ru-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.lteUE.rhel9 b/docker/Dockerfile.lteUE.rhel9 index 2b74ed0b0b..1ba07477c1 100644 --- a/docker/Dockerfile.lteUE.rhel9 +++ b/docker/Dockerfile.lteUE.rhel9 @@ -73,6 +73,7 @@ COPY --from=lte-ue-build \ COPY --from=lte-ue-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.nr-cuup.rhel9 b/docker/Dockerfile.nr-cuup.rhel9 index 9a45f7156a..5ae63a0e48 100644 --- a/docker/Dockerfile.nr-cuup.rhel9 +++ b/docker/Dockerfile.nr-cuup.rhel9 @@ -61,6 +61,7 @@ COPY --from=gnb-build \ COPY --from=gnb-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/ diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 53b179a935..445cc807b8 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -78,6 +78,7 @@ COPY --from=nr-ue-build \ COPY --from=nr-ue-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libforms.so.2 \ diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index 145c3b3c2c..223a5bb68a 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -83,6 +83,7 @@ COPY --from=phy-sim-build \ /lib64/libXau.so.6 \ /lib64/libforms.so.2 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/libexslt.so.0 \ /lib64/libxslt.so.1 \ From 00e3c5acddeb242eff551645c0fe3762308f92ed Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 20 Jun 2023 08:52:31 +0200 Subject: [PATCH 085/119] Run ldconfig to find libparams_libconfig.so in nr-cuup container --- docker/Dockerfile.nr-cuup.ubuntu20 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/Dockerfile.nr-cuup.ubuntu20 b/docker/Dockerfile.nr-cuup.ubuntu20 index f26be9c21c..222a4dd361 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu20 +++ b/docker/Dockerfile.nr-cuup.ubuntu20 @@ -52,6 +52,8 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /usr/local/lib/ +RUN ldconfig && ldd /opt/oai-gnb/bin/nr-cuup + # Create directory for configuration files WORKDIR /opt/oai-gnb/etc From 639ee53578e426751b4244961e42751519315fde Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:08:28 +0200 Subject: [PATCH 086/119] Configuration files for gNB: cleanup of config file --- .../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index cffa15e110..a1e66c7ade 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -229,15 +229,6 @@ RUs = ( } ); -THREAD_STRUCT = ( -{ - #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - parallel_config = "PARALLEL_SINGLE_THREAD"; - #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_ENABLE"; -} -); - security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen From cde71c8d0f379e5ffa82aea4a826173d2c9baf6c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:15:36 +0200 Subject: [PATCH 087/119] Add pipeline to Jenkins container parent --- ci-scripts/Jenkinsfile-GitLab-Container | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 8d52bc9f8e..c066333eaa 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -464,6 +464,26 @@ pipeline { } } } + stage ("SA-OAIUE-CN5G") { + when { expression {do5Gtest} } + steps { + script { + triggerCN5GSlaveJob ('RAN-SA-OAIUE-CN5G', 'RAN-SA-OAIUE-CN5G') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-SA-OAIUE-CN5G') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } } stage ("DockerHub-Push") { From 288e62898b0bdb0569111d25914cc00cd064a2d2 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:20:07 +0200 Subject: [PATCH 088/119] Update of UE infra file - removal of obelix UE, network script renamed --- ci-scripts/ci_ueinfra.yaml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 6bfcc86af2..2d19af7729 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -121,16 +121,10 @@ amarisoft_ue_10: UENetworkScript: ip netns exec ue10 ip a show dev pdn0 CmdPrefix: ip netns exec ue10 MTU: 1500 - -oai_ue_obelix: - Host: obelix - UENetworkScript: ip a show dev oaitun_ue1 - IF: oaitun_ue1 - oai_ue_caracal: Host: caracal AttachScript: 'docker start oai-nr-ue' DetachScript: 'docker stop oai-nr-ue' - UENetworkScript: ip a show dev oaitun_ue1 + NetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 MTU: 1500 From 1db0fb07ab7ea6bc951d422372649f45f8743eb6 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:28:38 +0200 Subject: [PATCH 089/119] Configuration files for nrUE: update of uesoftmodem options --- ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml index 2a12e4cd51..038ea51532 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -8,7 +8,7 @@ services: #entrypoint: /bin/bash -c "sleep infinity" environment: TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.20.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --nokrnmod 1 --ue-txgain 0 --ue-rxgain 65 --tune-offset 20000000 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.20.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 volumes: - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: From 70ad480a291f05dfb1511f8e84cf287c57da1292 Mon Sep 17 00:00:00 2001 From: mir Date: Fri, 19 May 2023 16:48:02 +0200 Subject: [PATCH 090/119] Add basic E2 agent through git submodule - Add E2 agent that leverages FlexRIC e2ap library - Add documentation in openair2/E2AP/README.md - Currently, statistics exported are random --- .gitmodules | 4 + CMakeLists.txt | 30 +++ cmake_targets/build_oai | 6 + executables/nr-softmodem.c | 53 +++++ openair2/E2AP/CMakeLists.txt | 98 +++++++++ openair2/E2AP/RAN_FUNCTION/CMakeLists.txt | 12 ++ .../RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt | 17 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c | 24 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c | 24 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h | 12 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c | 31 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c | 25 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c | 47 +++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c | 39 ++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h | 13 ++ .../E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt | 7 + openair2/E2AP/RAN_FUNCTION/O-RAN/README.md | 3 + .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 189 ++++++++++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h | 13 ++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c | 108 ++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h | 15 ++ openair2/E2AP/RAN_FUNCTION/init_ran_func.c | 73 +++++++ openair2/E2AP/RAN_FUNCTION/init_ran_func.h | 32 +++ openair2/E2AP/README.md | 153 ++++++++++++++ openair2/E2AP/e2_agent_arg.h | 35 ++++ openair2/E2AP/flexric | 1 + openair2/ENB_APP/enb_config.c | 22 ++ openair2/ENB_APP/enb_config.h | 5 + openair2/ENB_APP/enb_paramdef.h | 29 +++ openair2/GNB_APP/gnb_config.c | 20 ++ openair2/GNB_APP/gnb_config.h | 5 + .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 5 + 36 files changed, 1202 insertions(+) create mode 100644 .gitmodules create mode 100644 openair2/E2AP/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/README.md create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h create mode 100644 openair2/E2AP/RAN_FUNCTION/init_ran_func.c create mode 100644 openair2/E2AP/RAN_FUNCTION/init_ran_func.h create mode 100644 openair2/E2AP/README.md create mode 100644 openair2/E2AP/e2_agent_arg.h create mode 160000 openair2/E2AP/flexric diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..6d85cbb418 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "openair2/E2AP/flexric"] + path = openair2/E2AP/flexric + url = https://gitlab.eurecom.fr/mosaic5g/flexric.git + branch = remotes/origin/mir_dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 110a10bf04..c495fb52cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,6 +328,18 @@ endif() # asn1c skeletons need this add_definitions(-DHAVE_NETINET_IN_H) +######################### +##### E2 AGENT +######################### +#add_boolean_option() does not work -- why? +set(E2_AGENT "OFF" CACHE STRING "O-RAN-compliant E2 Agent") +set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF") + +if(E2_AGENT) + set(E2AP_DIR ${OPENAIR2_DIR}/E2AP) + add_subdirectory ("${E2AP_DIR}") +endif() + ################################################## # ASN.1 grammar C code generation & dependencies # ################################################## @@ -1567,6 +1579,11 @@ add_library(L2 ) target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap) target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +if(E2_AGENT) + target_link_libraries(L2 PUBLIC e2_agent e2_ran_func) + target_compile_definitions(L2 PRIVATE E2_AGENT) +endif() + add_library(MAC_NR ${MAC_NR_SRC}) target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) @@ -1597,6 +1614,11 @@ add_library(e1_pdcp_if target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap) +if(E2_AGENT) + target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func) + target_compile_definitions(L2_NR PRIVATE E2_AGENT) +endif() + add_library(L2_LTE_NR ${L2_RRC_SRC} @@ -2174,6 +2196,10 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +if(E2_AGENT) + target_compile_definitions(lte-softmodem PRIVATE E2_AGENT) +endif() + add_executable(oairu ${OPENAIR_DIR}/executables/lte-ru.c ${OPENAIR_DIR}/executables/ru_control.c @@ -2285,6 +2311,10 @@ endif() # force the generation of ASN.1 so that we don't need to wait during the build target_link_libraries(nr-softmodem PRIVATE asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp) +if(E2_AGENT) + target_compile_definitions(nr-softmodem PRIVATE E2_AGENT) +endif() + add_executable(nr-cuup executables/nr-cuup.c diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 1d4c55da20..0639385a1a 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -78,6 +78,8 @@ Options: Pass the supplied option verbatim to cmake. -d | --build-dir Sets build directory (will be /cmake_targets//build) +--build-e2 + Enable the the E2 Agent -I | --install-external-packages Installs required packages such as LibXML, asn1.1 compiler, ... This option will require root password @@ -197,6 +199,10 @@ function main() { -d | --build-dir) BUILD_DIR=$2 shift 2;; + --build-e2 ) + CMAKE_CMD="$CMAKE_CMD -DE2_AGENT=ON" + shift + ;; -I | --install-external-packages) INSTALL_EXTERNAL=1 echo_info "Will install external packages" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 13ea4b94ee..8f55024ef4 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -82,6 +82,12 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "openair2/E1AP/e1ap_common.h" #include "openair2/E1AP/e1ap_api.h" +#ifdef E2_AGENT +#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h" +#include "openair2/E2AP/RAN_FUNCTION/init_ran_func.h" +#endif + + pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex @@ -683,6 +689,53 @@ int main( int argc, char **argv ) { config_sync_var=0; + + + +#ifdef E2_AGENT + +////////////////////////////////// +////////////////////////////////// +//// Init the E2 Agent + + sm_io_ag_ran_t io = init_ran_func_ag(); + fr_args_t args = init_fr_args(0, NULL); + + // OAI Wrapper + e2_agent_args_t oai_args = RCconfig_NR_E2agent(); + if(oai_args.sm_dir != NULL) + memcpy(args.libs_dir, oai_args.sm_dir, 128); + + sleep(1); + const gNB_RRC_INST* rrc = RC.nrrrc[0]; + assert(rrc != NULL && "rrc cannot be NULL"); + + const int mcc = rrc->configuration.mcc[0]; + const int mnc = rrc->configuration.mnc[0]; + const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; + const ngran_node_t node_type = rrc->node_type; + int nb_id = 0; + int cu_du_id = 0; + if (node_type == ngran_gNB) { + nb_id = rrc->configuration.cell_identity; + } else if (node_type == ngran_gNB_DU) { + cu_du_id = rrc->node_id + 1; // Hack to avoid been 0 + nb_id = rrc->configuration.cell_identity; + } else if (node_type == ngran_gNB_CU) { + cu_du_id = rrc->node_id + 1; + nb_id = rrc->configuration.cell_identity; + } else { + LOG_E(NR_RRC, "not supported ran type detect\n"); + } + + printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id); + + init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args); +// } + +#endif // E2_AGENT + + if (NFAPI_MODE==NFAPI_MODE_PNF) { wait_nfapi_init("main?"); } diff --git a/openair2/E2AP/CMakeLists.txt b/openair2/E2AP/CMakeLists.txt new file mode 100644 index 0000000000..865eac5ffa --- /dev/null +++ b/openair2/E2AP/CMakeLists.txt @@ -0,0 +1,98 @@ +# Check that the submodule exists or init+update if not +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/flexric/CMakeLists.txt) + message(STATUS "E2AP submoduled not detected, therefore $git submodule init && git submodule update.") + execute_process(COMMAND git submodule init) + execute_process(COMMAND git submodule update) +else() + message(STATUS "E2AP submodule detected.") +endif() + +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/flexric/CMakeLists.txt) + message(FATAL_ERROR "The submodules for E2 agent were not downloaded!") +endif() + + +set(BUILDING_LIBRARY "STATIC" CACHE STRING "Static or dynamic library") +set_property(CACHE BUILDING_LIBRARY PROPERTY STRINGS "STATIC" "DYNAMIC") +message(STATUS "Selected LIBRARY TYPE: ${BUILDING_LIBRARY}") + + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +if(BUILDING_LIBRARY STREQUAL "STATIC") + add_compile_options("-W;-Wall;-Wextra;-g;-Wno-unused-result;") +elseif(BUILDING_LIBRARY STREQUAL "DYNAMIC") + # -fPIC flag + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + add_compile_options("-W;-Wall;-Wextra;-g") +else() + message(FATAL_ERROR "Unknown building type. Either choose a static or a dynamic library") +endif() + + +set(E2AP_ENCODING "ASN" CACHE STRING "The E2AP encoding to use") +set_property(CACHE E2AP_ENCODING PROPERTY STRINGS "ASN" "FLATBUFFERS") +message(STATUS "Selected E2AP_ENCODING: ${E2AP_ENCODING}") + + +####### +## Service Models +####### + +add_definitions(-DSERVICE_MODEL_DIR_PATH="${SM_DIR_PATH}/") + +# KPM service Model encoding definitions +set(SM_ENCODING_KPM "ASN" CACHE STRING "The KPM SM encoding to use") +set_property(CACHE SM_ENCODING_KPM PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected KPM SM_ENCODING: ${SM_ENCODING_KPM}") + +# RC service Model encoding definitions +set(SM_ENCODING_RC "ASN" CACHE STRING "The RC SM encoding to use") +set_property(CACHE SM_ENCODING_RC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected RC SM_ENCODING: ${SM_ENCODING_RC}") + +# MAC Service Model +set(SM_ENCODING_MAC "PLAIN" CACHE STRING "The MAC SM encoding to use") +set_property(CACHE SM_ENCODING_MAC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected MAC SM_ENCODING: ${SM_ENCODING_MAC}") + +# RLC Service Model +set(SM_ENCODING_RLC "PLAIN" CACHE STRING "The RLC SM encoding to use") +set_property(CACHE SM_ENCODING_RLC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected RLC SM_ENCODING: ${SM_ENCODING_RLC}") + +# PDCP Service Model +set(SM_ENCODING_PDCP "PLAIN" CACHE STRING "The PDCP SM encoding to use") +set_property(CACHE SM_ENCODING_PDCP PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected PDCP SM_ENCODING: ${SM_ENCODING_PDCP}") + +# SLICE Service Model +set(SM_ENCODING_SLICE "PLAIN" CACHE STRING "The SLICE SM encoding to use") +set_property(CACHE SM_ENCODING_SLICE PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected SLICE SM_ENCODING: ${SM_ENCODING_SLICE}") + +# GTP Service Model +set(SM_ENCODING_GTP "PLAIN" CACHE STRING "The GTP SM encoding to use") +set_property(CACHE SM_ENCODING_GTP PROPERTY STRINGS "PLAIN") +message(STATUS "Selected GTP SM_ENCODING: ${SM_ENCODING_GTP}") + +######## +### Flatbuffer +######## +set(FlatCC_INCLUDE_DIR "" CACHE STRING "The Flatbuffers include directory") +set(FlatCC_LIB_DIR "" CACHE STRING "The Flatbuffers lib directory") + +if(E2AP_ENCODING STREQUAL "FLATBUFFERS") + find_library(FlatCC + NAMES flatccrt_d + HINTS ${FlatCC_LIB_DIR} + ) +endif() + +include_directories(flexric/src) +add_subdirectory(flexric/src/agent) +add_subdirectory(flexric/src/lib) +add_subdirectory(flexric/src/sm) +add_subdirectory(flexric/src/util) +add_subdirectory(RAN_FUNCTION) + diff --git a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt new file mode 100644 index 0000000000..ef92ddb0be --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt @@ -0,0 +1,12 @@ +add_subdirectory(CUSTOMIZED) +add_subdirectory(O-RAN) + +add_library(e2_ran_func STATIC + init_ran_func.c + ) + +target_link_libraries(e2_ran_func + PUBLIC + e2_ran_func_cust + e2_ran_func_oran + ) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt new file mode 100644 index 0000000000..b165e1589b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(e2_ran_func_cust STATIC + ran_func_gtp.c + ran_func_mac.c + ran_func_pdcp.c + ran_func_rlc.c + ran_func_slice.c + ran_func_tc.c + # For testing purposes + ../../flexric/test/rnd/fill_rnd_data_gtp.c + ../../flexric/test/rnd/fill_rnd_data_tc.c + ../../flexric/test/rnd/fill_rnd_data_mac.c + ../../flexric/test/rnd/fill_rnd_data_rlc.c + ../../flexric/test/rnd/fill_rnd_data_pdcp.c + ../../flexric/test/rnd/fill_rnd_data_slice.c + ../../flexric/src/util/time_now_us.c + ) + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c new file mode 100644 index 0000000000..bd8b8b5881 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -0,0 +1,24 @@ +#include "ran_func_gtp.h" +#include "../../flexric/test/rnd/fill_rnd_data_gtp.h" +#include + +void read_gtp_sm(void * data) +{ + assert(data != NULL); + + gtp_ind_data_t* gtp = (gtp_ind_data_t*)(data); + fill_gtp_ind_data(gtp); +} + +void read_gtp_setup_sm(void* data) +{ + assert(data != NULL); + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_gtp_sm(void const* src) +{ + assert(src != NULL); + assert(0 !=0 && "Not supported"); +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h new file mode 100644 index 0000000000..6e88200401 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_gtp_sm(void*); + +void read_gtp_setup_sm(void*); + +sm_ag_if_ans_t write_ctrl_gtp_sm(void const*); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c new file mode 100644 index 0000000000..4b150e71ed --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -0,0 +1,24 @@ +#include "ran_func_mac.h" +#include "../../flexric/test/rnd/fill_rnd_data_mac.h" +#include + +void read_mac_sm(void* data) +{ + assert(data != NULL); + + mac_ind_data_t* mac = (mac_ind_data_t*)data; + fill_mac_ind_data(mac); +} + +void read_mac_setup_sm(void* data) +{ + assert(data != NULL); + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_mac_sm(void const* data) +{ + assert(data != NULL); + assert(0 !=0 && "Not supported"); +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h new file mode 100644 index 0000000000..26ae184b37 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h @@ -0,0 +1,12 @@ +#ifndef SM_MAC_READ_WRITE_AGENT_H +#define SM_MAC_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_mac_sm(void*); + +void read_mac_setup_sm(void*); + +sm_ag_if_ans_t write_ctrl_mac_sm(void const*); + +#endif diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c new file mode 100644 index 0000000000..14bb2400f7 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c @@ -0,0 +1,31 @@ +#include "ran_func_pdcp.h" +#include "../../flexric/test/rnd/fill_rnd_data_pdcp.h" +#include + +void read_pdcp_sm(void* data) +{ + assert(data != NULL); + //assert(data->type == PDCP_STATS_V0); + + pdcp_ind_data_t* pdcp = (pdcp_ind_data_t*)data; + fill_pdcp_ind_data(pdcp); +} + +void read_pdcp_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == PDCP_AGENT_IF_E2_SETUP_ANS_V0 ); + + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == PDCP_CTRL_REQ_V0 ); + assert(0 !=0 && "Not supported"); + sm_ag_if_ans_t ans = {0}; + return ans; +} + + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h new file mode 100644 index 0000000000..12dcaaf16b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_pdcp_sm(void*); + +void read_pdcp_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c new file mode 100644 index 0000000000..9a2a661175 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c @@ -0,0 +1,25 @@ +#include "ran_func_rlc.h" +#include "../../flexric/test/rnd/fill_rnd_data_rlc.h" + +void read_rlc_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RLC_STATS_V0); + + rlc_ind_data_t* rlc = (rlc_ind_data_t*)data; + fill_rlc_ind_data(rlc); +} + +void read_rlc_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RLC_AGENT_IF_E2_SETUP_ANS_V0 ); + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_rlc_sm(void const* data) +{ + (void)data; + assert(0!=0 && "Not supported"); +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h new file mode 100644 index 0000000000..c442cd7825 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_rlc_sm(void*); + +void read_rlc_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_rlc_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c new file mode 100644 index 0000000000..764cddf28f --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c @@ -0,0 +1,47 @@ +#include "ran_func_slice.h" +#include "../../flexric/test/rnd/fill_rnd_data_slice.h" +#include +#include + +void read_slice_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == SLICE_STATS_V0); + + slice_ind_data_t* slice = (slice_ind_data_t*)data; + fill_slice_ind_data(slice); +} + +void read_slice_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == SLICE_AGENT_IF_E2_SETUP_ANS_V0 ); + + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_slice_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == SLICE_CTRL_REQ_V0); + + slice_ctrl_req_data_t const* slice_req_ctrl = (slice_ctrl_req_data_t const* )data; // &data->slice_req_ctrl; + slice_ctrl_msg_t const* msg = &slice_req_ctrl->msg; + + if(msg->type == SLICE_CTRL_SM_V0_ADD){ + printf("[E2 Agent]: SLICE CONTROL ADD rx\n"); + } else if (msg->type == SLICE_CTRL_SM_V0_DEL){ + printf("[E2 Agent]: SLICE CONTROL DEL rx\n"); + } else if (msg->type == SLICE_CTRL_SM_V0_UE_SLICE_ASSOC){ + printf("[E2 Agent]: SLICE CONTROL ASSOC rx\n"); + } else { + assert(0!=0 && "Unknown msg_type!"); + } + + sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0}; + ans.ctrl_out.type = SLICE_AGENT_IF_CTRL_ANS_V0; + return ans; + +} + + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h new file mode 100644 index 0000000000..0c26d63120 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_slice_sm(void*); + +void read_slice_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_slice_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c new file mode 100644 index 0000000000..ca3997da7b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c @@ -0,0 +1,39 @@ +#include "ran_func_tc.h" +#include "../../flexric/test/rnd/fill_rnd_data_tc.h" +#include + +void read_tc_sm(void* data) +{ + assert(data != NULL); + //assert(data->type == TC_STATS_V0); + + tc_ind_data_t* tc = (tc_ind_data_t*)data; + fill_tc_ind_data(tc); +} + +void read_tc_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == TC_AGENT_IF_E2_SETUP_ANS_V0 ); + + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_tc_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == TC_CTRL_REQ_V0 ); + + tc_ctrl_req_data_t const* ctrl = (tc_ctrl_req_data_t const*)data; + + tc_ctrl_msg_e const t = ctrl->msg.type; + + assert(t == TC_CTRL_SM_V0_CLS || t == TC_CTRL_SM_V0_PLC + || t == TC_CTRL_SM_V0_QUEUE || t ==TC_CTRL_SM_V0_SCH + || t == TC_CTRL_SM_V0_SHP || t == TC_CTRL_SM_V0_PCR); + + sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0}; + ans.ctrl_out.type = TC_AGENT_IF_CTRL_ANS_V0; + return ans; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h new file mode 100644 index 0000000000..526d564b1b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_TC_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_tc_sm(void*); + +void read_tc_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_tc_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt new file mode 100644 index 0000000000..49624dc302 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(e2_ran_func_oran STATIC + ran_func_kpm.c + ran_func_rc.c + # For testing purposes + ../../flexric/test/rnd/fill_rnd_data_kpm.c + ../../flexric/test/rnd/fill_rnd_data_rc.c + ) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md b/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md new file mode 100644 index 0000000000..358f22a692 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md @@ -0,0 +1,3 @@ +RAN Functions as defined by O-RAN + + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c new file mode 100644 index 0000000000..daedef70e7 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -0,0 +1,189 @@ +#include "ran_func_kpm.h" +#include "../../flexric/test/rnd/fill_rnd_data_kpm.h" +#include "../../flexric/src/util/time_now_us.h" +#include +#include + +static +gnb_e2sm_t fill_gnb_data(void) +{ + gnb_e2sm_t gnb = {0}; + + // 6.2.3.16 + // Mandatory + // AMF UE NGAP ID + gnb.amf_ue_ngap_id = 112358132134; // % 2^40; + + // Mandatory + //GUAMI 6.2.3.17 + gnb.guami.plmn_id = (e2sm_plmn_t) {.mcc = 505, .mnc = 1, .mnc_digit_len = 2}; + + gnb.guami.amf_region_id = (rand() % 2^8) + 0; + gnb.guami.amf_set_id = (rand() % 2^10) + 0; + gnb.guami.amf_ptr = (rand() % 2^6) + 0; + + return gnb; +} + +static +ue_id_e2sm_t fill_ue_id_data(void) +{ + ue_id_e2sm_t ue_id_data = {0}; + + ue_id_data.type = GNB_UE_ID_E2SM; + ue_id_data.gnb = fill_gnb_data(); + + return ue_id_data; +} + +static +kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(void) +{ + kpm_ind_msg_format_1_t msg_frm_1 = {0}; + + // Measurement Data + uint32_t num_drbs = 2; + msg_frm_1.meas_data_lst_len = num_drbs; // (rand() % 65535) + 1; + msg_frm_1.meas_data_lst = calloc(msg_frm_1.meas_data_lst_len, sizeof(*msg_frm_1.meas_data_lst)); + assert(msg_frm_1.meas_data_lst != NULL && "Memory exhausted" ); + + for (size_t i = 0; i < msg_frm_1.meas_data_lst_len; i++){ + // Measurement Record + msg_frm_1.meas_data_lst[i].meas_record_len = 1; // (rand() % 65535) + 1; + msg_frm_1.meas_data_lst[i].meas_record_lst = calloc(msg_frm_1.meas_data_lst[i].meas_record_len, sizeof(meas_record_lst_t)); + assert(msg_frm_1.meas_data_lst[i].meas_record_lst != NULL && "Memory exhausted" ); + + for (size_t j = 0; j < msg_frm_1.meas_data_lst[i].meas_record_len; j++){ + msg_frm_1.meas_data_lst[i].meas_record_lst[j].value = REAL_MEAS_VALUE; // rand()%END_MEAS_VALUE; + msg_frm_1.meas_data_lst[i].meas_record_lst[j].real_val = (rand() % 256) + 0.1; + } + } + + // Measurement Information - OPTIONAL + msg_frm_1.meas_info_lst_len = num_drbs; + msg_frm_1.meas_info_lst = calloc(msg_frm_1.meas_info_lst_len, sizeof(meas_info_format_1_lst_t)); + assert(msg_frm_1.meas_info_lst != NULL && "Memory exhausted" ); + + for (size_t i = 0; i < msg_frm_1.meas_info_lst_len; i++) { + // Measurement Type + msg_frm_1.meas_info_lst[i].meas_type.type = ID_MEAS_TYPE; + // DRB ID + msg_frm_1.meas_info_lst[i].meas_type.id = i; + + // Label Information + msg_frm_1.meas_info_lst[i].label_info_lst_len = 1; + msg_frm_1.meas_info_lst[i].label_info_lst = calloc(msg_frm_1.meas_info_lst[i].label_info_lst_len, sizeof(label_info_lst_t)); + assert(msg_frm_1.meas_info_lst[i].label_info_lst != NULL && "Memory exhausted" ); + + for (size_t j = 0; j < msg_frm_1.meas_info_lst[i].label_info_lst_len; j++) { + msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = malloc(sizeof(enum_value_e)); + *msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = TRUE_ENUM_VALUE; + } + } + + return msg_frm_1; +} + +static +kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_sta(void) +{ + kpm_ind_msg_format_3_t msg_frm_3 = {0}; + + uint32_t num_ues = 1; + msg_frm_3.ue_meas_report_lst_len = num_ues; // (rand() % 65535) + 1; + + msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); + assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); + + for (size_t i = 0; i < msg_frm_3.ue_meas_report_lst_len; i++) + { + msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst = fill_ue_id_data(); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(); + } + + return msg_frm_3; +} + +static +kpm_ric_ind_hdr_format_1_t fill_kpm_ind_hdr_frm_1(void) +{ + kpm_ric_ind_hdr_format_1_t hdr_frm_1 = {0}; + + hdr_frm_1.collectStartTime = time_now_us(); + + hdr_frm_1.fileformat_version = NULL; + + hdr_frm_1.sender_name = calloc(1, sizeof(byte_array_t)); + hdr_frm_1.sender_name->buf = calloc(strlen("My OAI-MONO") + 1, sizeof(char)); + memcpy(hdr_frm_1.sender_name->buf, "My OAI-MONO", strlen("My OAI-MONO")); + hdr_frm_1.sender_name->len = strlen("My OAI-MONO"); + + hdr_frm_1.sender_type = calloc(1, sizeof(byte_array_t)); + hdr_frm_1.sender_type->buf = calloc(strlen("MONO") + 1, sizeof(char)); + memcpy(hdr_frm_1.sender_type->buf, "MONO", strlen("MONO")); + hdr_frm_1.sender_type->len = strlen("MONO"); + + hdr_frm_1.vendor_name = calloc(1, sizeof(byte_array_t)); + hdr_frm_1.vendor_name->buf = calloc(strlen("OAI") + 1, sizeof(char)); + memcpy(hdr_frm_1.vendor_name->buf, "OAI", strlen("OAI")); + hdr_frm_1.vendor_name->len = strlen("OAI"); + + return hdr_frm_1; +} + +static +kpm_ind_hdr_t fill_kpm_ind_hdr_sta(void) +{ + kpm_ind_hdr_t hdr = {0}; + + hdr.type = FORMAT_1_INDICATION_HEADER; + hdr.kpm_ric_ind_hdr_format_1 = fill_kpm_ind_hdr_frm_1(); + + return hdr; +} + +void read_kpm_sm(void* data) +{ + assert(data != NULL); + //assert(data->type == KPM_STATS_V3_0); + + kpm_rd_ind_data_t* kpm = (kpm_rd_ind_data_t*)data; + + assert(kpm->act_def!= NULL && "Cannot be NULL"); + if(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION){ + + if(kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond_type == CQI_TEST_COND_TYPE + && *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond == GREATERTHAN_TEST_COND){ + printf("Matching condition: UEs with CQI greater than %ld \n", *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.int_value ); + } + + printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst->meas_type.name.buf); + + kpm->ind.hdr = fill_kpm_ind_hdr_sta(); + // 7.8 Supported RIC Styles and E2SM IE Formats + // Format 4 corresponds to indication message 3 + kpm->ind.msg.type = FORMAT_3_INDICATION_MESSAGE; + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_sta(); + } else { + kpm->ind.hdr = fill_kpm_ind_hdr(); + kpm->ind.msg = fill_kpm_ind_msg(); + } +} + +void read_kpm_setup_sm(void* e2ap) +{ + assert(e2ap != NULL); +// assert(e2ap->type == KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0); + + kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap); + kpm->ran_func_def = fill_kpm_ran_func_def(); +} + +sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src) +{ + assert(0 !=0 && "Not supported"); + (void)src; + sm_ag_if_ans_t ans = {0}; + return ans; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h new file mode 100644 index 0000000000..cec10e06ad --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_kpm_sm(void*); + +void read_kpm_setup_sm(void*); + +sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c new file mode 100644 index 0000000000..5c6777d5a3 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c @@ -0,0 +1,108 @@ +#include "ran_func_rc.h" +#include "../../flexric/test/rnd/fill_rnd_data_rc.h" +#include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h" +#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h" +#include +#include +#include +#include + +void read_rc_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RAN_CTRL_STATS_V1_03); + assert(0!=0 && "Not implemented"); +} + +void read_rc_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0); + rc_e2_setup_t* rc = (rc_e2_setup_t*)data; + rc->ran_func_def = fill_rc_ran_func_def(); +} + +sm_ag_if_ans_t write_ctrl_rc_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == RAN_CONTROL_CTRL_V1_03 ); + + rc_ctrl_req_data_t const* ctrl = (rc_ctrl_req_data_t const*)data; + if(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR){ + if(ctrl->hdr.frmt_1.ric_style_type == 1 && ctrl->hdr.frmt_1.ctrl_act_id == 2){ + printf("QoS flow mapping configuration \n"); + e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1; + for(size_t i = 0; i < frmt_1->sz_ran_param; ++i){ + seq_ran_param_t const* rp = frmt_1->ran_param; + if(rp[i].ran_param_id == 1){ + assert(rp[i].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE ); + printf("DRB ID %ld \n", rp[i].ran_param_val.flag_true->int_ran); + } else if(rp[i].ran_param_id == 2){ + assert(rp[i].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE); + printf("List of QoS Flows to be modified \n"); + for(size_t j = 0; j < ctrl->msg.frmt_1.ran_param[i].ran_param_val.lst->sz_lst_ran_param; ++j){ + lst_ran_param_t const* lrp = rp[i].ran_param_val.lst->lst_ran_param; + // The following assertion should be true, but there is a bug in the std + // check src/sm/rc_sm/enc/rc_enc_asn.c:1085 and src/sm/rc_sm/enc/rc_enc_asn.c:984 + // assert(lrp[j].ran_param_id == 3); + assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_id == 4) ; + assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE); + + int64_t qfi = lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.flag_true->int_ran; + assert(qfi > -1 && qfi < 65); + + assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_id == 5); + assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.type == ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE); + int64_t dir = lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.flag_false->int_ran; + assert(dir == 0 || dir == 1); + printf("qfi = %ld dir %ld \n", qfi, dir); + } + } + } + } + } + + sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0}; + ans.ctrl_out.type = RAN_CTRL_V1_3_AGENT_IF_CTRL_ANS_V0; + return ans; +} + +static +void* emulate_rrc_msg(void* ptr) +{ + uint32_t* ric_id = (uint32_t*)ptr; + for(size_t i = 0; i < 5; ++i){ + usleep(rand()%4000); + rc_ind_data_t* d = calloc(1, sizeof(rc_ind_data_t)); + assert(d != NULL && "Memory exhausted"); + *d = fill_rnd_rc_ind_data(); + async_event_agent_api(*ric_id, d); + printf("Event for RIC Req ID %u generated\n", *ric_id); + } + + free(ptr); + return NULL; +} + +static +pthread_t t_ran_ctrl; + +sm_ag_if_ans_t write_subs_rc_sm(void const* src) +{ + assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03); + + wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src; + printf("ric req id %d \n", wr_rc->ric_req_id); + + uint32_t* ptr = malloc(sizeof(uint32_t)); + assert(ptr != NULL); + *ptr = wr_rc->ric_req_id; + + int rc = pthread_create(&t_ran_ctrl, NULL, emulate_rrc_msg, ptr); + assert(rc == 0); + + sm_ag_if_ans_t ans = {0}; + + return ans; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h new file mode 100644 index 0000000000..64f11c8068 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h @@ -0,0 +1,15 @@ +#ifndef RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_rc_sm(void *); + +void read_rc_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_rc_sm(void const* data); + +sm_ag_if_ans_t write_subs_rc_sm(void const* src); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c new file mode 100644 index 0000000000..bc60d139de --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c @@ -0,0 +1,73 @@ +#include "init_ran_func.h" +#include "../flexric/src/agent/e2_agent_api.h" +#include "CUSTOMIZED/ran_func_mac.h" +#include "CUSTOMIZED/ran_func_rlc.h" +#include "CUSTOMIZED/ran_func_pdcp.h" +#include "CUSTOMIZED/ran_func_slice.h" +#include "CUSTOMIZED/ran_func_tc.h" +#include "CUSTOMIZED/ran_func_gtp.h" +#include "O-RAN/ran_func_kpm.h" +#include "O-RAN/ran_func_rc.h" + +static +void init_read_ind_tbl(read_ind_fp (*read_ind_tbl)[SM_AGENT_IF_READ_V0_END]) +{ + (*read_ind_tbl)[MAC_STATS_V0] = read_mac_sm; + (*read_ind_tbl)[RLC_STATS_V0] = read_rlc_sm ; + (*read_ind_tbl)[PDCP_STATS_V0] = read_pdcp_sm ; + (*read_ind_tbl)[SLICE_STATS_V0] = read_slice_sm ; + (*read_ind_tbl)[TC_STATS_V0] = read_tc_sm ; + (*read_ind_tbl)[GTP_STATS_V0] = read_gtp_sm ; + (*read_ind_tbl)[KPM_STATS_V3_0] = read_kpm_sm ; + (*read_ind_tbl)[RAN_CTRL_STATS_V1_03] = read_rc_sm; +} + +static +void init_read_setup_tbl(read_e2_setup_fp (*read_setup_tbl)[SM_AGENT_IF_E2_SETUP_ANS_V0_END]) +{ + (*read_setup_tbl)[MAC_AGENT_IF_E2_SETUP_ANS_V0] = read_mac_setup_sm; + (*read_setup_tbl)[RLC_AGENT_IF_E2_SETUP_ANS_V0] = read_rlc_setup_sm ; + (*read_setup_tbl)[PDCP_AGENT_IF_E2_SETUP_ANS_V0] = read_pdcp_setup_sm ; + (*read_setup_tbl)[SLICE_AGENT_IF_E2_SETUP_ANS_V0] = read_slice_setup_sm ; + (*read_setup_tbl)[TC_AGENT_IF_E2_SETUP_ANS_V0] = read_tc_setup_sm ; + (*read_setup_tbl)[GTP_AGENT_IF_E2_SETUP_ANS_V0] = read_gtp_setup_sm ; + (*read_setup_tbl)[KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0] = read_kpm_setup_sm ; + (*read_setup_tbl)[RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0] = read_rc_setup_sm; +} + +static +void init_write_ctrl( write_ctrl_fp (*write_ctrl_tbl)[SM_AGENT_IF_WRITE_CTRL_V0_END]) +{ + (*write_ctrl_tbl)[MAC_CTRL_REQ_V0] = write_ctrl_mac_sm; + (*write_ctrl_tbl)[RLC_CTRL_REQ_V0] = write_ctrl_rlc_sm; + (*write_ctrl_tbl)[PDCP_CTRL_REQ_V0] = write_ctrl_pdcp_sm; + (*write_ctrl_tbl)[SLICE_CTRL_REQ_V0] = write_ctrl_slice_sm; + (*write_ctrl_tbl)[TC_CTRL_REQ_V0] = write_ctrl_tc_sm; + (*write_ctrl_tbl)[GTP_CTRL_REQ_V0] = write_ctrl_gtp_sm; + (*write_ctrl_tbl)[RAN_CONTROL_CTRL_V1_03] = write_ctrl_rc_sm; +} + +static +void init_write_subs(write_subs_fp (*write_subs_tbl)[SM_AGENT_IF_WRITE_SUBS_V0_END]) +{ + (*write_subs_tbl)[MAC_SUBS_V0] = NULL; + (*write_subs_tbl)[RLC_SUBS_V0] = NULL; + (*write_subs_tbl)[PDCP_SUBS_V0] = NULL; + (*write_subs_tbl)[SLICE_SUBS_V0] = NULL; + (*write_subs_tbl)[TC_SUBS_V0] = NULL; + (*write_subs_tbl)[GTP_SUBS_V0] = NULL; + (*write_subs_tbl)[KPM_SUBS_V3_0] = NULL; + (*write_subs_tbl)[RAN_CTRL_SUBS_V1_03] = write_subs_rc_sm; +} + +sm_io_ag_ran_t init_ran_func_ag(void) +{ + sm_io_ag_ran_t io = {0}; + init_read_ind_tbl(&io.read_ind_tbl); + init_read_setup_tbl(&io.read_setup_tbl); + init_write_ctrl(&io.write_ctrl_tbl); + init_write_subs(&io.write_subs_tbl); + + return io; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.h b/openair2/E2AP/RAN_FUNCTION/init_ran_func.h new file mode 100644 index 0000000000..3b7d10f506 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.h @@ -0,0 +1,32 @@ +/* + * 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 + */ + + + +#ifndef RAN_FUNC_INIT_E2_H +#define RAN_FUNC_INIT_E2_H + +#include "../flexric/src/sm/sm_io.h" + +sm_io_ag_ran_t init_ran_func_ag(void); + +#endif + diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md new file mode 100644 index 0000000000..ce8bf0dd7a --- /dev/null +++ b/openair2/E2AP/README.md @@ -0,0 +1,153 @@ +

+ OAI +

+ +

+ License + Supported OS Ubuntu 18 + Supported OS Ubuntu 20 + Supported OS Ubuntu 22 + Supported OS RHEL8 + Supported OS RELH9 + Supported OS Fedora 37 +

+ +

+ +

+ +

+ Docker Pulls + Docker Pulls + Docker Pulls + Docker Pulls +

+ + + +# OpenAirInterface License # + + * [OAI License Model](http://www.openairinterface.org/?page_id=101) + * [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698) + +It is distributed under **OAI Public License V1.1**. + +The license information is distributed under [LICENSE](LICENSE) file in the same directory. + +Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources. + +# Overview + +This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 agent, with FlexRIC, O-RAN compliant nearRT-RIC. + +# 1. Installation + +## 1.1 Install prerequisites + +- A *recent* CMake (at least v3.15). + + On Ubuntu, you might want to use [this PPA](https://apt.kitware.com/) to install an up-to-date version. + +- SWIG (at least v.4.0). + + We use SWIG as an interface generator to enable the multi-language feature (i.e., C/C++ and Python) for the xApps. Please, check your SWIG version (i.e, `swig + -version`) and install it from scratch if necessary as described here: https://swig.org/svn.html or via the code below: + + ```bash + git clone https://github.com/swig/swig.git + cd swig + ./autogen.sh + ./configure --prefix=/usr/ + make + make install + ``` + +- Flatbuffer encoding(optional). + + We also provide a flatbuffers encoding/decoding scheme as alternative to ASN.1. In case that you want to use it follow the + instructions at https://github.com/dvidelabs/flatcc and provide the path for the lib and include when selecting it at `ccmake ..` from the build directory + +## 1.2 Download the required dependencies. + +Below an example of how to install it in ubuntu +```bash +sudo apt install libsctp-dev python3.8 cmake-curses-gui libpcre2-dev python-dev +``` + +# 2. Deployment + +## 2.1 OAI RAN + +### 2.1.1 Clone the OAI repository +```bash +git clone https://gitlab.eurecom.fr/oai/openairinterface5g oai +cd oai/ +``` + +### 2.1.2 Build OAI +```bash +cd cmake_targets/ +./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja +``` +If the flexric folder is empty, try manually the following commands + +```bash +git submodule init +git submodule update +``` + + * -I option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. + * -w option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from liboai_device.so to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using -w SIMU option, but is also built during any softmodem build. + * --gNB is to build the nr-softmodem and nr-cuup executables and all required shared libraries + * --nrUE is to build the nr-uesoftmodem executable and all required shared libraries + * --ninja is to use the ninja build tool, which speeds up compilation + * --build-e2 option is to use the E2 agent, integrated within gNB. + +## 2.2 FlexRIC + +### 2.2.1 Clone the FlexRIC repository +```bash +git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric +cd flexric/ +git checkout mir_dev +``` + +### 2.2.2 Build FlexRIC +```bash +mkdir build && cd build && cmake .. && make +``` + +### 2.2.3 Installation of Service Models (SMs) +```bash +sudo make install +``` + +By default the service model libraries will be installed in the path /usr/local/lib/flexric while the configuration file in `/usr/local/etc/flexric`. + + * Note: currently, only xApp KPM v03.00 and RC v01.03 (xapp_kpm_rc) is supported to communicate with the integrated E2 agent in OAI. If you are interested in custom SMs (MAC, RLC, PDCP, GTP, TC and SLICE), please follow the instructions at https://gitlab.eurecom.fr/mosaic5g/flexric. + +# 3. Start the process + +* start the gNB +```bash +cd oai/cmake_targets/ran_build/build +sudo ./nr-softmodem RFSIMULATOR=server -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa +``` + +* start the nrUE +```bash +cd oai/cmake_targets/ran_build/build +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001 +``` + +* start the nearRT-RIC +```bash +cd flexric +./build/examples/ric/nearRT-RIC +``` + +* start the KPM+RC xApp +```bash +cd flexric +./build/examples/xApp/c/kpm_rc/xapp_kpm_rc +``` diff --git a/openair2/E2AP/e2_agent_arg.h b/openair2/E2AP/e2_agent_arg.h new file mode 100644 index 0000000000..b719c32d97 --- /dev/null +++ b/openair2/E2AP/e2_agent_arg.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef E2_AGENT_ARGS_H +#define E2_AGENT_ARGS_H + +#include + +// Wrapper for OAI +typedef struct{ + const char *ip; + const char *sm_dir; +} e2_agent_args_t; + +#endif + + diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric new file mode 160000 index 0000000000..ef00d05a3f --- /dev/null +++ b/openair2/E2AP/flexric @@ -0,0 +1 @@ +Subproject commit ef00d05a3f673d04bbc003f4ae479ead467bd8ea diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 26606a9c5c..b05dcf4f76 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2929,3 +2929,25 @@ void read_config_and_init(void) { RCconfig_RRC(enb_id, RC.rrc[enb_id]); } } + +#ifdef E2_AGENT + +e2_agent_args_t RCconfig_E2agent(void) +{ + paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC; + int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT); + if (ret < 0) { + LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT); + return (e2_agent_args_t) {0}; + } + return (e2_agent_args_t) { + .ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr, + .port = *e2agent_params[E2AGENT_CONFIG_PORT_IDX].u16ptr, + .sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr, + }; +} + + +#endif + + diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 67b4fb45e7..5abb7df2c9 100644 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -116,6 +116,11 @@ void read_config_and_init(void); int RCconfig_X2(MessageDef *msg_p, uint32_t i); int RCconfig_M2(MessageDef *msg_p, uint32_t i); +#ifdef E2_AGENT +#include "openair2/E2AP/e2_agent_arg.h" +e2_agent_args_t RCconfig_E2agent(void); +#endif + void fill_SL_configuration(RrcConfigurationReq *RRCcfg, ccparams_sidelink_t *SLconfig, int cell_idx, int cc_idx, char *config_fname); void fill_eMTC_configuration(RrcConfigurationReq *RRCcfg, ccparams_eMTC_t *eMTCconfig, int cell_idx, int cc_idx, char *config_fname, char *brparamspath); diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index e37c5388d0..34fcc6ad2c 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1317,6 +1317,35 @@ typedef struct srb1_params_s { #define CONFIG_HLP_PARALLEL "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n" /*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#ifdef E2_AGENT + +/* E2 Agent configuration */ +#define CONFIG_STRING_E2AGENT "e2_agent" + +#define E2AGENT_CONFIG_IP "ip" +//#define E2AGENT_CONFIG_PORT "port" +#define E2AGENT_CONFIG_SMDIR "sm_dir" + +static const char* const e2agent_config_ip_default = NULL; +static const char* const e2agent_config_smdir_default = NULL; +//static const uint16_t e2agent_config_port_default = 36421; + +#define E2AGENT_PARAMS_DESC { \ + {E2AGENT_CONFIG_IP, "RIC IP address", 0, strptr:NULL, defstrval:(char*)e2agent_config_ip_default, TYPE_STRING, 0}, \ + {E2AGENT_CONFIG_SMDIR, "Directory with SMs to load", 0, strptr:NULL, defstrval:(char*)e2agent_config_smdir_default, TYPE_STRING, 0}, \ +} +/* +// {E2AGENT_CONFIG_PORT, "RIC port", 0, u16ptr:NULL, defuintval:e2agent_config_port_default, TYPE_UINT16, 0}, \ +} +*/ + +#define E2AGENT_CONFIG_IP_IDX 0 +#define E2AGENT_CONFIG_SMDIR_IDX 1 +//#define E2AGENT_CONFIG_PORT_IDX 2 + +#endif // E2_AGENT + + #include "enb_paramdef_emtc.h" #include "enb_paramdef_sidelink.h" #include "enb_paramdef_mce.h" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 9db7cc5067..87f2c07d21 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2259,3 +2259,23 @@ void nr_read_config_and_init(void) { nr_pdcp_layer_init(); } } + +#ifdef E2_AGENT + +e2_agent_args_t RCconfig_NR_E2agent(void) +{ + paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC; + int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT); + if (ret < 0) { + LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters from FlexRIC\n", CONFIG_STRING_E2AGENT); + return (e2_agent_args_t) { 0 }; + } + e2_agent_args_t dst = {0}; + if(e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL) + dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr; + if(e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) + dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr; + return dst; +} + +#endif // E2_AGENT diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 3089753cff..0a23ebea74 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -110,5 +110,10 @@ void nr_read_config_and_init(void); MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process); ngran_node_t get_node_type(void); +#ifdef E2_AGENT +#include "openair2/E2AP/e2_agent_arg.h" +e2_agent_args_t RCconfig_NR_E2agent(void); +#endif // E2_AGENT + #endif /* GNB_CONFIG_H_ */ /** @} */ diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 7d5d49fe87..01210a0663 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -266,3 +266,8 @@ log_config : f1ap_log_level ="debug"; }; +e2_agent = { + address = "127.0.0.1"; + #sm_dir = "/path/where/the/SMs/are/located/" + sm_dir = "/usr/local/lib/flexric/" +}; From 126e7bb432733bd92f0bac8247e893e0243564ce Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 7 Jun 2023 10:45:48 +0200 Subject: [PATCH 091/119] Reference E2 agent tutorial in doc/README.md --- doc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/README.md b/doc/README.md index 6abca52f0b..f65f6f6ac0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -43,6 +43,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to run OAI-VNF and OAI-PNF](./RUN_NR_NFAPI.md) _Note: does not work currently_ - [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md) - [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt) +- [How to run with E2 agent](../openair2/E2AP/README.md) Legacy unmaintained files: - `L2NFAPI_NOS1.md`, `L2NFAPI_S1.md`: old L2simulator, not valid anymore From 483c5436e54d9c9e9496e9ebaef7e118685b601c Mon Sep 17 00:00:00 2001 From: mir Date: Fri, 16 Jun 2023 14:37:55 +0200 Subject: [PATCH 092/119] gitlink to FlexRIC was updated --- openair2/E2AP/README.md | 4 ++-- openair2/E2AP/flexric | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index ce8bf0dd7a..822880f2b2 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -109,12 +109,12 @@ git submodule update ```bash git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric cd flexric/ -git checkout mir_dev +git checkout d3ff879135d036632d7938c2085dbf4577759225 ``` ### 2.2.2 Build FlexRIC ```bash -mkdir build && cd build && cmake .. && make +mkdir build && cd build && cmake .. && make -j8 ``` ### 2.2.3 Installation of Service Models (SMs) diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric index ef00d05a3f..d3ff879135 160000 --- a/openair2/E2AP/flexric +++ b/openair2/E2AP/flexric @@ -1 +1 @@ -Subproject commit ef00d05a3f673d04bbc003f4ae479ead467bd8ea +Subproject commit d3ff879135d036632d7938c2085dbf4577759225 From bb3d8b82015eba1dcaf71f500b878a801e14da7a Mon Sep 17 00:00:00 2001 From: mir Date: Mon, 19 Jun 2023 16:20:22 +0200 Subject: [PATCH 093/119] near_ric_ip_addr added. The config needs to be defined in OAI's config file --- executables/nr-softmodem.c | 10 ++++++---- openair2/ENB_APP/enb_paramdef.h | 2 +- openair2/GNB_APP/gnb_config.c | 9 ++++++--- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 8f55024ef4..1b0ff90708 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -697,14 +697,16 @@ int main( int argc, char **argv ) { ////////////////////////////////// ////////////////////////////////// //// Init the E2 Agent - + sm_io_ag_ran_t io = init_ran_func_ag(); - fr_args_t args = init_fr_args(0, NULL); // OAI Wrapper e2_agent_args_t oai_args = RCconfig_NR_E2agent(); - if(oai_args.sm_dir != NULL) - memcpy(args.libs_dir, oai_args.sm_dir, 128); + AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); + AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\""); + + fr_args_t args = {.ip = oai_args.ip}; // init_fr_args(0, NULL); + memcpy(args.libs_dir, oai_args.sm_dir, 128); sleep(1); const gNB_RRC_INST* rrc = RC.nrrrc[0]; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 34fcc6ad2c..58eebba278 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1322,7 +1322,7 @@ typedef struct srb1_params_s { /* E2 Agent configuration */ #define CONFIG_STRING_E2AGENT "e2_agent" -#define E2AGENT_CONFIG_IP "ip" +#define E2AGENT_CONFIG_IP "near_ric_ip_addr" //#define E2AGENT_CONFIG_PORT "port" #define E2AGENT_CONFIG_SMDIR "sm_dir" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 87f2c07d21..2314cd2bf2 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2271,10 +2271,13 @@ e2_agent_args_t RCconfig_NR_E2agent(void) return (e2_agent_args_t) { 0 }; } e2_agent_args_t dst = {0}; - if(e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL) - dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr; - if(e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) + + if (e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr; + + if (e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL) + dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr; + return dst; } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 01210a0663..3b7fadf3bc 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -267,7 +267,7 @@ log_config : }; e2_agent = { - address = "127.0.0.1"; + near_ric_ip_addr = "127.0.0.1"; #sm_dir = "/path/where/the/SMs/are/located/" sm_dir = "/usr/local/lib/flexric/" }; From 31b7d7c432e162212892446689adcecd30ead8b2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Jul 2023 07:01:28 +0000 Subject: [PATCH 094/119] !2173: Favor --rfsimulator.serveraddr "server" over RFSIMULATOR=server --- openair2/E2AP/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index 822880f2b2..2ff52e8605 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -131,13 +131,13 @@ By default the service model libraries will be installed in the path /usr/local/ * start the gNB ```bash cd oai/cmake_targets/ran_build/build -sudo ./nr-softmodem RFSIMULATOR=server -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa --rfsimulator.serveraddr server ``` * start the nrUE ```bash cd oai/cmake_targets/ran_build/build -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001 +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1 ``` * start the nearRT-RIC From 1f14195543a83506a7f03db619b1b1c98fe246e2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 7 Jul 2023 13:47:05 +0200 Subject: [PATCH 095/119] Move inclusion of openair2/E2AP where it belongs --- CMakeLists.txt | 6 ------ openair2/CMakeLists.txt | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c495fb52cc..05ebd0b10c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,15 +331,9 @@ add_definitions(-DHAVE_NETINET_IN_H) ######################### ##### E2 AGENT ######################### -#add_boolean_option() does not work -- why? set(E2_AGENT "OFF" CACHE STRING "O-RAN-compliant E2 Agent") set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF") -if(E2_AGENT) - set(E2AP_DIR ${OPENAIR2_DIR}/E2AP) - add_subdirectory ("${E2AP_DIR}") -endif() - ################################################## # ASN.1 grammar C code generation & dependencies # ################################################## diff --git a/openair2/CMakeLists.txt b/openair2/CMakeLists.txt index 563d343420..117d18412b 100644 --- a/openair2/CMakeLists.txt +++ b/openair2/CMakeLists.txt @@ -1,4 +1,7 @@ add_subdirectory(E1AP) +if(E2_AGENT) + add_subdirectory(E2AP) +endif() add_subdirectory(F1AP) add_subdirectory(M2AP) add_subdirectory(X2AP) From 97904c6db0b381216431cf98350ce9d7b493fdac Mon Sep 17 00:00:00 2001 From: mir Date: Wed, 5 Jul 2023 09:51:05 +0200 Subject: [PATCH 096/119] Simplify README --- openair2/E2AP/README.md | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index 2ff52e8605..095d802877 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -1,30 +1,3 @@ -

- OAI -

- -

- License - Supported OS Ubuntu 18 - Supported OS Ubuntu 20 - Supported OS Ubuntu 22 - Supported OS RHEL8 - Supported OS RELH9 - Supported OS Fedora 37 -

- -

- -

- -

- Docker Pulls - Docker Pulls - Docker Pulls - Docker Pulls -

- - - # OpenAirInterface License # * [OAI License Model](http://www.openairinterface.org/?page_id=101) @@ -96,12 +69,12 @@ git submodule init git submodule update ``` - * -I option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. - * -w option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from liboai_device.so to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using -w SIMU option, but is also built during any softmodem build. - * --gNB is to build the nr-softmodem and nr-cuup executables and all required shared libraries - * --nrUE is to build the nr-uesoftmodem executable and all required shared libraries - * --ninja is to use the ninja build tool, which speeds up compilation - * --build-e2 option is to use the E2 agent, integrated within gNB. + * `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. + * `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build. + * `--gNB` is to build the `nr-softmodem` and `nr-cuup` executables and all required shared libraries + * `--nrUE` is to build the `nr-uesoftmodem` executable and all required shared libraries + * `--ninja` is to use the ninja build tool, which speeds up compilation + * `--build-e2` option is to use the E2 agent, integrated within gNB. ## 2.2 FlexRIC From 8d90178d57de605e7e6e8e2deb571929757a13cc Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 16:19:12 +0200 Subject: [PATCH 097/119] Modifications in cls_containerize: add comment --- ci-scripts/cls_containerize.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index f26fdc01cb..c9023a6513 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -1005,6 +1005,7 @@ class Containerize(): HTML.htmleNBFailureMsg='Could not copy logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.exitStatus = 1 + # use function for UE log analysis, when oai-nr-ue container is used elif 'oai-nr-ue' in services: self.exitStatus == 0 logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m') From a0d9beb0dd4fd2daa6c635ae8025bd851a6b94b5 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 16:22:54 +0200 Subject: [PATCH 098/119] CI: docs for nrUE pipeline: update --- doc/TESTBenches.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 1641e0160a..35aebfe1aa 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -145,9 +145,6 @@ Webhook - [RAN-SA-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-Module-CN5G/) - asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ OAI 5GC - NR 2x2 (standalone) -- [RAN-SA-OAIUE-N310-X300-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-OAIUE-N310-X300-CN5G/) - - asterix + N310 (gNB), obelix + N310 or X300 (5G UE), porcepix w/ OAI 5GC - - OTA test with OAIUE using both N310 and X300 - [RAN-SA-AmariS-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-AmariS-CN5G/) - asterix + N310, amariue (1x UE), porcepix w/ OAI 5GC - Amarisoft UE simulator: expected to be increased to more UEs From ed7b675330a330e7de43eadfe4409441fb7cf9dd Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 26 Jun 2023 15:46:11 +0200 Subject: [PATCH 099/119] remove redundant copies of pdu sessions list --- executables/nr-cuup.c | 3 +- openair2/E1AP/e1ap_api.c | 3 +- openair2/RRC/NR/cucp_cuup_direct.c | 12 +- openair2/RRC/NR/cucp_cuup_e1ap.c | 9 +- openair2/RRC/NR/cucp_cuup_if.h | 2 +- openair2/RRC/NR/nr_rrc_defs.h | 3 - openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 304 ++++++++++++----------------- openair2/RRC/NR/rrc_gNB_NGAP.c | 5 +- 9 files changed, 138 insertions(+), 205 deletions(-) diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 6fcf5b7ea3..ffa50a766b 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -111,9 +111,10 @@ f1ap_cudu_inst_t *getCxt(F1_t isCU, instance_t instanceP) return NULL; } -void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid) +NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) { abort(); + return NULL; } int main(int argc, char **argv) diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c index 15f05fb3ed..cf167f64e8 100644 --- a/openair2/E1AP/e1ap_api.c +++ b/openair2/E1AP/e1ap_api.c @@ -114,7 +114,8 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req, // Create N3 tunnel int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req); if (ret != 0) { - LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n", + LOG_E(NR_RRC, + "drb_config_N3gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n", create_tunnel_req.ue_id); return ret; } diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index 347e9fbff5..49f95c82f7 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -125,7 +125,8 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, sdap_data_req); if (ret != 0) { - LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE rnti %ld\n", + LOG_E(NR_RRC, + "drb_config_gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n", create_tunnel_req.ue_id); return ret; } @@ -160,14 +161,13 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, return ret; } -static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) +static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) { rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[instance], req->rnti); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; protocol_ctxt_t ctxt = {0}; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0); - fill_DRB_configList(&ctxt, ue_context_p, xid); e1ap_bearer_setup_resp_t resp = {0}; resp.numPDUSessions = req->numPDUSessions; for (int i = 0; i < resp.numPDUSessions; ++i) { @@ -184,7 +184,8 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; // GTP tunnel for UL - int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, UE->DRB_configList, rrc->e1_inst); + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(UE); + int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, DRB_configList, rrc->e1_inst); if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); // Used to store teids: if monolithic, will simply be NULL @@ -203,7 +204,8 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const prepare_and_send_ue_context_modification_f1(ue_context_p, &resp); } -static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) { +static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) +{ // only update GTP tunnels if it is really a CU if (!NODE_IS_CU(RC.nrrrc[0]->node_type)) return; diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c index 390ab232a7..200729ec11 100644 --- a/openair2/RRC/NR/cucp_cuup_e1ap.c +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -36,13 +36,8 @@ extern RAN_CONTEXT_t RC; -static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) +static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) { - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[instance], req->rnti); - protocol_ctxt_t ctxt = {0}; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); - - fill_DRB_configList(&ctxt, ue_context_p, xid); MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ); e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p); memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t)); @@ -50,7 +45,7 @@ static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const r itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p); } -static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) +static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) { MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); e1ap_bearer_setup_req_t *req_msg = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg); diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h index ed4702b4b2..079a32e850 100644 --- a/openair2/RRC/NR/cucp_cuup_if.h +++ b/openair2/RRC/NR/cucp_cuup_if.h @@ -27,7 +27,7 @@ struct e1ap_bearer_setup_req_s; struct e1ap_bearer_setup_resp_s; -typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance, uint8_t xid); +typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance); struct gNB_RRC_INST_s; void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 390347362d..e72624527c 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -237,9 +237,6 @@ typedef enum { typedef struct gNB_RRC_UE_s { uint8_t primaryCC_id; - NR_DRB_ToAddModList_t *DRB_configList; - NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; - NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; drb_t established_drbs[NGAP_MAX_DRBS_PER_UE]; uint8_t DRB_active[NGAP_MAX_DRBS_PER_UE]; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 504aced681..fd9f38a3fb 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -156,7 +156,7 @@ void ue_cxt_mod_send_e1ap(MessageDef *msg, void ue_cxt_mod_direct(MessageDef *msg, instance_t instance); -void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid); +NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue); void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index fbaf2364c2..0113792030 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,7 +113,77 @@ mui_t rrc_gNB_mui = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// +NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) +{ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + if (ue->nb_of_pdusessions == 0) + return NULL; + int nb_drb_to_setup = rrc->configuration.drbs; + long drb_priority[NGAP_MAX_DRBS_PER_UE] = {0}; + uint8_t drb_id_to_setup_start = 0; + NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); + for (int i = 0; i < ue->nb_of_pdusessions; i++) { + if (ue->pduSession[i].status >= PDU_SESSION_STATUS_DONE) { + continue; + } + LOG_I(NR_RRC, "adding rnti %x pdusession %d, nb drb %d\n", ue->rnti, ue->pduSession[i].param.pdusession_id, nb_drb_to_setup); + for (long drb_id_add = 1; drb_id_add <= nb_drb_to_setup; drb_id_add++) { + uint8_t drb_id; + // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping + for (int qos_flow_index = 0; qos_flow_index < ue->pduSession[i].param.nb_qos; qos_flow_index++) { + switch (ue->pduSession[i].param.qos[qos_flow_index].fiveQI) { + case 1 ... 4: /* GBR */ + drb_id = next_available_drb(ue, &ue->pduSession[i], GBR_FLOW); + break; + case 5 ... 9: /* Non-GBR */ + if (rrc->configuration.drbs > 1) { /* Force the creation from gNB Conf file */ + LOG_W(NR_RRC, "Adding %d DRBs, from gNB config file (not decided by 5GC\n", rrc->configuration.drbs); + drb_id = next_available_drb(ue, &ue->pduSession[i], GBR_FLOW); + } else { + drb_id = next_available_drb(ue, &ue->pduSession[i], NONGBR_FLOW); + } + break; + default: + LOG_E(NR_RRC, "not supported 5qi %lu\n", ue->pduSession[i].param.qos[qos_flow_index].fiveQI); + ue->pduSession[i].status = PDU_SESSION_STATUS_FAILED; + continue; + } + drb_priority[drb_id - 1] = ue->pduSession[i].param.qos[qos_flow_index].allocation_retention_priority.priority_level; + if (drb_priority[drb_id - 1] < 0 || drb_priority[drb_id - 1] > NGAP_PRIORITY_LEVEL_NO_PRIORITY) { + LOG_E(NR_RRC, "invalid allocation_retention_priority.priority_level %ld set to _NO_PRIORITY\n", drb_priority[drb_id - 1]); + drb_priority[drb_id - 1] = NGAP_PRIORITY_LEVEL_NO_PRIORITY; + } + + if (drb_is_active(ue, drb_id)) { /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ + nb_drb_to_setup--; + } else { + generateDRB(ue, + drb_id, + &ue->pduSession[i], + rrc->configuration.enable_sdap, + rrc->security.do_drb_integrity, + rrc->security.do_drb_ciphering); + NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue->established_drbs[drb_id - 1]); + if (drb_id_to_setup_start == 0) + drb_id_to_setup_start = DRB_config->drb_Identity; + asn1cSeqAdd(&DRB_configList->list, DRB_config); + } + LOG_D(RRC, "DRB Priority %ld\n", drb_priority[drb_id]); // To supress warning for now + } + } + } + if (DRB_configList->list.count == 0) { + free(DRB_configList); + return NULL; + } + return DRB_configList; +} + +static void freeDRBlist(NR_DRB_ToAddModList_t *list) +{ + return; +} static void nr_rrc_addmod_srbs(int rnti, const NR_SRB_INFO_TABLE_ENTRY *srb_list, const int nb_srb, @@ -338,7 +408,9 @@ static void apply_macrlc_config(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const u gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; nr_rrc_mac_update_cellgroup(ue_p->rnti, cgc); nr_rrc_addmod_srbs(ctxt_pP->rntiMaybeUEid, ue_p->Srb, maxSRBs, cgc->rlc_BearerToAddModList); - nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid, ue_p->DRB_configList, cgc->rlc_BearerToAddModList); + NR_DRB_ToAddModList_t *DRBs = fill_DRB_configList(ue_p); + nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid, DRBs, cgc->rlc_BearerToAddModList); + freeDRBlist(DRBs); } void apply_macrlc_config_reest(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, const protocol_ctxt_t *const ctxt_pP, ue_id_t ue_id) @@ -591,83 +663,18 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co } } -void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid) -{ - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - int qos_flow_index = 0; - int i; - uint8_t drb_id_to_setup_start = 0; - uint8_t nb_drb_to_setup = rrc->configuration.drbs; - long drb_priority[NGAP_MAX_DRBS_PER_UE]; - - if (!ue_p->DRB_configList) - ue_p->DRB_configList = CALLOC(1, sizeof(*ue_p->DRB_configList)); - if (!ue_p->DRB_configList2[xid]) - ue_p->DRB_configList2[xid] = CALLOC(1, sizeof(**ue_p->DRB_configList2)); - - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) { - continue; - } - LOG_I(NR_RRC, "adding rnti %x pdusession %d, nb drb %d, xid %d\n", ue_p->rnti, ue_p->pduSession[i].param.pdusession_id, nb_drb_to_setup, xid); - for(long drb_id_add = 1; drb_id_add <= nb_drb_to_setup; drb_id_add++){ - uint8_t drb_id; - // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping - for (qos_flow_index = 0; qos_flow_index < ue_p->pduSession[i].param.nb_qos; qos_flow_index++) { - switch (ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI) { - case 1 ... 4: /* GBR */ - drb_id = next_available_drb(ue_p, &ue_p->pduSession[i], GBR_FLOW); - break; - case 5 ... 9: /* Non-GBR */ - if(rrc->configuration.drbs > 1) /* Force the creation from gNB Conf file - Should be used only in noS1 mode and rfsim for testing purposes. */ - drb_id = next_available_drb(ue_p, &ue_p->pduSession[i], GBR_FLOW); - else - drb_id = next_available_drb(ue_p, &ue_p->pduSession[i], NONGBR_FLOW); - break; - - default: - LOG_E(NR_RRC, "not supported 5qi %lu\n", ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI); - ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED; - continue; - } - drb_priority[drb_id - 1] = ue_p->pduSession[i].param.qos[qos_flow_index].allocation_retention_priority.priority_level; - if (drb_priority[drb_id - 1] < 0 || drb_priority[drb_id - 1] > NGAP_PRIORITY_LEVEL_NO_PRIORITY) { - LOG_E(NR_RRC, "invalid allocation_retention_priority.priority_level %ld set to _NO_PRIORITY\n", drb_priority[drb_id - 1]); - drb_priority[drb_id - 1] = NGAP_PRIORITY_LEVEL_NO_PRIORITY; - } - - if(drb_is_active(ue_p, drb_id)){ /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ - nb_drb_to_setup--; - } else { - generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); - NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue_p->established_drbs[drb_id-1]); - if (drb_id_to_setup_start == 0) - drb_id_to_setup_start = DRB_config->drb_Identity; - asn1cSeqAdd(&ue_p->DRB_configList->list, DRB_config); - asn1cSeqAdd(&ue_p->DRB_configList2[xid]->list, DRB_config); - } - LOG_D(RRC, "DRB Priority %ld\n", drb_priority[drb_id]); // To supress warning for now - } - } - - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_p->pduSession[i].xid = xid; - } -} - //----------------------------------------------------------------------------- void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) //----------------------------------------------------------------------------- { gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; - int xid = -1; + uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); int drb_id_to_setup_start = 1; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList; - int nb_drb_to_setup = DRB_configList->list.count; - + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); + int nb_drb_to_setup = DRB_configList ? DRB_configList->list.count : 0; + ue_p->xids[xid] = RRC_PDUSESSION_ESTABLISH; struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); @@ -681,7 +688,10 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c if (ue_p->pduSession[j].param.nas_pdu.buffer != NULL) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_p->pduSession[j].param.nas_pdu.buffer, ue_p->pduSession[j].param.nas_pdu.length); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)ue_p->pduSession[j].param.nas_pdu.buffer, + ue_p->pduSession[j].param.nas_pdu.length); + ue_p->pduSession[j].status = PDU_SESSION_STATUS_DONE; asn1cSeqAdd(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); LOG_I(NR_RRC, "add NAS info with size %d (pdusession idx %d)\n", ue_p->pduSession[j].param.nas_pdu.length, j); @@ -690,7 +700,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c LOG_E(NR_RRC, "no NAS info (pdusession idx %d)\n", j); } - xid = ue_p->pduSession[j].xid; + ue_p->pduSession[j].xid = xid; } /* If list is empty free the list and reset the address */ @@ -701,7 +711,6 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup; - AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid); uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); int size = do_RRCReconfiguration(ctxt_pP, @@ -730,7 +739,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c ue_p->pduSession[i].param.nas_pdu.buffer = NULL; } } - + freeDRBlist(DRB_configList); LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); LOG_D(NR_RRC, "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", @@ -763,19 +772,15 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( rrc_gNB_ue_context_t *ue_context_pP) //----------------------------------------------------------------------------- { - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList2 = NULL; - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList - *dedicatedNAS_MessageList = NULL; + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); int qos_flow_index = 0; uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - ue_p->xids[xid] = RRC_DEDICATED_RECONF; + ue_p->xids[xid] = RRC_PDUSESSION_MODIFY; - DRB_configList2 = CALLOC(1, sizeof(NR_DRB_ToAddModList_t)); - memset(DRB_configList2, 0, sizeof(NR_DRB_ToAddModList_t)); - - dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = + CALLOC(1, sizeof(*dedicatedNAS_MessageList)); + NR_DRB_ToAddMod_t *DRB_config = NULL; for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { // bypass the new and already configured pdu sessions @@ -830,7 +835,6 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( ue_p->pduSession[i].cause_value = NGAP_CauseRadioNetwork_not_supported_5QI_value; continue; } - LOG_I(NR_RRC, "PDU SESSION ID %ld, DRB ID %ld (index %d), QOS flow %d, 5QI %ld \n", DRB_config->cnAssociation->choice.sdap_Config->pdu_Session, @@ -840,7 +844,7 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI); } - asn1cSeqAdd(&DRB_configList2->list, DRB_config); + asn1cSeqAdd(&DRB_configList->list, DRB_config); ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; ue_p->pduSession[i].xid = xid; @@ -862,21 +866,21 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( uint8_t buffer[RRC_BUF_SIZE]; int size = do_RRCReconfiguration(ctxt_pP, - buffer, - RRC_BUF_SIZE, - xid, - NULL, - DRB_configList2, - NULL, - NULL, - NULL, - NULL, - dedicatedNAS_MessageList, - NULL, - NULL, - NULL, - NULL, - NULL); + buffer, + RRC_BUF_SIZE, + xid, + NULL, + DRB_configList, + NULL, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL, + NULL, + NULL, + NULL, + NULL); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); /* Free all NAS PDUs */ @@ -922,37 +926,23 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( uint8_t *nas_buffer) //----------------------------------------------------------------------------- { - int i; - NR_DRB_ToReleaseList_t **DRB_Release_configList2 = NULL; - NR_DRB_Identity_t *DRB_release; - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList - *dedicatedNAS_MessageList = NULL; - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - DRB_Release_configList2 = &ue_p->DRB_Release_configList2[xid]; - if (*DRB_Release_configList2) { - free(*DRB_Release_configList2); - } + NR_DRB_ToReleaseList_t *DRB_Release_configList2 = CALLOC(sizeof(*DRB_Release_configList2), 1); - *DRB_Release_configList2 = CALLOC(1, sizeof(**DRB_Release_configList2)); - for(i = 0; i < NB_RB_MAX; i++) { + for (int i = 0; i < NB_RB_MAX; i++) { if ((ue_p->pduSession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_p->pduSession[i].xid == xid) { - DRB_release = CALLOC(1, sizeof(NR_DRB_Identity_t)); - *DRB_release = i+1; - asn1cSeqAdd(&(*DRB_Release_configList2)->list, DRB_release); + asn1cSequenceAdd(DRB_Release_configList2->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = i + 1; } } /* If list is empty free the list and reset the address */ + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; if (nas_length > 0) { - dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); - dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); - memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(dedicatedNAS_Message, - (char *)nas_buffer, - nas_length); - asn1cSeqAdd(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList)); + asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, dedicatedNAS_Message); + OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)nas_buffer, nas_length); LOG_I(NR_RRC,"add NAS info with size %d\n", nas_length); } else { LOG_W(NR_RRC,"dedlicated NAS list is empty\n"); @@ -965,7 +955,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( xid, NULL, NULL, - *DRB_Release_configList2, + DRB_Release_configList2, NULL, NULL, NULL, @@ -1019,10 +1009,7 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co uint8_t kUPenc[16] = {0}; uint8_t kUPint[16] = {0}; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList2[xid]; - NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_p->DRB_Release_configList2[xid]; - NR_DRB_Identity_t *drb_id_p = NULL; - // uint8_t nr_DRB2LCHAN[8]; + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); /* Derive the keys from kgnb */ if (DRB_configList != NULL) { @@ -1127,25 +1114,8 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co } // end if (DRB_configList->list.array[i]) } // end for (int i = 0; i < DRB_configList->list.count; i++) - free(DRB_configList); - ue_p->DRB_configList2[xid] = NULL; } // end if DRB_configList != NULL - - if(DRB_Release_configList2 != NULL) { - for (int i = 0; i < DRB_Release_configList2->list.count; i++) { - if (DRB_Release_configList2->list.array[i]) { - drb_id_p = DRB_Release_configList2->list.array[i]; - drb_id = *drb_id_p; - - if (ue_p->DRB_active[drb_id] == 1) { - ue_p->DRB_active[drb_id] = 0; - } - } - } - - free(DRB_Release_configList2); - ue_p->DRB_Release_configList2[xid] = NULL; - } + freeDRBlist(DRB_configList); } //----------------------------------------------------------------------------- @@ -1219,35 +1189,6 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP, nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } -/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the DRBs -/// that the UE previously had, it gets the information from the established_drbs -/// struct. -/// @param new_xid The new RRC transaction id. -void RRCReestablishmentComplete_fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP, - const uint8_t new_xid) -{ - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); - - if (*DRB_configList2) { - free(*DRB_configList2); - LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->DRB_configList2[%d])\n", new_xid); - } - - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - - for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { - if (ue_p->established_drbs[i].status != DRB_INACTIVE) { - ue_p->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; - DRB_config = generateDRB_ASN1(&ue_p->established_drbs[i]); - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); - } - } -} - /// @brief Function used in RRCReestablishmentComplete procedure to update the NGU Tunnels. /// @param reestablish_rnti is the old C-RNTI void RRCReestablishmentComplete_update_ngu_tunnel(const protocol_ctxt_t *const ctxt_pP, @@ -1349,7 +1290,6 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx nr_rrc_pdcp_config_security(ctxt_pP, ue_context_pP, send_security_mode_command); LOG_D(NR_RRC, "RRC Reestablishment - set security successfully \n"); } - RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid); RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti); RRCReestablishmentComplete_nas_pdu_update(ue_context_pP, xid); @@ -1377,11 +1317,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx asn1cSeqAdd(&cellGroupConfig->rlc_BearerToAddModList->list, ue_p->masterCellGroup->rlc_BearerToAddModList->list.array[i]); for (i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { - cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = - CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); - *cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; + asn1cCallocOne(cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC, + NR_RLC_BearerConfig__reestablishRLC_true); } + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, true); int size = do_RRCReconfiguration(ctxt_pP, @@ -1389,7 +1329,7 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx RRC_BUF_SIZE, new_xid, SRBs, - ue_p->DRB_configList2[new_xid], + DRB_configList, NULL, NULL, NULL, @@ -1401,7 +1341,7 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx NULL, cellGroupConfig); freeSRBlist(SRBs); - + freeDRBlist(DRB_configList); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); @@ -2364,7 +2304,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i // send the F1 response message up to update F1-U tunnel info // it seems the rrc transaction id (xid) is not needed here - rrc->cucp_cuup.bearer_context_mod(&req, instance, 0); + rrc->cucp_cuup.bearer_context_mod(&req, instance); } if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index cb763f0583..f0a7f3b90f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -278,9 +278,6 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) static int decodePDUSessionResourceSetup(pdusession_t *session) { NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL; - for (int i=0; ipdusessionTransfer.length; i++) - printf("%02x:",session->pdusessionTransfer.buffer[i]); - printf("\n"); asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; asn_dec_rval_t dec_rval = aper_decode(&st, &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, (void **)&pdusessionTransfer, session->pdusessionTransfer.buffer, session->pdusessionTransfer.length, 0, 0); @@ -819,7 +816,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins } int xid = rrc_gNB_get_next_transaction_identifier(instance); UE->xids[xid] = RRC_PDUSESSION_ESTABLISH; - rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance, xid); + rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance); return; } From 7e7b3c13f1ab1ae664982b6f8a16ddbe9ac5b2e3 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 6 Jul 2023 09:01:04 +0100 Subject: [PATCH 100/119] Fix multiple PDUSessions --- openair2/E1AP/e1ap.c | 9 ++- openair2/RRC/NR/rrc_gNB.c | 80 ++++++++++++++++--------- openair2/RRC/NR/rrc_gNB_NGAP.c | 8 ++- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 10 ++++ 4 files changed, 77 insertions(+), 30 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 6c33ddf973..7a1954f714 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -589,7 +589,14 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare for (DRB_nGRAN_to_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRB2Setup; j++) { asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); - ieC6_1_1->dRB_ID = j->id; + + ieC6_1_1->dRB_ID = ieC6_1->pDU_Session_ID; + LOG_W(E1AP, + "%s: %d Current implementation configures one DRB per PDUSession, ieC6_1->pDU_Session_ID %ld, ieC6_1_1->dRB_ID %ld\n", + __FUNCTION__, + __LINE__, + ieC6_1->pDU_Session_ID, + ieC6_1_1->dRB_ID); ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB; ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0113792030..a23c260612 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,6 +113,44 @@ mui_t rrc_gNB_mui = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// + +static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + if (!ue->Srb[1].Active) { + LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); + return NULL; + } + NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); + for (int i = 0; i < maxSRBs; i++) { + if (ue->Srb[i].Active) { + asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); + srb->srb_Identity = i; + if (reestablish && i == 2) { + asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); + } + } + } + return list; +} + +static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue->established_drbs[i].status != DRB_INACTIVE) { + ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); + if (reestablish) { + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + } + asn1cSeqAdd(&DRB_configList->list, DRB_config); + } + } + return DRB_configList; +} + NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) { gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -374,24 +412,6 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) return tmp; } -static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) -{ - if (!ue->Srb[1].Active) { - LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); - return NULL; - } - NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); - for (int i = 0; i < maxSRBs; i++) - if (ue->Srb[i].Active) { - asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); - srb->srb_Identity = i; - if (reestablish && i == 2) { - asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); - } - } - return list; -} - static void freeSRBlist(NR_SRB_ToAddModList_t *l) { if (l) { @@ -702,6 +722,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c ue_p->pduSession[j].xid = xid; } + freeDRBlist(DRB_configList); /* If list is empty free the list and reset the address */ if (dedicatedNAS_MessageList->list.count == 0) { @@ -709,16 +730,27 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c dedicatedNAS_MessageList = NULL; } + /* Free all NAS PDUs */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_p->pduSession[i].param.nas_pdu.buffer); + ue_p->pduSession[i].param.nas_pdu.buffer = NULL; + } + } + NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup; uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); + int size = do_RRCReconfiguration(ctxt_pP, buffer, RRC_BUF_SIZE, xid, SRBs, - DRB_configList, + DRBs, NULL, NULL, NULL, @@ -731,15 +763,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c cellGroupConfig); LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); freeSRBlist(SRBs); - /* Free all NAS PDUs */ - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { - /* Free the NAS PDU buffer and invalidate it */ - free(ue_p->pduSession[i].param.nas_pdu.buffer); - ue_p->pduSession[i].param.nas_pdu.buffer = NULL; - } - } - freeDRBlist(DRB_configList); + freeDRBlist(DRBs); LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); LOG_D(NR_RRC, "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index f0a7f3b90f..fd31004a17 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -778,7 +778,13 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins for (int j=0; j < pdu->numDRB2Setup; j++) { DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; - drb->id = i + j + UE->nb_of_pdusessions; + drb->id = session->pdusession_id; + LOG_W(NR_RRC, + "%s: %d Current implementation configures one DRB per PDUSession, session->pdusession_id %d, drb->id %ld\n", + __FUNCTION__, + __LINE__, + session->pdusession_id, + drb->id); drb->defaultDRB = E1AP_DefaultDRB_true; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 9e6e7961d6..57dcd35a9b 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -147,6 +147,16 @@ uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession { uint8_t drb_id; + drb_id = pdusession->param.pdusession_id; + LOG_W(NR_RRC, + "%s: %d Current implementation configures one DRB per PDUSession, pdusession_id %d, drb_id %d\n", + __FUNCTION__, + __LINE__, + pdusession->param.pdusession_id, + drb_id); + + return drb_id; + if(!is_gbr) { /* Find if Non-GBR DRB exists in the same PDU Session */ for (drb_id = 0; drb_id < NGAP_MAX_DRBS_PER_UE; drb_id++) if (pdusession->param.used_drbs[drb_id] == DRB_ACTIVE_NONGBR) From 1fdf71e1db5bf12abc0bca6f380dbe468d53b60e Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 6 Jul 2023 19:45:10 +0200 Subject: [PATCH 101/119] Address review comments --- openair2/RRC/NR/cucp_cuup_direct.c | 2 ++ openair2/RRC/NR/rrc_gNB.c | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index 49f95c82f7..9c4e6462a4 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -187,6 +187,8 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(UE); int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, DRB_configList, rrc->e1_inst); if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); + // the code is very badly organized, it is not possible here to call freeDRBlist() + ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList,DRB_configList ); // Used to store teids: if monolithic, will simply be NULL if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a23c260612..05df1da23c 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -133,7 +133,10 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) return list; } -static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +// not clear what this function do against fill_DRB_configList() +// it sets reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true +// else it should probably be removed and merged into fill_DRB_configList +static NR_DRB_ToAddModList_t *createDRBlistReestablish(gNB_RRC_UE_t *ue) { NR_DRB_ToAddMod_t *DRB_config = NULL; NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); @@ -142,9 +145,6 @@ static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) if (ue->established_drbs[i].status != DRB_INACTIVE) { ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); - if (reestablish) { - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - } asn1cSeqAdd(&DRB_configList->list, DRB_config); } } @@ -220,6 +220,7 @@ NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) static void freeDRBlist(NR_DRB_ToAddModList_t *list) { + //ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, list); return; } static void nr_rrc_addmod_srbs(int rnti, @@ -743,7 +744,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); - NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); + NR_DRB_ToAddModList_t *DRBs = createDRBlistReestablish(ue_p); int size = do_RRCReconfiguration(ctxt_pP, buffer, From 4deb58339b20fe6393dd10900cb547506b5bbc01 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Fri, 7 Jul 2023 11:01:04 +0100 Subject: [PATCH 102/119] Fix multiple PDUSessions after review, now DRBs are configured sequentially, no matter what PDUSession id we receive --- openair2/E1AP/e1ap.c | 9 +- openair2/RRC/NR/rrc_gNB.c | 112 ++++++++++++------------ openair2/RRC/NR/rrc_gNB_NGAP.c | 8 +- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 18 +--- 4 files changed, 63 insertions(+), 84 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 7a1954f714..6c33ddf973 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -589,14 +589,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare for (DRB_nGRAN_to_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRB2Setup; j++) { asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); - - ieC6_1_1->dRB_ID = ieC6_1->pDU_Session_ID; - LOG_W(E1AP, - "%s: %d Current implementation configures one DRB per PDUSession, ieC6_1->pDU_Session_ID %ld, ieC6_1_1->dRB_ID %ld\n", - __FUNCTION__, - __LINE__, - ieC6_1->pDU_Session_ID, - ieC6_1_1->dRB_ID); + ieC6_1_1->dRB_ID = j->id; ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB; ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 05df1da23c..776c6b9275 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -114,43 +114,6 @@ mui_t rrc_gNB_mui = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// -static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) -{ - if (!ue->Srb[1].Active) { - LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); - return NULL; - } - NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); - for (int i = 0; i < maxSRBs; i++) { - if (ue->Srb[i].Active) { - asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); - srb->srb_Identity = i; - if (reestablish && i == 2) { - asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); - } - } - } - return list; -} - -// not clear what this function do against fill_DRB_configList() -// it sets reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true -// else it should probably be removed and merged into fill_DRB_configList -static NR_DRB_ToAddModList_t *createDRBlistReestablish(gNB_RRC_UE_t *ue) -{ - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); - - for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { - if (ue->established_drbs[i].status != DRB_INACTIVE) { - ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; - DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); - asn1cSeqAdd(&DRB_configList->list, DRB_config); - } - } - return DRB_configList; -} - NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) { gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -413,6 +376,42 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) return tmp; } +static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + if (!ue->Srb[1].Active) { + LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); + return NULL; + } + NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); + for (int i = 0; i < maxSRBs; i++) + if (ue->Srb[i].Active) { + asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); + srb->srb_Identity = i; + if (reestablish && i == 2) { + asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); + } + } + return list; +} + +static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue->established_drbs[i].status != DRB_INACTIVE) { + DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); + if (reestablish) { + ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + } + asn1cSeqAdd(&DRB_configList->list, DRB_config); + } + } + return DRB_configList; +} + static void freeSRBlist(NR_SRB_ToAddModList_t *l) { if (l) { @@ -744,7 +743,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); - NR_DRB_ToAddModList_t *DRBs = createDRBlistReestablish(ue_p); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); int size = do_RRCReconfiguration(ctxt_pP, buffer, @@ -1034,7 +1033,7 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co uint8_t kUPenc[16] = {0}; uint8_t kUPint[16] = {0}; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); + NR_DRB_ToAddModList_t *DRB_configList = createDRBlist(ue_p, false); /* Derive the keys from kgnb */ if (DRB_configList != NULL) { @@ -1048,18 +1047,20 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co /* Refresh SRBs/DRBs */ LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %04x\n", ue_p->rnti); ue_id_t reestablish_ue_id = 0; - if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) { - for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { - nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i]; - if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) { - ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++; - reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti; - LOG_D(NR_RRC, "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti); - // clear current C-RNTI from map - nr_reestablish_rnti_map->ue_id = 0; - nr_reestablish_rnti_map->c_rnti = 0; - break; - } + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i]; + if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) { + ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++; + reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti; + LOG_D(NR_RRC, + "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", + i, + nr_reestablish_rnti_map->ue_id, + nr_reestablish_rnti_map->c_rnti); + // clear current C-RNTI from map + nr_reestablish_rnti_map->ue_id = 0; + nr_reestablish_rnti_map->c_rnti = 0; + break; } } NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); @@ -1346,15 +1347,16 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx NR_RLC_BearerConfig__reestablishRLC_true); } - NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); - uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, true); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, true); + + uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ctxt_pP, buffer, RRC_BUF_SIZE, new_xid, SRBs, - DRB_configList, + DRBs, NULL, NULL, NULL, @@ -1366,7 +1368,7 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx NULL, cellGroupConfig); freeSRBlist(SRBs); - freeDRBlist(DRB_configList); + freeDRBlist(DRBs); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index fd31004a17..f0a7f3b90f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -778,13 +778,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins for (int j=0; j < pdu->numDRB2Setup; j++) { DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; - drb->id = session->pdusession_id; - LOG_W(NR_RRC, - "%s: %d Current implementation configures one DRB per PDUSession, session->pdusession_id %d, drb->id %ld\n", - __FUNCTION__, - __LINE__, - session->pdusession_id, - drb->id); + drb->id = i + j + UE->nb_of_pdusessions; drb->defaultDRB = E1AP_DefaultDRB_true; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 57dcd35a9b..4c5c50fb00 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -147,25 +147,15 @@ uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession { uint8_t drb_id; - drb_id = pdusession->param.pdusession_id; - LOG_W(NR_RRC, - "%s: %d Current implementation configures one DRB per PDUSession, pdusession_id %d, drb_id %d\n", - __FUNCTION__, - __LINE__, - pdusession->param.pdusession_id, - drb_id); - - return drb_id; - - if(!is_gbr) { /* Find if Non-GBR DRB exists in the same PDU Session */ + if (0 /*!is_gbr*/) { /* Find if Non-GBR DRB exists in the same PDU Session */ for (drb_id = 0; drb_id < NGAP_MAX_DRBS_PER_UE; drb_id++) if (pdusession->param.used_drbs[drb_id] == DRB_ACTIVE_NONGBR) - return drb_id+1; + return drb_id + 1; } /* GBR Flow or a Non-GBR DRB does not exist in the same PDU Session, find an available DRB */ for (drb_id = 0; drb_id < NGAP_MAX_DRBS_PER_UE; drb_id++) - if(ue->DRB_active[drb_id] == DRB_INACTIVE) - return drb_id+1; + if (ue->DRB_active[drb_id] == DRB_INACTIVE) + return drb_id + 1; /* From this point, we need to handle the case that all DRBs are already used by the UE. */ LOG_E(RRC, "Error - All the DRBs are used - Handle this\n"); return DRB_INACTIVE; From cfc7a70f9a205726414e83e822e2eeb42c5df6f0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 26 Jun 2023 09:30:53 +0200 Subject: [PATCH 103/119] bugfix in ue msg3 scheduler --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b60e0199a2..52b5bd75dd 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1459,7 +1459,7 @@ int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, uint8_t is_Msg3, frame_t curren DURATION_RX_TO_TX); *slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; - if (current_slot + k2 + delta > nr_slots_per_frame[mu]){ + if (current_slot + k2 + delta >= nr_slots_per_frame[mu]){ *frame_tx = (current_frame + 1) % 1024; } else { *frame_tx = current_frame; From 0449ab7908c741ff5ab9517877651617492b347f Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 9 Jun 2023 10:25:07 +0200 Subject: [PATCH 104/119] further cleanup of config files for CI --- ...gnb.band261.32PRB.rfsim.phytest-dora.conf} | 0 ...gnb.band66.106prb.rfsim.phytest-dora.conf} | 0 ...gnb.band78.106PRB.rfsim.phytest-dora.conf} | 0 ...b.band78.106PRB.usrpn300.phytest-dora.conf | 260 ++++++++++++++++++ ....band78.162PRB.usrpn300.phytest-dora.conf} | 0 ...b.band78.sa.106PRB.2x2.usrpn310.asue.conf} | 0 ...=> gnb.band78.sa.106PRB.2x2.usrpn310.conf} | 0 ....band78.sa.106PRB.ddsuu.2x2.usrpn310.conf} | 0 ...=> gnb.band78.sa.162PRB.2x2.usrpn310.conf} | 0 ...10.conf => gnb.sa.band78.24PRB.rfsim.conf} | 0 .../gnb.band78.tm1.fr1.106PRB.usrpn310.conf | 0 .../xml_files/fr1_sa_amarisoft_ue_1x.xml | 2 +- ci-scripts/xml_files/fr1_sa_oaiue_n310.xml | 2 +- ci-scripts/xml_files/fr1_sa_quectel.xml | 2 +- .../xml_files/fr1_sa_quectel_162prb.xml | 2 +- .../xml_files/fr1_sa_quectel_stages.xml | 2 +- ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml | 2 +- .../gnb_nr_ue_usrp_run_multi_thread.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run.xml | 2 +- .../xml_files/gnb_phytest_usrp_run_60.xml | 2 +- .../xml_files/gnb_phytest_usrp_run_60_2x2.xml | 2 +- .../5g_rfsimulator_24prb/docker-compose.yaml | 2 +- .../docker-compose.yaml | 2 +- .../docker-compose.yaml | 2 +- .../docker-compose.yaml | 2 +- 25 files changed, 274 insertions(+), 14 deletions(-) rename ci-scripts/conf_files/{gnb.band261.tm1.32PRB.usrpn300.conf => gnb.band261.32PRB.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band66.tm1.106PRB.usrpn300.conf => gnb.band66.106prb.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.tm1.106PRB.usrpn300.conf => gnb.band78.106PRB.rfsim.phytest-dora.conf} (100%) create mode 100644 ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf rename ci-scripts/conf_files/{gnb.band78.tm1.162PRB.usrpn300.conf => gnb.band78.162PRB.usrpn300.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf => gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf => gnb.band78.sa.106PRB.2x2.usrpn310.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf => gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf => gnb.band78.sa.162PRB.2x2.usrpn310.conf} (100%) rename ci-scripts/conf_files/{gnb.sa.band78.fr1.24PRB.usrpb210.conf => gnb.sa.band78.24PRB.rfsim.conf} (100%) rename ci-scripts/conf_files/{ => untested}/gnb.band78.tm1.fr1.106PRB.usrpn310.conf (100%) diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf new file mode 100644 index 0000000000..453b03910b --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf @@ -0,0 +1,260 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 99; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + port = 36412 ; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; +} +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 50; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + }; + diff --git a/ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf rename to ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf similarity index 100% rename from ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf rename to ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf rename to ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf diff --git a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml b/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml index c34fa34cf1..c00e47223a 100644 --- a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml +++ b/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml @@ -87,7 +87,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml index 7105828be4..ec99cedf94 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -68,7 +68,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index b13de6f3ef..c23ae0b540 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -86,7 +86,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index d1c250862d..0544c82de2 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -70,7 +70,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 94cf5d71ef..0b840b7782 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -91,7 +91,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index dd2b15a4f2..53636de6a1 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml index 7c9d689e44..af48f00d5a 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP (Tx-Write-Threading enabled) - -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml index 382efbdd9e..c98796890f 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.default.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml index 24b0854224..3d91d55dfa 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.1x1.60.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml index 29d284886c..6231f45169 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.60.2x2.yaml NR 192.168.20.2 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index f076cf2db0..600f34cbc2 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -175,7 +175,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.24PRB.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml index b654f06d12..d93a4b1051 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band66.tm1.106PRB.usrpn300.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index eef67d713b..63293cf628 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band261.tm1.32PRB.usrpn300.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index ed2af44fbb..b3afb48e8d 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band78.tm1.106PRB.usrpn300.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" From 8048ea485b4c406526cba965d6b3071efdefa7aa Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 11:10:29 +0200 Subject: [PATCH 105/119] Remove old unused config file of gNB and XML for Amarisoft ue test --- ...nb.band78.sa.106PRB.2x2.usrpn310.asue.conf | 282 ------------------ .../xml_files/fr1_sa_amarisoft_ue_1x.xml | 124 -------- 2 files changed, 406 deletions(-) delete mode 100644 ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf delete mode 100644 ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml diff --git a/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf deleted file mode 100644 index a723e3a4b7..0000000000 --- a/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf +++ /dev/null @@ -1,282 +0,0 @@ -Active_gNBs = ( "gNB-OAI"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -gNBs = -( - { - ////////// Identification parameters: - gNB_ID = 0xe00; - -# cell_type = "CELL_MACRO_GNB"; - - gNB_name = "gNB-OAI"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - - plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0x010203 }) }); - - nr_cellid = 12345678L - -# tr_s_preference = "local_mac" - - ////////// Physical parameters: - - pusch_AntennaPorts = 2; - pdsch_AntennaPorts_XP = 2; - ul_prbblacklist = "51,52,53,54" - do_SRS = 0; - do_CSIRS = 1; - - servingCellConfigCommon = ( - { - #spCellConfigCommon - - physCellId = 0; - -# downlinkConfigCommon - #frequencyInfoDL - # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 - #absoluteFrequencySSB = 620640; - # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 - absoluteFrequencySSB = 621312; - # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 - #absoluteFrequencySSB = 634080; - # this is 3600.48 MHz - #absoluteFrequencySSB = 640032; - #dl_frequencyBand = 78; - # this is 3301.68 MHz - #dl_absoluteFrequencyPointA = 620112; - # this is 3300.60 MHz - dl_absoluteFrequencyPointA = 620040; - # this is 3502.56 MHz - #dl_absoluteFrequencyPointA = 633552; - # this is 3600.48 MHz - #dl_absoluteFrequencyPointA = 640032; - #scs-SpecificCarrierList - dl_offstToCarrier = 0; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_subcarrierSpacing = 1; - dl_carrierBandwidth = 106; - #initialDownlinkBWP - #genericParameters - # this is RBstart=0,L=106 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 28875; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - initialDLBWPsubcarrierSpacing = 1; - #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 11; - initialDLBWPsearchSpaceZero = 0; - - #uplinkConfigCommon - #frequencyInfoUL - ul_frequencyBand = 78; - #scs-SpecificCarrierList - ul_offstToCarrier = 0; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - ul_subcarrierSpacing = 1; - ul_carrierBandwidth = 106; - pMax = 20; - #initialUplinkBWP - #genericParameters - initialULBWPlocationAndBandwidth = 28875; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - initialULBWPsubcarrierSpacing = 1; - #rach-ConfigCommon - #rach-ConfigGeneric - prach_ConfigurationIndex = 98; -#prach_msg1_FDM -#0 = one, 1=two, 2=four, 3=eight - prach_msg1_FDM = 0; - prach_msg1_FrequencyStart = 0; - zeroCorrelationZoneConfig = 12; - preambleReceivedTargetPower = -104; -#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) - preambleTransMax = 6; -#powerRampingStep -# 0=dB0,1=dB2,2=dB4,3=dB6 - powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; -#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR -#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 - ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; -#ra_ContentionResolutionTimer -#(0..7) 8,16,24,32,40,48,56,64 - ra_ContentionResolutionTimer = 7; - rsrp_ThresholdSSB = 19; -#prach-RootSequenceIndex_PR -#1 = 839, 2 = 139 - prach_RootSequenceIndex_PR = 2; - prach_RootSequenceIndex = 1; - # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex - # - msg1_SubcarrierSpacing = 1, -# restrictedSetConfig -# 0=unrestricted, 1=restricted type A, 2=restricted type B - restrictedSetConfig = 0, - - msg3_DeltaPreamble = 1; - p0_NominalWithGrant =-90; - -# pucch-ConfigCommon setup : -# pucchGroupHopping -# 0 = neither, 1= group hopping, 2=sequence hopping - pucchGroupHopping = 0; - hoppingId = 40; - p0_nominal = -90; -# ssb_PositionsInBurs_BitmapPR -# 1=short, 2=medium, 3=long - ssb_PositionsInBurst_PR = 2; - ssb_PositionsInBurst_Bitmap = 1; - -# ssb_periodicityServingCell -# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 - ssb_periodicityServingCell = 2; - -# dmrs_TypeA_position -# 0 = pos2, 1 = pos3 - dmrs_TypeA_Position = 0; - -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - subcarrierSpacing = 1; - - - #tdd-UL-DL-ConfigurationCommon -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - referenceSubcarrierSpacing = 1; - # pattern1 - # dl_UL_TransmissionPeriodicity - # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 - dl_UL_TransmissionPeriodicity = 6; - nrofDownlinkSlots = 7; - nrofDownlinkSymbols = 6; - nrofUplinkSlots = 2; - nrofUplinkSymbols = 4; - - ssPBCH_BlockPower = -25; - } - - ); - - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - ////////// AMF parameters: - amf_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - NETWORK_INTERFACES : - { - - GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; - GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; - GNB_INTERFACE_NAME_FOR_NGU = "em1"; - GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 220; - pucch_TargetSNRx10 = 220; - ulsch_max_frame_inactivity = 10; - } -); - -L1s = ( -{ - num_cc = 1; - tr_n_preference = "local_mac"; - prach_dtx_threshold = 200; -# pucch0_dtx_threshold = 150; -} -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 2 - nb_rx = 2 - att_tx = 0 - att_rx = 0; - bands = [78]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 75; - eNB_instances = [0]; - ##beamforming 1x2 matrix: 1 layer x 2 antennas - bf_weights = [0x00007fff, 0x0000]; - ##beamforming 1x4 matrix: 1 layer x 4 antennas - #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; - ## beamforming 2x2 matrix: - # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; - ## beamforming 4x4 matrix: - #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; - sf_extension = 0 - sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" - } -); - -THREAD_STRUCT = ( - { - #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - parallel_config = "PARALLEL_SINGLE_THREAD"; - #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_ENABLE"; - } -); - -security = { - # preferred ciphering algorithms - # the first one of the list that an UE supports in chosen - # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea2" ); - - # preferred integrity algorithms - # the first one of the list that an UE supports in chosen - # valid values: nia0, nia1, nia2, nia3 - integrity_algorithms = ( "nia1", "nia2" ); - - # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter - # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' - drb_ciphering = "yes"; - drb_integrity = "yes"; -}; - - log_config : - { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; - f1ap_log_level ="info"; - }; diff --git a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml b/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml deleted file mode 100644 index c00e47223a..0000000000 --- a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - TEST-SA-FR1-Tab1 - SA Ping DL UL with 1 AS UE - tasks - 1 - - 100000 - 010000 - 040000 - 010001 - 010002 - 050000 - 010100 - 010200 - 011111 - 080000 - 200000 - - - - - Custom_Command - Disable Sleep States - asterix - sudo cpupower idle-set -D 0 - - - Custom_Command - Enable Sleep States - asterix - sudo cpupower idle-set -E - - - - Initialize_UE - Initialize AS-UE Scenario - amarisoft_ue - - - Attach_UE - Attach UE - amarisoft_ue_1 - - - Attach_UE - Attach UE - amarisoft_ue_2 - - - Detach_UE - Detach UE - amarisoft_ue_1 - - - Detach_UE - Detach UE - amarisoft_ue_2 - - - Terminate_UE - Terminate UE - amarisoft_ue - - - - Initialize_eNB - Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time - 0 - 0 - nr - yes - yes - datalog_rt_stats.2x2.yaml - 172.21.19.14 - numactl --cpunodebind=netdev:ens2f0np0 --membind=netdev:ens2f0np0 - - - - Ping - Ping Log Analysis - amarisoft_ue_1 amarisoft_ue_2 - 1 - - - - IdleSleep - Sleep - 5 - - - - - Terminate_eNB - Terminate gNB - 0 - 0 - nr - - - - From 0409dcf5ee84c4bd3679c842153a1b747c603311 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 12:18:56 +0200 Subject: [PATCH 106/119] Rename sa-2x2-usrpn310 config and correct in XMLs using the same --- ....2x2.usrpn310.conf => gnb.sa.band78.106prb.usrp310.2x2.conf} | 0 ci-scripts/xml_files/fr1_sa_oaiue_n310.xml | 2 +- ci-scripts/xml_files/fr1_sa_quectel_stages.xml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename ci-scripts/conf_files/{gnb.band78.sa.106PRB.2x2.usrpn310.conf => gnb.sa.band78.106prb.usrp310.2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml index ec99cedf94..73cb246391 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -68,7 +68,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 0b840b7782..8900462ad1 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -91,7 +91,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr From 23c1d4e63cdb34484eac0409762a4ada88131db1 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 12:26:41 +0200 Subject: [PATCH 107/119] Rename sa-2x2-ddsuu config file and correct in XML file using the same --- ...rpn310.conf => gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf} | 0 ci-scripts/xml_files/fr1_sa_quectel.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-scripts/conf_files/{gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf => gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index c23ae0b540..33a817f2e8 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -86,7 +86,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr From 8f4ccdcf3c857e940cbc3420890e3ec2dca1f324 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 12:30:30 +0200 Subject: [PATCH 108/119] Rename sa-162prb config file and correct in XML using it --- ...2x2.usrpn310.conf => gnb.sa.band78.162prb.usrpn310.2x2.conf} | 0 ci-scripts/xml_files/fr1_sa_quectel_162prb.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-scripts/conf_files/{gnb.band78.sa.162PRB.2x2.usrpn310.conf => gnb.sa.band78.162prb.usrpn310.2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index 0544c82de2..0a60cb5d7a 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -70,7 +70,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr From 7e6124bb54bc580d4dde096d94321eb02dfd8026 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 9 Jun 2023 18:01:13 +0200 Subject: [PATCH 109/119] Cleanup in rfsim config files --- .../gnb.nsa.band78.106prb.usrpb200.conf | 2 +- .../gnb.sa.band78.106prb.rfsim.2x2.conf | 4 ++-- .../conf_files/gnb.sa.band78.106prb.rfsim.conf | 18 ------------------ .../gnb.sa.band78.106prb.usrp310.2x2.conf | 14 -------------- ...nb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf | 1 - .../gnb.sa.band78.162prb.usrpn310.2x2.conf | 3 --- .../conf_files/gnb.sa.band78.24PRB.rfsim.conf | 2 +- .../gnb.sa.band78.51prb.usrpb200.conf | 2 -- 8 files changed, 4 insertions(+), 42 deletions(-) diff --git a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf index 53b81d0ae1..46b0c4f8d4 100644 --- a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf @@ -29,7 +29,7 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + absoluteFrequencySSB = 641272; dl_frequencyBand = 78; # this is 3600 MHz dl_absoluteFrequencyPointA = 640000; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf index cc70829aae..60b1e92f9e 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf @@ -32,10 +32,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 - absoluteFrequencySSB = 621312; # 641280 + absoluteFrequencySSB = 621312; dl_frequencyBand = 78; # this is 3300.60 MHz - dl_absoluteFrequencyPointA = 620040; # 640008 + dl_absoluteFrequencyPointA = 620040; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf index 9728977d21..61ec78328c 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf @@ -23,11 +23,7 @@ gNBs = ////////// Physical parameters: - #pusch_TargetSNRx10 = 200; - #pucch_TargetSNRx10 = 200; - ul_prbblacklist = "51,52,53,54" min_rxtxtime = 6; - do_SRS = 1; servingCellConfigCommon = ( { @@ -37,23 +33,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 - #absoluteFrequencySSB = 620640; # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 absoluteFrequencySSB = 621312; - # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 - #absoluteFrequencySSB = 634080; - # this is 3600.48 MHz - #absoluteFrequencySSB = 640032; - #dl_frequencyBand = 78; - # this is 3301.68 MHz - #dl_absoluteFrequencyPointA = 620112; # this is 3300.60 MHz dl_absoluteFrequencyPointA = 620040; - # this is 3502.56 MHz - #dl_absoluteFrequencyPointA = 633552; - # this is 3600.48 MHz - #dl_absoluteFrequencyPointA = 640032; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -208,7 +191,6 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; - ulsch_max_frame_inactivity = 1; } ); diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf index f5c0e23670..480bb45637 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf @@ -25,7 +25,6 @@ gNBs = pdsch_AntennaPorts_XP = 2; pusch_AntennaPorts = 2; - do_SRS = 0; servingCellConfigCommon = ( { @@ -35,23 +34,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 - #absoluteFrequencySSB = 620640; # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 absoluteFrequencySSB = 621312; - # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 - #absoluteFrequencySSB = 634080; - # this is 3600.48 MHz - #absoluteFrequencySSB = 640032; - #dl_frequencyBand = 78; - # this is 3301.68 MHz - #dl_absoluteFrequencyPointA = 620112; # this is 3300.60 MHz dl_absoluteFrequencyPointA = 620040; - # this is 3502.56 MHz - #dl_absoluteFrequencyPointA = 633552; - # this is 3600.48 MHz - #dl_absoluteFrequencyPointA = 640032; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf index e8fc796b61..c77399bbed 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf @@ -25,7 +25,6 @@ gNBs = pusch_AntennaPorts = 2; ul_prbblacklist = "51,52,53,54" - do_SRS = 0; servingCellConfigCommon = ( { diff --git a/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf index ec443b174a..a24f45f024 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf @@ -25,10 +25,7 @@ gNBs = pdsch_AntennaPorts_XP = 2; pusch_AntennaPorts = 2; - #pusch_TargetSNRx10 = 200; - #pucch_TargetSNRx10 = 200; ul_prbblacklist = "79,80,81,82" - do_SRS = 0; servingCellConfigCommon = ( { diff --git a/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf index 9a6efada5b..d188c1c8a3 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf @@ -17,7 +17,7 @@ gNBs = ////////// Physical parameters: - sib1_tda = 15; + sib1_tda = 15; min_rxtxtime = 6; servingCellConfigCommon = ( diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf index 16cc70ca4b..f94ba38eb5 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf @@ -17,8 +17,6 @@ gNBs = ////////// Physical parameters: - do_CSIRS = 0; - do_SRS = 0; servingCellConfigCommon = ( { From c357f96120b511a5120414eba7e03494b90426ad Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 12 Jun 2023 08:48:49 +0200 Subject: [PATCH 110/119] Rename config file for 5g-l2sim --- ...band78.106prb.l2sim.conf => gnb.sa.band78.106prb.l2sim.conf} | 0 ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-scripts/conf_files/{gnb.band78.106prb.l2sim.conf => gnb.sa.band78.106prb.l2sim.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.106prb.l2sim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.l2sim.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.106prb.l2sim.conf rename to ci-scripts/conf_files/gnb.sa.band78.106prb.l2sim.conf diff --git a/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml b/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml index db77cdae53..86c678c811 100644 --- a/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml @@ -174,7 +174,7 @@ services: - oai-spgwu - oai-amf volumes: - - ../../conf_files/gnb.band78.106prb.l2sim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.106prb.l2sim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s From 6c241ec759c4db2a6ea7d606df48373cccb28bd8 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 12 Jun 2023 08:54:43 +0200 Subject: [PATCH 111/119] Rename config file nsa-2x2 --- ...RB.usrpn310.conf => gnb.nsa.band78.106PRB.usrpn310.2x2.conf} | 0 ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 2 +- ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename ci-scripts/conf_files/{gnb.band78.nsa_2x2.106PRB.usrpn310.conf => gnb.nsa.band78.106PRB.usrpn310.2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf rename to ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 185d637218..5b84f7e43f 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -113,7 +113,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index d1515898ff..8e96dea441 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -118,7 +118,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr From 12a3045bec575bd8f8b113e9f18dadecbc4ee07b Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Wed, 14 Jun 2023 16:21:27 +0200 Subject: [PATCH 112/119] Config files: make them lowercase Changes for: - phytest-dora config file - rfsim-phytest-dora-106prb - phytest-dora-106prb-usrpn300 - lte-2x2-tm1 - lte-2x2-tm2 - NSA-2x2 - 4g-rfsim-mbms-fembms - 5grfsim-fr2-32prb - nsa-2x2-quectel - 5g-rfsim-24prb - test xml --- ....usrpn310.conf => enb.band38.lte_2x2.100prb.usrpn310.conf} | 0 ...pn310.conf => enb.band38.lte_2x2_tm2.100prb.usrpn310.conf} | 0 ....usrpn310.conf => enb.band38.nsa_2x2.100prb.usrpn310.conf} | 0 ...RB.rfsim.mbms.conf => enb.band7.tm1.25prb.rfsim.mbms.conf} | 0 ....50PRB.usrpb210.conf => enb.band7.tm1.50prb.usrpb210.conf} | 0 ...st-dora.conf => gnb.band261.32prb.rfsim.phytest-dora.conf} | 0 ...st-dora.conf => gnb.band78.106prb.rfsim.phytest-dora.conf} | 0 ...dora.conf => gnb.band78.106prb.usrpn300.phytest-dora.conf} | 0 ...dora.conf => gnb.band78.162prb.usrpn300.phytest-dora.conf} | 0 ...pn310.2x2.conf => gnb.nsa.band78.106prb.usrpn310.2x2.conf} | 0 ...band78.24PRB.rfsim.conf => gnb.sa.band78.24prb.rfsim.conf} | 0 ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 4 ++-- ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml | 4 ++-- ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml | 2 +- ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml | 2 +- ci-scripts/xml_files/test_case_list_template.xml | 2 +- .../yaml_files/4g_rfsimulator_fembms/docker-compose.yml | 2 +- ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml | 2 +- .../yaml_files/5g_rfsimulator_24prb/docker-compose.yaml | 2 +- .../yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml | 2 +- .../yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml | 2 +- ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml | 2 +- ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml | 2 +- doc/RUNMODEM.md | 2 +- openair1/SIMULATION/TOOLS/DOC/rtusage.md | 2 +- 28 files changed, 19 insertions(+), 19 deletions(-) rename ci-scripts/conf_files/{enb.band38.lte_2x2.100PRB.usrpn310.conf => enb.band38.lte_2x2.100prb.usrpn310.conf} (100%) rename ci-scripts/conf_files/{enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf => enb.band38.lte_2x2_tm2.100prb.usrpn310.conf} (100%) rename ci-scripts/conf_files/{enb.band38.nsa_2x2.100PRB.usrpn310.conf => enb.band38.nsa_2x2.100prb.usrpn310.conf} (100%) rename ci-scripts/conf_files/{enb.band7.tm1.25PRB.rfsim.mbms.conf => enb.band7.tm1.25prb.rfsim.mbms.conf} (100%) rename ci-scripts/conf_files/{enb.band7.tm1.50PRB.usrpb210.conf => enb.band7.tm1.50prb.usrpb210.conf} (100%) rename ci-scripts/conf_files/{gnb.band261.32PRB.rfsim.phytest-dora.conf => gnb.band261.32prb.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.106PRB.rfsim.phytest-dora.conf => gnb.band78.106prb.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.106PRB.usrpn300.phytest-dora.conf => gnb.band78.106prb.usrpn300.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.162PRB.usrpn300.phytest-dora.conf => gnb.band78.162prb.usrpn300.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.nsa.band78.106PRB.usrpn310.2x2.conf => gnb.nsa.band78.106prb.usrpn310.2x2.conf} (100%) rename ci-scripts/conf_files/{gnb.sa.band78.24PRB.rfsim.conf => gnb.sa.band78.24prb.rfsim.conf} (100%) diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf rename to ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf rename to ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf diff --git a/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf rename to ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf b/ci-scripts/conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf similarity index 100% rename from ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf rename to ci-scripts/conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf diff --git a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.50prb.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf rename to ci-scripts/conf_files/enb.band7.tm1.50prb.usrpb210.conf diff --git a/ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band261.32prb.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band261.32prb.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf rename to ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf diff --git a/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf similarity index 100% rename from ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf rename to ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 5b84f7e43f..325c5108d9 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -100,7 +100,7 @@ Initialize_eNB Initialize eNB - -O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function 0 0 lte @@ -113,7 +113,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index 8e96dea441..f5f4b1e549 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -105,7 +105,7 @@ Initialize_eNB Initialize eNB - -O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function 0 0 lte @@ -118,7 +118,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index 53636de6a1..1c4faaf99f 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml index af48f00d5a..2122f8651c 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP (Tx-Write-Threading enabled) - -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml index c98796890f..83e7d23f04 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.default.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml index 3d91d55dfa..31be6e8ac4 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.1x1.60.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml index 6231f45169..09dbbd7757 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.60.2x2.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/test_case_list_template.xml b/ci-scripts/xml_files/test_case_list_template.xml index eecdfe80b9..fddf8ad0e4 100644 --- a/ci-scripts/xml_files/test_case_list_template.xml +++ b/ci-scripts/xml_files/test_case_list_template.xml @@ -42,7 +42,7 @@ Initialize_eNB Initialize eNB (FDD/Band1/5MHz/info) - -O enb.band7.tm1.50PRB.usrpb210.conf --log_config.global_log_options level,nocolor,time + -O enb.band7.tm1.50prb.usrpb210.conf --log_config.global_log_options level,nocolor,time diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml index f568989f3f..47e38ba08c 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml @@ -13,7 +13,7 @@ services: RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --eNBs.[0].component_carriers.[0].mbms_dedicated_serving_cell ENABLE --log_config.global_log_options level,nocolor,time volumes: - - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf healthcheck: test: /bin/bash -c "pgrep lte-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml index 5dc9ae1a04..81a85ff246 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml @@ -13,7 +13,7 @@ services: RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --log_config.global_log_options level,nocolor,time volumes: - - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf healthcheck: test: /bin/bash -c "pgrep lte-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 600f34cbc2..a113203d05 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -175,7 +175,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band78.24PRB.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.24prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index 63293cf628..349b07f2b4 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band261.32prb.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index b3afb48e8d..3f58340d1b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml index 9655cca180..8a7f4693ec 100644 --- a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml @@ -8,7 +8,7 @@ services: TZ: Europe/Paris USE_ADDITIONAL_OPTIONS: --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 volumes: - - ../../conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf:/opt/oai-enb/etc/enb.conf network_mode: "host" healthcheck: test: /bin/bash -c "pgrep lte-softmodem" diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml index 84711b0a3c..1f54e7e380 100644 --- a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml @@ -8,7 +8,7 @@ services: TZ: Europe/Paris USE_ADDITIONAL_OPTIONS: --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 volumes: - - ../../conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf:/opt/oai-enb/etc/enb.conf network_mode: "host" healthcheck: test: /bin/bash -c "pgrep lte-softmodem" diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index d32758b1a2..e25400a0a6 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -61,7 +61,7 @@ This setup requires an EPC, an OAI eNB and gNB, and a COTS Phone. A dedicated pa ### Launch eNB ```bash -sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50prb.usrpb210.conf ``` ### Launch gNB diff --git a/openair1/SIMULATION/TOOLS/DOC/rtusage.md b/openair1/SIMULATION/TOOLS/DOC/rtusage.md index 059d02a307..5e1bd1b1da 100644 --- a/openair1/SIMULATION/TOOLS/DOC/rtusage.md +++ b/openair1/SIMULATION/TOOLS/DOC/rtusage.md @@ -27,7 +27,7 @@ Several model lists can be defined in the oai configuration file. One, defined b Channel simulation parameters can also be specified on the command line: ```bash -./lte-softmodem -O ../../../ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf --noS1 --rfsim --rfsimulator.options chanmod --rfsimulator.serveraddr enb --telnetsrv --channelmod.modellist modellist_rfsimu_2 --channelmod.modellist_rfsimu_2.[1].offset 120 +./lte-softmodem -O ../../../ci-scripts/conf_files/enb.band7.tm1.50prb.usrpb210.conf --noS1 --rfsim --rfsimulator.options chanmod --rfsimulator.serveraddr enb --telnetsrv --channelmod.modellist modellist_rfsimu_2 --channelmod.modellist_rfsimu_2.[1].offset 120 ``` ### Using the telnet server to modify channel simulator parameters The telnet server includes a `channelmod` command which can be used to dynamically modify some channel model parameters. This command is only available when channel simulation is enabled (via `rfsimulator.options chanmod` option when running the rfsimulator. `channelmod` command has its own help: From c8f78a232fac3db846a097d9116f5bdd4fb4f694 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 23 Jun 2023 00:53:11 +0200 Subject: [PATCH 113/119] Move unused config to untested folder --- .../conf_files/{ => untested}/enb.band13.tm1.25PRB.usrpb210.conf | 0 .../conf_files/{ => untested}/enb.band13.tm1.50PRB.emtc.conf | 0 .../conf_files/{ => untested}/enb.band17.tm1.25PRB.usrpb210.conf | 0 .../{ => untested}/enb.band17.tm1.mbms.25PRB.usrpb210.conf | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename ci-scripts/conf_files/{ => untested}/enb.band13.tm1.25PRB.usrpb210.conf (100%) rename ci-scripts/conf_files/{ => untested}/enb.band13.tm1.50PRB.emtc.conf (100%) rename ci-scripts/conf_files/{ => untested}/enb.band17.tm1.25PRB.usrpb210.conf (100%) rename ci-scripts/conf_files/{ => untested}/enb.band17.tm1.mbms.25PRB.usrpb210.conf (100%) diff --git a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/untested/enb.band13.tm1.25PRB.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf rename to ci-scripts/conf_files/untested/enb.band13.tm1.25PRB.usrpb210.conf diff --git a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf b/ci-scripts/conf_files/untested/enb.band13.tm1.50PRB.emtc.conf similarity index 100% rename from ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf rename to ci-scripts/conf_files/untested/enb.band13.tm1.50PRB.emtc.conf diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/untested/enb.band17.tm1.25PRB.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf rename to ci-scripts/conf_files/untested/enb.band17.tm1.25PRB.usrpb210.conf diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/untested/enb.band17.tm1.mbms.25PRB.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf rename to ci-scripts/conf_files/untested/enb.band17.tm1.mbms.25PRB.usrpb210.conf From ff337b02af25efb5765d57a537adc59f886f6383 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Thu, 15 Jun 2023 12:00:00 +0200 Subject: [PATCH 114/119] Remove unused UE conf, clean up documentation --- ci-scripts/conf_files/lteue.usim.conf | 153 ------------------------- ci-scripts/conf_files/nr-ue-sim.conf | 7 -- ci-scripts/conf_files/nr-ue.nfapi.conf | 37 ------ ci-scripts/conf_files/ue.nfapi.conf | 37 ------ doc/L2NFAPI.md | 2 +- doc/L2NFAPI_NOS1.md | 8 +- doc/L2NFAPI_S1.md | 8 +- docker/Dockerfile.nrUE.rhel9 | 3 - docker/Dockerfile.nrUE.rocky | 4 - docker/Dockerfile.nrUE.ubuntu20 | 3 - 10 files changed, 9 insertions(+), 253 deletions(-) delete mode 100644 ci-scripts/conf_files/lteue.usim.conf delete mode 100644 ci-scripts/conf_files/nr-ue-sim.conf delete mode 100644 ci-scripts/conf_files/nr-ue.nfapi.conf delete mode 100644 ci-scripts/conf_files/ue.nfapi.conf diff --git a/ci-scripts/conf_files/lteue.usim.conf b/ci-scripts/conf_files/lteue.usim.conf deleted file mode 100644 index e9b02e9b1f..0000000000 --- a/ci-scripts/conf_files/lteue.usim.conf +++ /dev/null @@ -1,153 +0,0 @@ -# List of known PLMNS -PLMN: { - PLMN0: { - FULLNAME="OpenAirInterface"; - SHORTNAME="OAICN"; - MNC="96"; - MCC="208"; - }; -}; - -UE0: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; - -UE1: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; - -UE2: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; - -UE3: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; diff --git a/ci-scripts/conf_files/nr-ue-sim.conf b/ci-scripts/conf_files/nr-ue-sim.conf deleted file mode 100644 index 884430bf39..0000000000 --- a/ci-scripts/conf_files/nr-ue-sim.conf +++ /dev/null @@ -1,7 +0,0 @@ -uicc0 = { - imsi = "@FULL_IMSI@"; - key = "@FULL_KEY@"; - opc= "@OPC@"; - dnn= "@DNN@"; - nssai_sst=@NSSAI_SST@; -} diff --git a/ci-scripts/conf_files/nr-ue.nfapi.conf b/ci-scripts/conf_files/nr-ue.nfapi.conf deleted file mode 100644 index 90798702cf..0000000000 --- a/ci-scripts/conf_files/nr-ue.nfapi.conf +++ /dev/null @@ -1,37 +0,0 @@ -log_config = { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; -}; - - -L1s = ( - { - num_cc = 1; - tr_n_preference = "nfapi"; - local_n_if_name = "ens3"; - remote_n_address = "127.0.0.1"; //Proxy IP - local_n_address = "127.0.0.1"; - local_n_portc = 50600; - remote_n_portc = 50601; - local_n_portd = 50610; - remote_n_portd = 50611; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 90 - att_rx = 0; - bands = [7,38,42,43]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - } -); diff --git a/ci-scripts/conf_files/ue.nfapi.conf b/ci-scripts/conf_files/ue.nfapi.conf deleted file mode 100644 index 09ad7529b1..0000000000 --- a/ci-scripts/conf_files/ue.nfapi.conf +++ /dev/null @@ -1,37 +0,0 @@ -log_config = { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; -}; - - -L1s = ( - { - num_cc = 1; - tr_n_preference = "nfapi"; - local_n_if_name = "ens3"; - remote_n_address = "CI_ENB_IP_ADDR"; - local_n_address = "CI_UE_IP_ADDR"; - local_n_portc = 50000; - remote_n_portc = 50001; - local_n_portd = 50010; - remote_n_portd = 50011; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 90 - att_rx = 0; - bands = [7,38,42,43]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - } -); diff --git a/doc/L2NFAPI.md b/doc/L2NFAPI.md index e87f9f270c..d7bba0bfeb 100644 --- a/doc/L2NFAPI.md +++ b/doc/L2NFAPI.md @@ -64,7 +64,7 @@ $ sudo -E ./nr-softmodem -O ../ci-scripts/conf_files/episci/proxy_rcc.band78.tm1 ``` ### Start UE ```bash -$ sudo -E ./nr-uesoftmodem -O ../ci-scripts/conf_files/episci/proxy_nr-ue.nfapi.conf --nfapi STANDALONE_PNF --node-number 2 --sa --emulate-l1 +$ sudo -E ./nr-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --nfapi STANDALONE_PNF --node-number 2 --sa --emulate-l1 ``` ### EpiSci's Documentation A more detailed tutorial is available on the [EpiSci GitHub Repository](https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy#readme). diff --git a/doc/L2NFAPI_NOS1.md b/doc/L2NFAPI_NOS1.md index 10d0c2a577..b65aaef3ba 100644 --- a/doc/L2NFAPI_NOS1.md +++ b/doc/L2NFAPI_NOS1.md @@ -191,7 +191,7 @@ Last, the S1 interface shall be properly set. ```bash $ ssh sudousername@machineB cd ue_folder -# Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor +# Edit ci-scripts/conf_files/nrue.uicc.conf with your preferred editor ``` Verify the nFAPI interface setup on the loopback interface. @@ -246,9 +246,9 @@ In the second terminal (the one you used to build the UE): $ ssh sudousername@machineC cd ue_folder/cmake_targets # Test 64 UEs, 1 thread in FDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 # Test 64 UEs, 1 thread in TDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 # The "-T 1" option means TDD config ``` @@ -262,7 +262,7 @@ For example, running with 4 UEs: ```bash $ ssh sudousername@machineC cd ue_folder/cmake_targets -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 sleep 10 ifconfig ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX diff --git a/doc/L2NFAPI_S1.md b/doc/L2NFAPI_S1.md index e7faec106f..a8b287ddf3 100644 --- a/doc/L2NFAPI_S1.md +++ b/doc/L2NFAPI_S1.md @@ -196,7 +196,7 @@ Last, the S1 interface shall be properly set. ```bash $ ssh sudousername@machineB cd ue_folder -# Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor +# Edit ci-scripts/conf_files/nrue.uicc.conf with your preferred editor ``` Verify the nFAPI interface setup on the loopback interface. @@ -252,9 +252,9 @@ In the second terminal (the one you used to build the UE): $ ssh sudousername@machineC cd ue_folder/cmake_targets # Test 64 UEs, 1 thread in FDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 # Test 64 UEs, 1 thread in TDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 # The "-T 1" option means TDD config ``` @@ -268,7 +268,7 @@ For example, running with 4 UEs: ```bash $ ssh sudousername@machineC cd ue_folder/cmake_targets -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 sleep 10 ifconfig ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 53b179a935..b142847c8e 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -59,9 +59,6 @@ COPY --from=nr-ue-build \ ./ COPY ./docker/scripts/nr_ue_entrypoint.sh ./entrypoint.sh WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build \ - /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf \ - ./ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/Dockerfile.nrUE.rocky b/docker/Dockerfile.nrUE.rocky index f0cc4b5788..cb07b2eb6a 100644 --- a/docker/Dockerfile.nrUE.rocky +++ b/docker/Dockerfile.nrUE.rocky @@ -63,10 +63,6 @@ COPY --from=nr-ue-build \ ./ WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build \ - /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf \ - /oai-ran/docker/etc/nr-ue.nfapi.conf \ - ./ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/Dockerfile.nrUE.ubuntu20 b/docker/Dockerfile.nrUE.ubuntu20 index c298394abd..a4b63d3cef 100644 --- a/docker/Dockerfile.nrUE.ubuntu20 +++ b/docker/Dockerfile.nrUE.ubuntu20 @@ -65,9 +65,6 @@ COPY --from=nr-ue-build \ COPY ./docker/scripts/nr_ue_entrypoint.sh ./entrypoint.sh WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build \ - /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf \ - ./ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ From c25ee6fd322f07db085041b1897a0f1f42abcd00 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jun 2023 08:35:37 +0200 Subject: [PATCH 115/119] Move symlink creation to radio/transport device to cmake --- cmake_targets/build_oai | 19 ------------------- radio/AW2SORI/CMakeLists.txt | 3 +++ radio/BLADERF/CMakeLists.txt | 3 +++ radio/ETHERNET/CMakeLists.txt | 3 +++ radio/ETHERNET/benetel/4g/CMakeLists.txt | 3 +++ radio/ETHERNET/benetel/5g/CMakeLists.txt | 3 +++ radio/IRIS/CMakeLists.txt | 3 +++ radio/LMSSDR/CMakeLists.txt | 3 +++ radio/USRP/CMakeLists.txt | 3 +++ 9 files changed, 24 insertions(+), 19 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 8c9dbccda8..3580edac1b 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -537,47 +537,28 @@ function main() { # Build RF device and transport protocol libraries # #################################################### if [ "$HW" != "None" ] ; then - rm -f liboai_device.so - if [ "$HW" == "OAI_USRP" ] ; then compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif - ln -sf liboai_usrpdevif.so liboai_device.so - echo "liboai_device.so symlinks to liboai_usrpdevif.so" elif [ "$HW" == "OAI_BLADERF" ] ; then compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif - ln -sf liboai_bladerfdevif.so liboai_device.so - echo "liboai_device.so symlinks liboai_bladerfdevif.so" elif [ "$HW" == "OAI_LMSSDR" ] ; then compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif - ln -sf liboai_lmssdrdevif.so liboai_device.so - echo "liboai_device.so symlinks to liboai_lmssdrdevif.so" elif [ "$HW" == "OAI_IRIS" ] ; then compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif - ln -s liboai_irisdevif.so liboai_device.so - echo "liboai_device.so symlinks to liboai_irisdevif.so" elif [ "$HW" == "OAI_AW2SORI" ] ; then compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro - ln -sf libaw2sori_transpro.so libthirdparty_transpro.so - echo "libthirdparty_transpro.so symlinks to libaw2sori_transpro.so" else echo_fatal "illegal HW option $HW" fi fi if [ "$TP" != "None" ]; then - rm -f liboai_transpro.so if [ "$TP" == "Ethernet" ]; then compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro - ln -sf liboai_eth_transpro.so liboai_transpro.so - echo_info "liboai_transpro.so symlinks to liboai_eth_transpro.so" elif [ "$TP" == "benetel4g" ]; then compilations $BUILD_DIR benetel_4g.txt benetel4g - ln -sf libbenetel_4g.so liboai_transpro.so - echo_info "liboai_transpro.so symlinks to libbenetel_4g.so" elif [ "$TP" == "benetel5g" ]; then compilations $BUILD_DIR benetel_5g.txt benetel_5g - ln -sf libbenetel_5g.so liboai_transpro.so - echo_info "liboai_transpro.so symlinks to libbenetel_5g.so" else echo_fatal "illegal TP option $TP" fi diff --git a/radio/AW2SORI/CMakeLists.txt b/radio/AW2SORI/CMakeLists.txt index d055b374ac..e02d8a2721 100644 --- a/radio/AW2SORI/CMakeLists.txt +++ b/radio/AW2SORI/CMakeLists.txt @@ -11,3 +11,6 @@ add_library(aw2sori_transpro MODULE oaiori.c) target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) target_link_libraries(aw2sori_transpro PRIVATE ori oai_eth_transpro) set_target_properties(aw2sori_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET aw2sori_transpro POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink libaw2sori_transpro.so libthirdparty_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/BLADERF/CMakeLists.txt b/radio/BLADERF/CMakeLists.txt index d7a7fc7162..551cc8ef1d 100644 --- a/radio/BLADERF/CMakeLists.txt +++ b/radio/BLADERF/CMakeLists.txt @@ -2,3 +2,6 @@ pkg_check_modules(bladeRF REQUIRED libbladeRF) add_library(oai_bladerfdevif MODULE bladerf_lib.c) target_link_libraries(oai_bladerfdevif PRIVATE bladeRF) set_target_properties(oai_bladerfdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_bladerfdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_bladerfdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/CMakeLists.txt b/radio/ETHERNET/CMakeLists.txt index aa2b14ef12..52aebdcc1a 100644 --- a/radio/ETHERNET/CMakeLists.txt +++ b/radio/ETHERNET/CMakeLists.txt @@ -5,5 +5,8 @@ add_library(oai_eth_transpro MODULE ) target_include_directories(oai_eth_transpro PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(oai_eth_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_eth_transpro POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_eth_transpro.so liboai_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_subdirectory(benetel) diff --git a/radio/ETHERNET/benetel/4g/CMakeLists.txt b/radio/ETHERNET/benetel/4g/CMakeLists.txt index b0f180719c..164e33eb28 100644 --- a/radio/ETHERNET/benetel/4g/CMakeLists.txt +++ b/radio/ETHERNET/benetel/4g/CMakeLists.txt @@ -15,3 +15,6 @@ target_include_directories(benetel_4g PRIVATE ${libdpdk_INCLUDE_DIRS}) target_link_libraries(benetel_4g PRIVATE ${libdpdk_LIBRARIES}) target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) set_target_properties(benetel_4g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET benetel_4g POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink libbenetel_4g.so liboai_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/5g/CMakeLists.txt b/radio/ETHERNET/benetel/5g/CMakeLists.txt index da957acb5b..cdad594ce3 100644 --- a/radio/ETHERNET/benetel/5g/CMakeLists.txt +++ b/radio/ETHERNET/benetel/5g/CMakeLists.txt @@ -14,3 +14,6 @@ target_link_libraries(benetel_5g PRIVATE ${libdpdk_LIBRARIES}) target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") set_target_properties(benetel_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET benetel_5g POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink libbenetel_5g.so liboai_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/IRIS/CMakeLists.txt b/radio/IRIS/CMakeLists.txt index cd12bf09bb..edc7c7568a 100644 --- a/radio/IRIS/CMakeLists.txt +++ b/radio/IRIS/CMakeLists.txt @@ -3,3 +3,6 @@ find_package(SoapySDR REQUIRED) add_library(oai_irisdevif MODULE iris_lib.cpp) target_link_libraries(oai_irisdevif PRIVATE SoapySDR) set_target_properties(oai_irisdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_irisdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_irisdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/LMSSDR/CMakeLists.txt b/radio/LMSSDR/CMakeLists.txt index d93b84f6f1..2df5c9a01f 100644 --- a/radio/LMSSDR/CMakeLists.txt +++ b/radio/LMSSDR/CMakeLists.txt @@ -3,3 +3,6 @@ find_package(LimeSuite REQUIRED) add_library(oai_lmssdrdevif MODULE lms_lib.cpp) target_link_libraries(oai_lmssdrdevif LimeSuite ) set_target_properties(oai_lmssdrdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_lmssdrdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_lmssdrdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/USRP/CMakeLists.txt b/radio/USRP/CMakeLists.txt index bcdf2b6a23..4aef8b1f8d 100644 --- a/radio/USRP/CMakeLists.txt +++ b/radio/USRP/CMakeLists.txt @@ -5,3 +5,6 @@ add_library(oai_usrpdevif MODULE usrp_lib.cpp) #target_include_directories(oai_usrpdevif PRIVATE Boost::boost) target_link_libraries(oai_usrpdevif uhd) set_target_properties(oai_usrpdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_usrpdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_usrpdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) From 5f58ccb56c02cc60e96ad8c3ee1920cb78e2eb83 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jun 2023 09:02:37 +0200 Subject: [PATCH 116/119] Remove unused build_oai variables --- cmake_targets/build_oai | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 3580edac1b..ecf281ad58 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -37,12 +37,8 @@ set_openair_env gen_nvram_path=$OPENAIR_DIR/cmake_targets/ran_build/build conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -XFORMS="True" -SKIP_SHARED_LIB_FLAG="False" -PRINT_STATS="False" HW="None" TP="None" -EPC=0 VERBOSE_CI=0 VERBOSE_COMPILE=0 RUN_GROUP=0 @@ -52,12 +48,8 @@ BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -BUILD_ECLIPSE=0 -NR="False" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" RU=0 -CMAKE_C_FLAGS=() -CMAKE_CXX_FLAGS=() function print_help() { echo_info " @@ -81,9 +73,6 @@ Options: This option will require root password --install-optional-packages Install useful but not mandatory packages such as valgrind --i | --install-system-files - Install OpenAirInterface required files in Linux system - This option will require root password -g | --run-with-gdb 0 ]]; then CMAKE_CMD="$CMAKE_CMD -DCMAKE_C_FLAGS=\"${CMAKE_C_FLAGS[*]}\""; fi - if [[ ${#CMAKE_CXX_FLAGS[@]} > 0 ]]; then CMAKE_CMD="$CMAKE_CMD -DCMAKE_CXX_FLAGS=\"${CMAKE_CXX_FLAGS[*]}\""; fi # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, # e.g., cmake_targets/ran_build/build, hence the ../../.. From 306b4974ad2b008a8edbc8e795b7ad1d849ef7f3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jun 2023 09:57:45 +0200 Subject: [PATCH 117/119] Simplify build_oai --- cmake_targets/build_oai | 179 +++++++++++++++------------------------- 1 file changed, 68 insertions(+), 111 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index ecf281ad58..5405af9b28 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -37,8 +37,7 @@ set_openair_env gen_nvram_path=$OPENAIR_DIR/cmake_targets/ran_build/build conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -HW="None" -TP="None" +HW="" VERBOSE_CI=0 VERBOSE_COMPILE=0 RUN_GROUP=0 @@ -49,7 +48,7 @@ DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" -RU=0 +TARGET_LIST="" function print_help() { echo_info " @@ -226,22 +225,27 @@ function main() { shift;; --eNB) eNB=1 + TARGET_LIST="$TARGET_LIST lte-softmodem" echo_info "Will compile eNB" shift;; --gNB) gNB=1 + TARGET_LIST="$TARGET_LIST nr-softmodem nr-cuup" echo_info "Will compile gNB" shift;; --RU) RU=1 + TARGET_LIST="$TARGET_LIST oairu" echo_info "Will compile RRU" shift;; --UE) UE=1 + TARGET_LIST="$TARGET_LIST lte-uesoftmodem" echo_info "Will compile UE" shift;; --nrUE) nrUE=1 + TARGET_LIST="$TARGET_LIST nr-uesoftmodem" echo_info "Will compile NR UE" shift;; --mu) @@ -255,38 +259,48 @@ function main() { gen_nvram_path=$(readlink -f "$2") shift 2;; --UE-ip) - UE_ip=1 - echo_info "Will compile UE" + TARGET_LIST="$TARGET_LIST ue_ip" shift;; -w | --hardware) - # Use OAI_USRP as the key word USRP is used inside UHD driver case "$2" in - "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU" | "AW2SORI") + "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU") HW="OAI_"$2 + TARGET_LIST="$TARGET_LIST oai_${2,,}devif" # ,, makes lowercase + CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON" + ;; + "AW2SORI") + HW="OAI_"$2 + TARGET_LIST="$TARGET_LIST aw2sori_transpro" CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON" ;; "None") - HW="None" ;; *) - echo_fatal "Unknown HW type $2: exit..." + echo_fatal "Unknown hardware type $2: exit..." + ;; esac shift 2;; -t | --transport) case "$2" in - "Ethernet" | "benetel4g" | "benetel5g") - TP=$2 + "Ethernet") + TARGET_LIST="$TARGET_LIST oai_eth_transpro" + CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase + ;; + "benetel4g" | "benetel5g") + TARGET_LIST="$TARGET_LIST $2" CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase ;; "None") - HW="None" ;; *) - echo_fatal "Unknown TP type $2; exit..." + echo_fatal "Unknown transport type $2; exit..." + ;; esac shift 2;; -P | --phy_simulators) SIMUS_PHY=1 + # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim + TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim" echo_info "Will compile dlsim, ulsim, ..." shift;; -s | --check) @@ -347,26 +361,19 @@ function main() { echo_info "Enabling build eclipse project support" shift 1;; --build-lib) - BUILD_OPTLIB="" if [ "$2" == "all" ] ; then - BUILD_OPTLIB="$OPTIONAL_LIBRARIES" + TARGET_LIST="$TARGET_LIST $OPTIONAL_LIBRARIES" + for lib in $OPTIONAL_LIBRARIES; do CMAKE_CMD="$CMAKE_CMD -DENABLE_${lib^^}=ON"; done echo_info "Enabling build of all optional shared libraries ($OPTIONAL_LIBRARIES)" else - for alib in $2 ; do - for oklib in $OPTIONAL_LIBRARIES ; do - if [ "$alib" = "$oklib" ] ; then - BUILD_OPTLIB="$BUILD_OPTLIB $alib" - echo_info "Enabling build of lib${alib}.so" - fi - done + for reqlib in $2; do + lib=$(echo $OPTIONAL_LIBRARIES | tr ' ' '\n' | grep -w $reqlib) # search given parameter in list + [[ $? -ne 0 ]] && echo_fatal "Unknown optional library in $reqlib, valid libraries are $OPTIONAL_LIBRARIES" + TARGET_LIST="$TARGET_LIST $lib" # will append the found library + CMAKE_CMD="$CMAKE_CMD -DENABLE_${lib^^}=ON" + echo_info "Enabling build of optional shared library $lib" done - if [ "${BUILD_OPTLIB## }" != "$2" ] ; then - echo_fatal "Unknown optional library in $2, valid libraries are $OPTIONAL_LIBRARIES" - fi fi - for oklib in $BUILD_OPTLIB ; do - CMAKE_CMD="$CMAKE_CMD -DENABLE_${oklib^^}=ON" - done shift 2;; --noavx512) CMAKE_CMD="$CMAKE_CMD -DAVX512=OFF" @@ -444,96 +451,46 @@ function main() { check_install_additional_tools fi - execlist="" - [[ "$eNB" == "1" ]] && execlist="$execlist lte-softmodem" - [[ "$gNB" == "1" ]] && execlist="$execlist nr-softmodem nr-cuup" - [[ "$RU" == "1" ]] && execlist="$execlist oairu" - [[ "$UE" == 1 ]] && execlist="$execlist lte-uesoftmodem" - [[ "$nrUE" == 1 ]] && execlist="$execlist nr-uesoftmodem" - # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim - [[ "$SIMUS_PHY" == "1" ]] && execlist="$execlist dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim" - [[ "$BUILD_OPTLIB" != "" ]] && execlist="$execlist $BUILD_OPTLIB" - [[ "$execlist" != "" ]] && execlist="$execlist params_libconfig coding rfsimulator" - DIR=$OPENAIR_DIR/cmake_targets [ "$CLEAN" = "1" ] && rm -rf $DIR/$BUILD_DIR/build - mkdir -p $DIR/$BUILD_DIR/build - cd $DIR/$BUILD_DIR/build - - # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, - # e.g., cmake_targets/ran_build/build, hence the ../../.. - CMAKE_CMD="$CMAKE_CMD ../../.." - echo_info "Running \"$CMAKE_CMD\"" - eval $CMAKE_CMD - - if [[ "$execlist" != "" ]]; then - compilations $BUILD_DIR all.txt $execlist - fi - - if [ "$UE" = 1 ] ; then - - echo_info "Compiling UE specific part" - - if [ "$UE_ip" = 1 ] - then - echo_info "Building ue_ip module" - compilations $BUILD_DIR ue_ip.txt ue_ip - else - echo_info "Bypassing ue_ip build" - fi #IS_CONTAINER - -# mkdir -p $DIR/at_commands/build -# cd $DIR/at_commands/build -# eval $CMAKE_CMD -# compilations at_commands at_nas_ue - - [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build - mkdir -p $DIR/nas_sim_tools/build - cd $DIR/nas_sim_tools/build - - eval $CMAKE_CMD .. - compilations nas_sim_tools usim.txt usim - compilations nas_sim_tools nvram.txt nvram - compilations nas_sim_tools conf2uedata.txt conf2uedata - - # generate USIM data - if [ -f conf2uedata ]; then - install_nas_tools $conf_nvram_path $DIR/$BUILD_DIR/build "$DIR/$BUILD_DIR/build/conf2uedata.txt" - else - echo_warning "not generated UE NAS files: binaries not found" + if [[ $TARGET_LIST != "" ]]; then + # add some default libraries that should always be built + # for eNB, gNB, UEs, simulators + if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then + TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts" fi - fi - #################################################### - # Build RF device and transport protocol libraries # - #################################################### - if [ "$HW" != "None" ] ; then - if [ "$HW" == "OAI_USRP" ] ; then - compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif - elif [ "$HW" == "OAI_BLADERF" ] ; then - compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif - elif [ "$HW" == "OAI_LMSSDR" ] ; then - compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif - elif [ "$HW" == "OAI_IRIS" ] ; then - compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif - elif [ "$HW" == "OAI_AW2SORI" ] ; then - compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro - else - echo_fatal "illegal HW option $HW" - fi - fi + mkdir -p $DIR/$BUILD_DIR/build + cd $DIR/$BUILD_DIR/build - if [ "$TP" != "None" ]; then - if [ "$TP" == "Ethernet" ]; then - compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro - elif [ "$TP" == "benetel4g" ]; then - compilations $BUILD_DIR benetel_4g.txt benetel4g - elif [ "$TP" == "benetel5g" ]; then - compilations $BUILD_DIR benetel_5g.txt benetel_5g - else - echo_fatal "illegal TP option $TP" + # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, + # e.g., cmake_targets/ran_build/build, hence the ../../.. + CMAKE_CMD="$CMAKE_CMD ../../.." + echo_info "Running \"$CMAKE_CMD\"" + eval $CMAKE_CMD + compilations $BUILD_DIR all.txt $TARGET_LIST + + if [ "$UE" = 1 ] ; then + + echo_info "Compiling UE specific part" + + [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build + mkdir -p $DIR/nas_sim_tools/build + cd $DIR/nas_sim_tools/build + + eval $CMAKE_CMD .. + compilations nas_sim_tools usim.txt usim + compilations nas_sim_tools nvram.txt nvram + compilations nas_sim_tools conf2uedata.txt conf2uedata + + # generate USIM data + if [ -f conf2uedata ]; then + install_nas_tools $conf_nvram_path $DIR/$BUILD_DIR/build "$DIR/$BUILD_DIR/build/conf2uedata.txt" + else + echo_warning "not generated UE NAS files: binaries not found" + fi fi fi From 079866bf4f0562de31818930f45bd40c40992628 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Jul 2023 11:21:38 +0200 Subject: [PATCH 118/119] Check for libforms for building scopes --- openair1/PHY/TOOLS/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openair1/PHY/TOOLS/CMakeLists.txt b/openair1/PHY/TOOLS/CMakeLists.txt index 0def967792..8acd528617 100644 --- a/openair1/PHY/TOOLS/CMakeLists.txt +++ b/openair1/PHY/TOOLS/CMakeLists.txt @@ -29,6 +29,13 @@ #* \warning #*/ +find_library(forms NAMES forms) +if(NOT forms) + message(FATAL_ERROR "required library forms not found for building scopes") +else() + message(STATUS "libforms library, required for scopes, found at ${forms}") +endif() + include_directories ("/usr/include/X11") add_library(xforms_common OBJECT lte_phy_scope.c From 9dd27e60f92bf31ad88ad80f04e53ef5c36ea1ec Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 10 Jul 2023 08:57:18 +0200 Subject: [PATCH 119/119] Fix after merging ssh asterix into integration; conflict from ls --- ci-scripts/xml_files/container_sa_n310_nrue.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index 309b2860f7..ce7dd26b6d 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -111,7 +111,7 @@ Ping Ping: 20pings in 20sec oai_ue_caracal - -c 20 + -c 20 %cn_ip% 1 25 @@ -120,7 +120,7 @@ Ping Ping: 100pings in 20sec oai_ue_caracal - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 30