diff --git a/CMakeLists.txt b/CMakeLists.txt index ec60df8b35..0b48680830 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1040,6 +1040,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c + ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_freq_equalization.c ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c @@ -1144,6 +1145,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) add_library(PHY_NR ${PHY_NR_SRC}) add_library(PHY_NR_UE ${PHY_NR_UE_SRC}) +target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs) add_library(PHY_RU ${PHY_SRC_RU}) target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs) diff --git a/ci-scripts/cls_physim1.py b/ci-scripts/cls_physim1.py index b0c9012d7d..70f8729764 100644 --- a/ci-scripts/cls_physim1.py +++ b/ci-scripts/cls_physim1.py @@ -161,7 +161,7 @@ class PhySim: isRunning = False count = 0 # Check whether the containers are in Running state or not under 2 mins - while(count < 2 and isRunning == False): + while(count < 5 and isRunning == False): time.sleep(60) mySSH.command('oc get pods -o wide -l app=physim | tee -a cmake_targets/log/physim_pods_summary.txt', '\$', 30, resync=True) running_count = mySSH.getBefore().count('Running') diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index c65c4614d2..dca2b28901 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -15,7 +15,7 @@ Ref : DLSCH encoding : 137.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 210.0 - PUSCH decoding : 210.0 + PUSCH decoding : 2200.0 Schedule Response : 48.0 DL & UL scheduling timing : 13.0 UL Indication : 60.0 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index 50444cc6b0..7d2ea1ef03 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -15,7 +15,7 @@ Ref : DLSCH encoding : 177.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 210.0 - PUSCH decoding : 210.0 + PUSCH decoding : 2200.0 Schedule Response : 111.0 DL & UL scheduling timing : 20.0 UL Indication : 127.0 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 6304404742..bbc5b2d016 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -15,7 +15,7 @@ Ref : DLSCH encoding : 118.0 L1 Rx processing : 305.0 PUSCH inner-receiver : 150.0 - PUSCH decoding : 210.0 + PUSCH decoding : 2200.0 Schedule Response : 30.0 DL & UL scheduling timing : 10.0 UL Indication : 40.0 diff --git a/ci-scripts/xml_files/container_4g_l2sim_proxy.xml b/ci-scripts/xml_files/container_4g_l2sim_proxy.xml index 4c8f9ae019..795bce6bef 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_proxy.xml @@ -36,7 +36,7 @@ 1 1 True - f390610304baf6b66e4ec8cc00bf91398a651172 + b64d9bce986b38ca59e8582864ade3fcdd05c0dc diff --git a/ci-scripts/xml_files/container_l2sim_proxy.xml b/ci-scripts/xml_files/container_l2sim_proxy.xml index 8a8dbd05c2..81ee7c1bfa 100644 --- a/ci-scripts/xml_files/container_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_l2sim_proxy.xml @@ -36,7 +36,7 @@ 1 1 True - f390610304baf6b66e4ec8cc00bf91398a651172 + b64d9bce986b38ca59e8582864ade3fcdd05c0dc diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index bacd781c43..cbd9f7265b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -319,8 +319,7 @@ check_install_usrp_uhd_driver(){ $SUDO apt-get remove libuhd3.15.0 -y || true local distribution=$(get_distribution_release) if [[ "$distribution" == "ubuntu18.04" || "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" ]]; then - $SUDO apt-get remove libuhd4.0.0 -y || true - $SUDO apt-get remove libuhd4.1.0 -y || true + $SUDO apt-get remove libuhd4.?.? -y || true fi v=$(lsb_release -cs) $SUDO apt-add-repository --remove "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" @@ -350,7 +349,7 @@ check_install_usrp_uhd_driver(){ $SUDO apt-get -y install python-tk $boost_libs_ubuntu libusb-1.0-0-dev case "$(get_distribution_release)" in "ubuntu18.04" | "ubuntu20.04" | "ubuntu22.04") - $SUDO apt-get -y install libuhd-dev libuhd4.4.0 uhd-host + $SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host ;; esac elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then diff --git a/common/utils/ds/byte_array.c b/common/utils/ds/byte_array.c index dfc8872662..c3281ffa27 100644 --- a/common/utils/ds/byte_array.c +++ b/common/utils/ds/byte_array.c @@ -22,6 +22,7 @@ #include "byte_array.h" #include "common/utils/assertions.h" +#include #include byte_array_t copy_byte_array(byte_array_t src) @@ -56,3 +57,19 @@ bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1) return true; } + +byte_array_t cp_str_to_ba(const char* str) +{ + assert(str != NULL); + + const size_t sz = strlen(str); + + byte_array_t dst = {.len = sz}; + + dst.buf = calloc(sz,sizeof(uint8_t)); + assert(dst.buf != NULL && "Memory exhausted"); + + memcpy(dst.buf, str, sz); + + return dst; +} diff --git a/common/utils/ds/byte_array.h b/common/utils/ds/byte_array.h index f16fd7c01d..236f3e683f 100644 --- a/common/utils/ds/byte_array.h +++ b/common/utils/ds/byte_array.h @@ -19,8 +19,10 @@ * contact@openairinterface.org */ -#ifndef BYTE_ARRAY_H_OAI -#define BYTE_ARRAY_H_OAI +#ifndef BYTE_ARRAY_H +#define BYTE_ARRAY_H + +/* WARNING: This file is also defined at XXXXX. Both files need to be completely equal. Same applies for *.c */ #include #include @@ -39,4 +41,6 @@ byte_array_t copy_byte_array(byte_array_t src); void free_byte_array(byte_array_t ba); bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1); +byte_array_t cp_str_to_ba(const char* str); + #endif diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 64f7a4772c..da4d4ccaa1 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -37,6 +37,46 @@ const char *duplex_mode[]={"FDD","TDD"}; +static const uint8_t bit_reverse_table_256[] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, + 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, + 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, + 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, + 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, + 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, + 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; + +// Reverse bits implementation based on http://graphics.stanford.edu/~seander/bithacks.html +uint64_t reverse_bits(uint64_t in, int n_bits) +{ + // Reverse n_bits in uint64_t variable, example: + // n_bits: 10 + // in: 10 0000 1111 + // return: 11 1100 0001 + + AssertFatal(n_bits <= 64, "Maximum bits to reverse is 64, impossible to reverse %d bits!\n", n_bits); + uint64_t rev_bits = 0; + uint8_t *p = (uint8_t *)∈ + uint8_t *q = (uint8_t *)&rev_bits; + int n_bytes = n_bits >> 3; + for (int n = 0; n < n_bytes; n++) { + q[n_bytes - 1 - n] = bit_reverse_table_256[p[n]]; + } + + // Reverse remaining bits (not aligned with 8-bit) + rev_bits = rev_bits << (n_bits % 8); + for (int i = n_bytes * 8; i < n_bits; i++) { + rev_bits |= ((in >> i) & 0x1) << (n_bits - i - 1); + } + return rev_bits; +} + static const int tables_5_3_2[5][12] = { {25, 52, 79, 106, 133, 160, 216, 270, -1, -1, -1, -1}, // 15 FR1 {11, 24, 38, 51, 65, 78, 106, 133, 162, 217, 245, 273}, // 30 FR1 diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index d9ac675493..ea879e93b4 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -90,6 +90,8 @@ static inline int get_num_dmrs(uint16_t dmrs_mask ) { return(num_dmrs); } +uint64_t reverse_bits(uint64_t in, int n_bits); + int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols); int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index b0d05c6aca..941e4de6ef 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -49,6 +49,7 @@ extern "C" { int nb_fd_epoll=0; int epoll_fd=-1; int sem_fd=-1; + size_t last_log_size = 0; } task_list_t; int timer_expired(int fd); @@ -131,11 +132,23 @@ extern "C" { int message_id = message->ittiMsgHeader.messageId; size_t s=t->message_queue.size(); - if ( s > t->admin.queue_size ) - LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s ); - - if ( s > 50 ) - LOG_I(ITTI,"Queue for %s task size: %ld (last message %s)\n",itti_get_task_name(destination_task_id), s+1,ITTI_MSG_NAME(message)); + // to reduce the number of logs, we give a message each increase of 25% + if ((s > t->last_log_size * 1.25) && (s > t->admin.queue_size / 10)) { + if (s > t->admin.queue_size) { + LOG_E(TMR, "Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s); + } else { + LOG_I(ITTI, + "Queue for %s task size: %ld (last message %s)\n", + itti_get_task_name(destination_task_id), + s + 1, + ITTI_MSG_NAME(message)); + } + t->last_log_size = s; + } else if (t->last_log_size && s < t->admin.queue_size / 10) { + // Inform when the queue decreases + LOG_I(ITTI, "Queue for %s task size is back under 10%% of max size\n", itti_get_task_name(destination_task_id)); + t->last_log_size = 0; + } t->message_queue.insert(t->message_queue.begin(), message); eventfd_t sem_counter = 1; diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index d310e1162c..d7b9b3cf9d 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -59,8 +59,13 @@ add_library(telnetsrv_ci MODULE telnetsrv_ci.c) target_link_libraries(telnetsrv_ci PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_dependencies(telnetsrv telnetsrv_ci) +message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so") +add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c) +target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +add_dependencies(telnetsrv telnetsrv_bearer) + # all libraries should be written to root build dir -set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci +set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../.. ) diff --git a/common/utils/telnetsrv/telnetsrv_bearer.c b/common/utils/telnetsrv/telnetsrv_bearer.c new file mode 100644 index 0000000000..f019d3d48b --- /dev/null +++ b/common/utils/telnetsrv/telnetsrv_bearer.c @@ -0,0 +1,121 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include "openair2/RRC/NR/rrc_gNB_UE_context.h" + +#define TELNETSERVERCODE +#include "telnetsrv.h" + +#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0) + +static int get_single_ue_rnti(void) +{ + rrc_gNB_ue_context_t *ue_context_p = NULL; + RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) { + return ue_context_p->ue_context.rnti; + } + return -1; +} + +int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (buf) + ERROR_MSG_RET("no parameter allowed\n"); + + int rnti = get_single_ue_rnti(); + if (rnti < 1) + ERROR_MSG_RET("different number of UEs\n"); + + prnt("single UE RNTI %04x\n", rnti); + return 0; +} + +void rrc_gNB_trigger_new_bearer(int rnti); +int add_bearer(char *buf, int debug, telnet_printfunc_t prnt) +{ + int rnti = -1; + if (!buf) { + rnti = get_single_ue_rnti(); + if (rnti < 1) + ERROR_MSG_RET("no UE found\n"); + } else { + rnti = strtol(buf, NULL, 16); + if (rnti < 1 || rnti >= 0xfffe) + ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n"); + } + + // verify it exists in RRC as well + rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti); + if (!rrcue) + ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti); + + rrc_gNB_trigger_new_bearer(rnti); + prnt("called rrc_gNB_trigger_new_bearer(%04x)\n", rnti); + return 0; +} + +void rrc_gNB_trigger_release_bearer(int rnti); +int release_bearer(char *buf, int debug, telnet_printfunc_t prnt) +{ + int rnti = -1; + if (!buf) { + rnti = get_single_ue_rnti(); + if (rnti < 1) + ERROR_MSG_RET("no UE found\n"); + } else { + rnti = strtol(buf, NULL, 16); + if (rnti < 1 || rnti >= 0xfffe) + ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n"); + } + + // verify it exists in RRC as well + rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti); + if (!rrcue) + ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti); + + rrc_gNB_trigger_release_bearer(rnti); + prnt("called rrc_gNB_trigger_release_bearer(%04x)\n", rnti); + return 0; +} + +static telnetshell_cmddef_t bearercmds[] = { + {"get_single_rnti", "", get_single_rnti}, + {"add_bearer", "[rnti(hex,opt)]", add_bearer}, + {"release_bearer", "[rnti(hex,opt)]", release_bearer}, + {"", "", NULL}, +}; + +static telnetshell_vardef_t bearervars[] = { + + {"", 0, 0, NULL} +}; + +void add_bearer_cmds(void) { + add_telnetcmd("bearer", bearervars, bearercmds); +} diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 33fe6b3f2a..e4a9e4e5e6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -475,10 +475,12 @@ void init_gNB_Tpool(int inst) { PHY_VARS_gNB *gNB; gNB = RC.gNB[inst]; gNB_L1_proc_t *proc = &gNB->proc; - + // PUSCH symbols per thread need to be calculated by how many threads we have + gNB->num_pusch_symbols_per_thread = 1; // ULSCH decoding threadpool initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE)); // ULSCH decoder result FIFO + initNotifiedFIFO(&gNB->respPuschSymb); initNotifiedFIFO(&gNB->respDecode); // L1 RX result FIFO diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 8bffda8f61..31bde16b97 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -709,7 +709,7 @@ int main( int argc, char **argv ) { 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; + // const ngran_node_t node_type = rrc->node_type; int nb_id = 0; int cu_du_id = 0; if (node_type == ngran_gNB) { diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 97f73ef880..67f6c346c7 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1070,6 +1070,7 @@ int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { rx_ind->pdu_list[j].rnti = ind->pdu_list[j].rnti; rx_ind->pdu_list[j].timing_advance = ind->pdu_list[j].timing_advance; rx_ind->pdu_list[j].ul_cqi = ind->pdu_list[j].ul_cqi; + rx_ind->pdu_list[j].rssi = ind->pdu_list[j].rssi; } if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { diff --git a/nfapi/open-nFAPI/nfapi/inc/nfapi.h b/nfapi/open-nFAPI/nfapi/inc/nfapi.h index e1a0ec4f4e..dc2d3d3ec0 100644 --- a/nfapi/open-nFAPI/nfapi/inc/nfapi.h +++ b/nfapi/open-nFAPI/nfapi/inc/nfapi.h @@ -77,6 +77,9 @@ uint8_t unpackarray(uint8_t **ppReadPackedMsg, uint8_t *end, unpack_array_elem_fn fn); +uint32_t pack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **out, uint8_t *end); +uint32_t unpack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **in, uint8_t *end); + uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end); uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index a9338cf3ca..21c9558653 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -932,6 +932,8 @@ typedef struct typedef struct { + uint16_t bwp_size; // Needed for SCF222 10.02 + uint16_t bwp_start; // Needed for SCF222 10.02 uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4 uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274 diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index ef80c86849..62d79bb511 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -544,6 +545,43 @@ uint8_t unpackarray(uint8_t **ppReadPackedMsg, void *array, uint16_t array_eleme return 1; } +uint32_t pack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **out, uint8_t *end) +{ + // Helper vars for DCI Payload + uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN]; + uint8_t dci_byte_len = (payloadSizeBits + 7) / 8; + // Align the dci payload bits to the left on the payload buffer + uint64_t *dci_pdu = (uint64_t *)payload; + if (payloadSizeBits % 8 != 0) { + uint8_t rotation_bits = 8 - (payloadSizeBits % 8); + *dci_pdu = (*dci_pdu << rotation_bits); + } + // Invert the byte order of the DCI Payload + for (int j = 0; j < dci_byte_len; j++) { + dci_bytes_inverted[j] = payload[(dci_byte_len - 1) - j]; + } + return pusharray8(dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, out, end); +} + +uint32_t unpack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **in, uint8_t *end) +{ + // Pull the inverted DCI and invert it back + // Helper vars for DCI Payload + uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN]; + uint8_t dci_byte_len = (payloadSizeBits + 7) / 8; + // Get DCI array inverted + uint32_t pullresult = pullarray8(in, dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, end); + uint64_t *dci_pdu = (uint64_t *)payload; + // Reversing the byte order of the inverted DCI payload + for (uint16_t j = 0; j < dci_byte_len; j++) { + payload[j] = dci_bytes_inverted[(dci_byte_len - 1) - j]; + } + if (payloadSizeBits % 8 != 0) { + uint8_t rotation_bits = 8 - (payloadSizeBits % 8); + *dci_pdu = (*dci_pdu >> rotation_bits); + } + return pullresult; +} uint32_t pack_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { if(ve != 0 && config != 0) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index f5a05d0d71..8f7a7c2804 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -196,124 +196,176 @@ static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t *value, uint8_t **ppW return 1; } - -static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; - return( - push8(value->subcarrier_spacing, ppWritePackedMsg, end) && - push8(value->cyclic_prefix, ppWritePackedMsg, end) && - push16(value->start_rb, ppWritePackedMsg, end) && - push16(value->nr_of_rbs, ppWritePackedMsg, end) && - push8(value->csi_type, ppWritePackedMsg, end) && - push8(value->row, ppWritePackedMsg, end) && - push16(value->freq_domain, ppWritePackedMsg, end) && - push8(value->symb_l0, ppWritePackedMsg, end) && - push8(value->symb_l1, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - push8(value->freq_density, ppWritePackedMsg, end) && - push16(value->scramb_id, ppWritePackedMsg, end) && - push8(value->power_control_offset, ppWritePackedMsg, end) && - push8(value->power_control_offset_ss, ppWritePackedMsg, end) - ); + return (push16(value->bwp_size, ppWritePackedMsg, end) && push16(value->bwp_start, ppWritePackedMsg, end) + && push8(value->subcarrier_spacing, ppWritePackedMsg, end) && push8(value->cyclic_prefix, ppWritePackedMsg, end) + && push16(value->start_rb, ppWritePackedMsg, end) && push16(value->nr_of_rbs, ppWritePackedMsg, end) + && push8(value->csi_type, ppWritePackedMsg, end) && push8(value->row, ppWritePackedMsg, end) + && push16(value->freq_domain, ppWritePackedMsg, end) && push8(value->symb_l0, ppWritePackedMsg, end) + && push8(value->symb_l1, ppWritePackedMsg, end) && push8(value->cdm_type, ppWritePackedMsg, end) + && push8(value->freq_density, ppWritePackedMsg, end) && push16(value->scramb_id, ppWritePackedMsg, end) + && push8(value->power_control_offset, ppWritePackedMsg, end) + && push8(value->power_control_offset_ss, ppWritePackedMsg, end) && + // TODO Add Precoding and Beamforming, hardcoded for now + push16(0, ppWritePackedMsg, end) && push16(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end)); } +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; -static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + if (!(push16(value->BWPSize, ppWritePackedMsg, end) && push16(value->BWPStart, ppWritePackedMsg, end) + && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && push8(value->CyclicPrefix, ppWritePackedMsg, end) + && push8(value->StartSymbolIndex, ppWritePackedMsg, end) && push8(value->DurationSymbols, ppWritePackedMsg, end) + && pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) + && push8(value->CceRegMappingType, ppWritePackedMsg, end) && push8(value->RegBundleSize, ppWritePackedMsg, end) + && push8(value->InterleaverSize, ppWritePackedMsg, end) && push8(value->CoreSetType, ppWritePackedMsg, end) + && push16(value->ShiftIndex, ppWritePackedMsg, end) && push8(value->precoderGranularity, ppWritePackedMsg, end) + && push16(value->numDlDci, ppWritePackedMsg, end))) { + return 0; + } - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - return 0; - } - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->CceRegMappingType, ppWritePackedMsg, end) && - push8(value->RegBundleSize, ppWritePackedMsg, end) && - push8(value->InterleaverSize, ppWritePackedMsg, end) && - push8(value->CoreSetType, ppWritePackedMsg, end) && - push16(value->ShiftIndex, ppWritePackedMsg, end) && - push8(value->precoderGranularity, ppWritePackedMsg, end) && - push16(value->numDlDci, ppWritePackedMsg, end)); + for (uint16_t i = 0; i < value->numDlDci; ++i) { + if (!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) + && push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and beamforming + // TODO get these values from elsewhere and delete the hardcoded ones + value->dci_pdu[i].precodingAndBeamforming.num_prgs = 0; + value->dci_pdu[i].precodingAndBeamforming.prg_size = 0; // 1 PRG of max size for analogue beamforming + value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces = 0; + value->dci_pdu[i].precodingAndBeamforming.prgs_list[0].pm_idx = 0; + value->dci_pdu[i].precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; + if (!(push16(value->dci_pdu[i].precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->dci_pdu[i].precodingAndBeamforming.prg_size, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < value->dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!push16(value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int digInt = 0; digInt < value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; digInt++) { + if (!push16(value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, + ppWritePackedMsg, + end)) { + return 0; + } + } + } + // TX Power info + if (!(push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + // DCI Payload fields + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + // Pack DCI Payload + pack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) { + return 0; + } + } + return 1; } - -static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->pduBitmap, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->pduIndex, ppWritePackedMsg, end) && - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->NrOfCodewords, ppWritePackedMsg, end) && - pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && - pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && - push16(value->dataScramblingId, ppWritePackedMsg, end) && - push8(value->nrOfLayers, ppWritePackedMsg, end) && - push8(value->transmissionScheme, ppWritePackedMsg, end) && - push8(value->refPoint, ppWritePackedMsg, end) && - push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && - push8(value->dmrsConfigType, ppWritePackedMsg, end) && - push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && - push8(value->SCID, ppWritePackedMsg, end) && - push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && - push16(value->dmrsPorts, ppWritePackedMsg, end) && - push8(value->resourceAlloc, ppWritePackedMsg, end) && - push16(value->rbStart, ppWritePackedMsg, end) && - push16(value->rbSize, ppWritePackedMsg, end) && - push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->NrOfSymbols, ppWritePackedMsg, end) && - push8(value->PTRSPortIndex, ppWritePackedMsg, end) && - push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && - push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && - push8(value->PTRSReOffset, ppWritePackedMsg, end) - ); + + if (!(push16(value->pduBitmap, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push16(value->pduIndex, ppWritePackedMsg, end) && push16(value->BWPSize, ppWritePackedMsg, end) + && push16(value->BWPStart, ppWritePackedMsg, end) && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) + && push8(value->CyclicPrefix, ppWritePackedMsg, end) && push8(value->NrOfCodewords, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->NrOfCodewords; ++i) { + if (!(push16(value->targetCodeRate[i], ppWritePackedMsg, end) && push8(value->qamModOrder[i], ppWritePackedMsg, end) + && push8(value->mcsIndex[i], ppWritePackedMsg, end) && push8(value->mcsTable[i], ppWritePackedMsg, end) + && push8(value->rvIndex[i], ppWritePackedMsg, end) && push32(value->TBSize[i], ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push16(value->dataScramblingId, ppWritePackedMsg, end) && push8(value->nrOfLayers, ppWritePackedMsg, end) + && push8(value->transmissionScheme, ppWritePackedMsg, end) && push8(value->refPoint, ppWritePackedMsg, end) + && push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && push8(value->dmrsConfigType, ppWritePackedMsg, end) + && push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && push8(value->SCID, ppWritePackedMsg, end) + && push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && push16(value->dmrsPorts, ppWritePackedMsg, end) + && push8(value->resourceAlloc, ppWritePackedMsg, end) && (int)pusharray8(value->rbBitmap, 36, 36, ppWritePackedMsg, end) + && push16(value->rbStart, ppWritePackedMsg, end) && push16(value->rbSize, ppWritePackedMsg, end) + && push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && push8(value->StartSymbolIndex, ppWritePackedMsg, end) + && push8(value->NrOfSymbols, ppWritePackedMsg, end))) { + return 0; + } + + // Check pduBitMap bit 1 to add or not PTRS parameters + if (value->pduBitmap & 0b1) { + if (!(push8(value->PTRSPortIndex, ppWritePackedMsg, end) && push8(value->PTRSTimeDensity, ppWritePackedMsg, end) + && push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && push8(value->PTRSReOffset, ppWritePackedMsg, end) + && push8(value->nEpreRatioOfPDSCHToPTRS, ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push16(value->precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->precodingAndBeamforming.prg_size, ppWritePackedMsg, end) + && push8(value->precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->precodingAndBeamforming.num_prgs; ++i) { + if (!push16(value->precodingAndBeamforming.prgs_list[i].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int k = 0; k < value->precodingAndBeamforming.dig_bf_interfaces; ++k) { + if (!push16(value->precodingAndBeamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + // TODO Add TX power info + // Hardcoded values that represent 0db + if (!(push8(8, ppWritePackedMsg, end) && // powerControlOffset + push8(1, ppWritePackedMsg, end))) { // powerControlOffsetSS + return 0; + } + // TODO Add CBG Fields + return 1; } +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing ssb. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; -static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing ssb. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - push16(value->PhysCellId, ppWritePackedMsg, end) && - push8(value->BetaPss, ppWritePackedMsg, end) && - push8(value->SsbBlockIndex, ppWritePackedMsg, end) && - push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && - push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && - push8(value->bchPayloadFlag, ppWritePackedMsg, end) && - push32(value->bchPayload, ppWritePackedMsg, end) && - push8(value->ssbRsrp, ppWritePackedMsg, end) - // TODO: pack precoding_and_beamforming too - ); - + if (!(push16(value->PhysCellId, ppWritePackedMsg, end) && push8(value->BetaPss, ppWritePackedMsg, end) + && push8(value->SsbBlockIndex, ppWritePackedMsg, end) && push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) + && push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && push8(value->bchPayloadFlag, ppWritePackedMsg, end) + && push8((value->bchPayload >> 16) & 0xff, ppWritePackedMsg, end) + && push8((value->bchPayload >> 8) & 0xff, ppWritePackedMsg, end) && push8(value->bchPayload & 0xff, ppWritePackedMsg, end) + && push8(0, ppWritePackedMsg, end) && + // TODO add Tx Power Info + push8(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end) + && push16(value->precoding_and_beamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->precoding_and_beamforming.prg_size, ppWritePackedMsg, end) + && push8(value->precoding_and_beamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->precoding_and_beamforming.num_prgs; ++i) { + if (!push16(value->precoding_and_beamforming.prgs_list[i].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int k = 0; k < value->precoding_and_beamforming.dig_bf_interfaces; ++k) { + if (!push16(value->precoding_and_beamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + return 1; } - static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_dl_config_dci_dl_pdu_rel13_t *value = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && @@ -594,47 +646,47 @@ static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppWrit push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); } - -static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)tlv; - - if(!(push32(value->PDUSize, ppWritePackedMsg, end) && - push16(value->PDUType, ppWritePackedMsg, end) )) + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->PDUType, ppWritePackedMsg, end)) + return 0; + uint8_t *pPackedLengthField = *ppWritePackedMsg; + if (!push16(value->PDUSize, ppWritePackedMsg, end)) return 0; // first match the pdu type, then call the respective function - switch(value->PDUType) { + switch (value->PDUType) { case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { - if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { - if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { - if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + if (!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15, ppWritePackedMsg, end))) return 0; - } - break; + } break; default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType); + } break; } - - return 1; + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->PDUSize = packedMsgLen; + return push16(value->PDUSize, &pPackedLengthField, end); } static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { @@ -777,42 +829,34 @@ static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePac return 1; } - -static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && - pusharray8(pNfapiMsg->dl_tti_request_body.nUe, 256, pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push8(pNfapiMsg->dl_tti_request_body.nPDUs, ppWritePackedMsg, end) + && push8(pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { + if (!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pusharrays32(arr, 12, pNfapiMsg->dl_tti_request_body.nUe[i], ppWritePackedMsg, end))) - return 0; - } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { + if (!push8(pNfapiMsg->dl_tti_request_body.nUe[i], ppWritePackedMsg, end)) + return 0; + for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { + if (!(push32(pNfapiMsg->dl_tti_request_body.PduIdx[i][j], ppWritePackedMsg, end))) { + return 0; + } + } + return 0; + } - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) - return 0; - } - -return 1; + return 1; } - - static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -882,148 +926,178 @@ static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppW //Pack fns for ul_tti PDUS - -static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - return( - push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && - push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && - push8(prach_pdu->prach_format, ppWritePackedMsg, end) && - push8(prach_pdu->num_ra, ppWritePackedMsg, end) && - push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && - push16(prach_pdu->num_cs, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); -} - -static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - return( - push16(pucch_pdu->rnti, ppWritePackedMsg, end) && - push32(pucch_pdu->handle, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(pucch_pdu->format_type, ppWritePackedMsg, end) && - push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && - push8(pucch_pdu->pi_2bpsk, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && - push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && - push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && - push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && - push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && - push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && - push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && - push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - if (!( - push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && - push16(pusch_pdu->rnti, ppWritePackedMsg, end) && - push32(pusch_pdu->handle, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && - push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && - push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && - push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && - push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->scid, ppWritePackedMsg, end) && - push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && - push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && - push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && - push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && - push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && - push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )) +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) + && push8(prach_pdu->prach_format, ppWritePackedMsg, end) && push8(prach_pdu->num_ra, ppWritePackedMsg, end) + && push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && push16(prach_pdu->num_cs, ppWritePackedMsg, end))) { return 0; - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map) { - case PUSCH_PDU_BITMAP_PUSCH_DATA: { - // pack optional TLVs - return( - push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && - push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && - pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: { - return( - push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: { - return( - push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: { - return( - push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && - push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) - ); - } - break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } } + // TODO: put these hardoded values elsewhere + // Beamforming + prach_pdu->beamforming.num_prgs = 0; + prach_pdu->beamforming.prg_size = 0; + prach_pdu->beamforming.dig_bf_interface = 0; + + if (prach_pdu->beamforming.prgs_list == NULL) { + prach_pdu->beamforming.prgs_list = calloc(prach_pdu->beamforming.num_prgs, sizeof(*prach_pdu->beamforming.prgs_list)); + } + if (prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list == NULL) { + prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list = + calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list)); + } + prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; + + // Pack RX Beamforming PDU + if (!(push16(prach_pdu->beamforming.num_prgs, ppWritePackedMsg, end) + && push16(prach_pdu->beamforming.prg_size, ppWritePackedMsg, end) + && push8(prach_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) + return 0; + + for (int prg = 0; prg < prach_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < prach_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!push16(prach_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) + return 0; + } + } + return 1; +} + +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(pucch_pdu->rnti, ppWritePackedMsg, end) && push32(pucch_pdu->handle, ppWritePackedMsg, end) + && push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) + && push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) + && push8(pucch_pdu->format_type, ppWritePackedMsg, end) && push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) + && push8(pucch_pdu->pi_2bpsk, ppWritePackedMsg, end) && push16(pucch_pdu->prb_start, ppWritePackedMsg, end) + && push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) + && push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) + && push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) + && push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) + && push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) + && push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) + && push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) + && push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) + && push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // Pack RX Beamforming PDU + && push16(pucch_pdu->beamforming.num_prgs, ppWritePackedMsg, end) + && push16(pucch_pdu->beamforming.prg_size, ppWritePackedMsg, end) + && push8(pucch_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) { + return 0; + } + + for (int prg = 0; prg < pucch_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < pucch_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!push16(pucch_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) + return 0; + } + } + return 1; +} + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && push16(pusch_pdu->rnti, ppWritePackedMsg, end) + && push32(pusch_pdu->handle, ppWritePackedMsg, end) && push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) + && push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) + && push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) + && push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) + && push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) + && push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) + && push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) + && push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_identity, ppWritePackedMsg, end) && push8(pusch_pdu->scid, ppWritePackedMsg, end) + && push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) + && push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) + && pusharray8(pusch_pdu->rb_bitmap, 36, 36, ppWritePackedMsg, end) && push16(pusch_pdu->rb_start, ppWritePackedMsg, end) + && push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) + && push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) + && push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) + && push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) + && push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) { + return 0; + } + // Pack Optional Data only included if indicated in pduBitmap + switch (pusch_pdu->pdu_bit_map) { + case PUSCH_PDU_BITMAP_PUSCH_DATA: { + // pack optional TLVs + if (!(push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_data.new_data_indicator, ppWritePackedMsg, end) + && push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) + && pusharray8(pusch_pdu->pusch_data.cb_present_and_position, + (pusch_pdu->pusch_data.num_cb + 7) / 8, + (pusch_pdu->pusch_data.num_cb + 7) / 8, + ppWritePackedMsg, + end))) { + return 0; + } + } break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: { + if (!(push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end))) { + return 0; + } + } break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: { + if (!push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end)) { + return 0; + } + for (int i = 0; i < pusch_pdu->pusch_ptrs.num_ptrs_ports; ++i) { + if (!(push16(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_port_index, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_dmrs_port, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_re_offset, ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end))) { + return 0; + } + } break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: { + if (!(push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) + && push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) + && push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) + && push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end))) { + return 0; + } + } break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map); + } + } + // Pack RX Beamforming PDU + if (!(push16(pusch_pdu->beamforming.num_prgs, ppWritePackedMsg, end) + && push16(pusch_pdu->beamforming.prg_size, ppWritePackedMsg, end) + && push8(pusch_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < pusch_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < pusch_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!push16(pusch_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } return 1; } @@ -1346,48 +1420,50 @@ static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t * push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); } - - -static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_ul_tti_request_number_of_pdus_t *value = (nfapi_nr_ul_tti_request_number_of_pdus_t *)tlv; - - if(!(push16(value->pdu_size, ppWritePackedMsg, end) && - push16(value->pdu_type, ppWritePackedMsg, end) )) + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->pdu_type, ppWritePackedMsg, end)) { return 0; + } + uint8_t *pPackedLengthField = *ppWritePackedMsg; - // first match the pdu type, then call the respective function - switch(value->pdu_type) { + if (!push16(value->pdu_size, ppWritePackedMsg, end)) + return 0; + // pack PDUs + // first match the pdu type, then call the respective function + switch (value->pdu_type) { case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { - if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { - if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { - if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { - if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + if (!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) return 0; - } - break; + } break; default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); - } - break; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type); + } break; } - return 1; + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->pdu_size = packedMsgLen; + return push16(value->pdu_size, &pPackedLengthField, end); } static uint8_t pack_ul_tti_groups_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { @@ -1577,9 +1653,23 @@ static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePac return 1; } - -static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + pNfapiMsg->n_ulcch = 0; + pNfapiMsg->n_ulsch = 0; + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + switch ((&pNfapiMsg->pdus_list[i])->pdu_type) { + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + pNfapiMsg->n_ulcch++; + } break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + pNfapiMsg->n_ulsch++; + } break; + default: + break; + } + } if (!push16(pNfapiMsg->SFN, ppWritePackedMsg, end)) return 0; @@ -1587,29 +1677,28 @@ static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ return 0; if (!push8(pNfapiMsg->n_pdus, ppWritePackedMsg, end)) return 0; - if (!push8(pNfapiMsg->n_group, ppWritePackedMsg, end)) - return 0; if (!push8(pNfapiMsg->rach_present, ppWritePackedMsg, end)) return 0; if (!push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end)) return 0; if (!push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end)) return 0; + if (!push8(pNfapiMsg->n_group, ppWritePackedMsg, end)) + return 0; - for(int i=0; in_pdus; i++) { - if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + if (!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) return 0; } - for(int i=0; in_group; i++) { - if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + for (int i = 0; i < pNfapiMsg->n_group; i++) { + if (!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) return 0; } return 1; } - static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -1810,45 +1899,87 @@ static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePacke return 1; } -static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)tlv; + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->PDUType, ppWritePackedMsg, end)) { + return 0; + } + uint8_t *pPackedLengthField = *ppWritePackedMsg; + if (!(push16(value->PDUSize, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) + && pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { + if (!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and Beamforming + // TODO get these values from elsewhere and delete the hardcoded ones + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[0].pm_idx = 0; + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - - return 0; - } - - return (push16(value->PDUType, ppWritePackedMsg, end) && - push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); + if (!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, + ppWritePackedMsg, + end)) { + return 0; + } + for (int digInt = 0; digInt < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; + digInt++) { + if (!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i] + .precodingAndBeamforming.prgs_list[prg] + .dig_bf_interface_list[digInt] + .beam_idx, + ppWritePackedMsg, + end)) { + return 0; + } + } + } + if (!(push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + // DCI Payload fields + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + // Pack DCI Payload + pack_dci_payload(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, + ppWritePackedMsg, + end))) { + return 0; + } + } + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->PDUSize = packedMsgLen; + return push16(value->PDUSize, &pPackedLengthField, end); } static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { @@ -1878,40 +2009,32 @@ static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8 } //pack_tx_data_pdu_list_value -static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; - - if(!(push32(value->num_TLV, ppWritePackedMsg, end) && - push16(value->PDU_index, ppWritePackedMsg, end) && - push16(value->PDU_length, ppWritePackedMsg, end) - )) + if (!(push16(value->PDU_length, ppWritePackedMsg, end) && push16(value->PDU_index, ppWritePackedMsg, end) + && push32(value->num_TLV, ppWritePackedMsg, end))) return 0; uint16_t i = 0; uint16_t total_number_of_tlvs = value->num_TLV; - for(; i < total_number_of_tlvs; ++i) { - if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && - push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + for (; i < total_number_of_tlvs; ++i) { + if (!(push16(value->TLVs[i].tag, ppWritePackedMsg, end) && push16(value->TLVs[i].length, ppWritePackedMsg, end))) return 0; - switch(value->TLVs[i].tag) { + switch (value->TLVs[i].tag) { case 0: { - if (!pusharray32(value->TLVs[i].value.direct, sizeof(value->TLVs[i].value.direct) / sizeof(uint32_t), - value->TLVs[i].length / sizeof(uint32_t), ppWritePackedMsg, end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", - __FUNCTION__, __LINE__, value->TLVs[i].length); + if (!pusharray32(value->TLVs[i].value.direct, 16384, (value->TLVs[i].length + 3) / 4, ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); return 0; } - break; } case 1: { - if (!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length / sizeof(uint32_t), - value->TLVs[i].length / sizeof(uint32_t), ppWritePackedMsg, end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", - __FUNCTION__, __LINE__, value->TLVs[i].length); + if (!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length, value->TLVs[i].length, ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); return 0; } @@ -1919,7 +2042,7 @@ static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg } default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag); break; } } @@ -1971,19 +2094,25 @@ static uint8_t pack_tx_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, return 1; } -static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - if (!( - push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) - )) + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end))) return 0; - for(int i=0; iNumber_of_PDUs; i++) { - if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { + if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", + __FUNCTION__, + __LINE__, + i, + pNfapiMsg->pdu_list[i].PDU_length, + pNfapiMsg->pdu_list[i].PDU_index); return 0; + } } return 1; @@ -3034,79 +3163,84 @@ return 1; static uint8_t pack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push16(value->pdu_length, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; - if(pusharray8(value->pdu, value->pdu_length, value->pdu_length, ppWritePackedMsg, end) == 0) - return 0; + if(pusharray8(value->pdu, value->pdu_length, value->pdu_length, ppWritePackedMsg, end) == 0) + return 0; - return 1; + return 1; } static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) - return 0; - } + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) + { + if(!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) + return 0; + } - return 1; + return 1; } //NR CRC INDICATION -static uint8_t pack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) +static uint8_t pack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push8(value->tb_crc_status, ppWritePackedMsg, end) && - push16(value->num_cb, ppWritePackedMsg, end) && - //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - return 1; + if (!(push32(value->handle, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push8(value->harq_id, ppWritePackedMsg, end) && push8(value->tb_crc_status, ppWritePackedMsg, end) + && push16(value->num_cb, ppWritePackedMsg, end))) { + return 0; + } + if (value->num_cb != 0) { + if (!pusharray8(value->cb_crc_status, + (int)(value->num_cb / 8) + 1, + (int)(value->num_cb / 8) + 1, + ppWritePackedMsg, + end)) { // length is ceil(NumCb/8) + return 0; + } + } + if (!(push8(value->ul_cqi, ppWritePackedMsg, end) && push16(value->timing_advance, ppWritePackedMsg, end) + && push16(value->rssi, ppWritePackedMsg, end))) { + return 0; + } + return 1; } static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) - )) - return 0; + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; - for (int i = 0; i < pNfapiMsg->number_crcs; i++) - { - if(!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end)) - return 0; - } + for (int i = 0; i < pNfapiMsg->number_crcs; i++) + { + if(!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end)) + return 0; + } -return 1; + return 1; } //SRS INDICATION @@ -3287,7 +3421,7 @@ return 1; //UCI INDICATION static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; if (!push8(value->pduBitmap, ppWritePackedMsg, end)) return 0; @@ -3322,123 +3456,192 @@ static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint } } - return 1; + return 1; } static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; - if (!push8(value->pduBitmap, ppWritePackedMsg, end)) - return 0; - if (!push32(value->handle, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rnti, ppWritePackedMsg, end)) - return 0; - if (!push8(value->pucch_format, ppWritePackedMsg, end)) - return 0; - if (!push8(value->ul_cqi, ppWritePackedMsg, end)) - return 0; - if (!push16(value->timing_advance, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rssi, ppWritePackedMsg, end)) - return 0; + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->pucch_format-2, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; - if (value->pduBitmap & 0x01) { //SR - if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->sr.sr_payload, - (int)((value->sr.sr_bit_len / 8) + 1), - (int)((value->sr.sr_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if (value->pduBitmap & 0x01) { //SR + if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->sr.sr_payload, + (int)((value->sr.sr_bit_len / 8) + 1), + (int)((value->sr.sr_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - if ((value->pduBitmap >> 1) & 0x01) { //HARQ - if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->harq.harq_payload, - (int)((value->harq.harq_bit_len / 8) + 1), - (int)((value->harq.harq_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if ((value->pduBitmap >> 1) & 0x01) { //HARQ + if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->harq.harq_payload, + (int)((value->harq.harq_bit_len / 8) + 1), + (int)((value->harq.harq_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - if ((value->pduBitmap >> 2) & 0x01) { //CSI-1 - if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->csi_part1.csi_part1_payload, - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if ((value->pduBitmap >> 2) & 0x01) { //CSI-1 + if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->csi_part1.csi_part1_payload, + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - if ((value->pduBitmap >> 3) & 0x01) { //CSI-2 - if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->csi_part2.csi_part2_payload, - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } + if ((value->pduBitmap >> 3) & 0x01) { //CSI-2 + if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) + return 0; + if (!pusharray8(value->csi_part2.csi_part2_payload, + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } - return 1; + return 1; +} + +static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_pusch_pdu_t *value = (nfapi_nr_uci_pusch_pdu_t *)tlv; + + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; + + // Bit 0 not used in PUSCH PDU + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) + return 0; + + if (!pusharray8(value->harq.harq_payload, + (int)((value->harq.harq_bit_len / 8) + 1), + (int)((value->harq.harq_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) + return 0; + + if (!pusharray8(value->csi_part1.csi_part1_payload, + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) + return 0; + + if (!pusharray8(value->csi_part2.csi_part2_payload, + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + ppWritePackedMsg, + end)) + return 0; + } + + return 1; } static uint8_t pack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) { - if (!push16(value->pdu_type, ppWritePackedMsg, end)) - return 0; - if (!push16(value->pdu_size, ppWritePackedMsg, end)) - return 0; + if (!push16(value->pdu_type, ppWritePackedMsg, end)) + return 0; + if (!push16(value->pdu_size, ppWritePackedMsg, end)) + return 0; - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + if(!pack_nr_uci_pusch(&value->pusch_pdu, ppWritePackedMsg, end)){ + return 0; + } + break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: - pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); - break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + if(!pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end)){ + return 0; + } + break; - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: - pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end); - break; - } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + if(!pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end)){ + return 0; + } + break; + } - return 1; + return 1; } static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; - if (!push16(pNfapiMsg->sfn , ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->slot , ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)) - return 0; + if (!push16(pNfapiMsg->sfn , ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->slot , ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)) + return 0; - for (int i = 0; i < pNfapiMsg->num_ucis; i++) - { - if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end)) - return 0; + for (int i = 0; i < pNfapiMsg->num_ucis; i++) + { + if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end)) + return 0; - } + } -return 1; + return 1; } @@ -3446,95 +3649,95 @@ return 1; int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { -nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; -uint8_t *pWritePackedMessage = pPackedBuf; -uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; -if (pMessageBuf == NULL || pPackedBuf == NULL) { + if (pMessageBuf == NULL || pPackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); return -1; -} + } -uint8_t *end = (uint8_t *)pPackedBuf + packedBufLen; + uint8_t *end = (uint8_t *)pPackedBuf + packedBufLen; -// process the header -if (!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) - && push16(0 /*pMessageHeader->message_length*/, &pWritePackedMessage, end) - && push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) - && push32(0 /*pMessageHeader->checksum*/, &pWritePackedMessage, end) - && push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { + // process the header + if (!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) + && push16(0 /*pMessageHeader->message_length*/, &pWritePackedMessage, end) + && push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) + && push32(0 /*pMessageHeader->checksum*/, &pWritePackedMessage, end) + && push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); return -1; -} + } -if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, // pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); -} -// look for the specific message -uint8_t result = 0; -switch (pMessageHeader->message_id) { + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_UE_RELEASE_REQUEST: - result = pack_nr_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_UE_RELEASE_RESPONSE: - result = pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; default: { - if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { if (config && config->pack_p7_vendor_extension) { result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); } else { @@ -3543,47 +3746,47 @@ switch (pMessageHeader->message_id) { __FUNCTION__, pMessageHeader->message_id); } - } else { + } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } + } } break; -} + } -if (result == 0) { + if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); return -1; -} + } -// check for a valid message length -uintptr_t msgHead = (uintptr_t)pPackedBuf; -uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; -uint32_t packedMsgLen = msgEnd - msgHead; -uint16_t packedMsgLen16; -if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); return -1; -} else { + } else { packedMsgLen16 = (uint16_t)packedMsgLen; -} + } -// Update the message length in the header -pMessageHeader->message_length = packedMsgLen16; + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; -if (!push16(packedMsgLen16, &pPackedLengthField, end)) + if (!push16(packedMsgLen16, &pPackedLengthField, end)) return -1; -if (1) { + if (1) { // quick test if (pMessageHeader->message_length != packedMsgLen) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, - "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", - packedMsgLen, - pMessageHeader->message_length, - pMessageHeader->message_id); + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", + packedMsgLen, + pMessageHeader->message_length, + pMessageHeader->message_id); } -} + } -return (packedMsgLen); + return (packedMsgLen); } int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { @@ -3751,122 +3954,179 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu // Unpack routines // NR: -static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; - return( - pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &value->start_rb, end) && - pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && - pull8(ppReadPackedMsg, &value->csi_type, end) && - pull8(ppReadPackedMsg, &value->row, end) && - pull16(ppReadPackedMsg, &value->freq_domain, end) && - pull8(ppReadPackedMsg, &value->symb_l0, end) && - pull8(ppReadPackedMsg, &value->symb_l1, end) && - pull8(ppReadPackedMsg, &value->cdm_type, end) && - pull8(ppReadPackedMsg, &value->freq_density, end) && - pull16(ppReadPackedMsg, &value->scramb_id, end) && - pull8(ppReadPackedMsg, &value->power_control_offset, end) && - pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) - ); + uint16_t num_prgs = 0, prg_size = 0; + uint8_t dig_bf_interfaces = 0; + return (pull16(ppReadPackedMsg, &value->bwp_size, end) && pull16(ppReadPackedMsg, &value->bwp_start, end) + && pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &value->cyclic_prefix, end) + && pull16(ppReadPackedMsg, &value->start_rb, end) && pull16(ppReadPackedMsg, &value->nr_of_rbs, end) + && pull8(ppReadPackedMsg, &value->csi_type, end) && pull8(ppReadPackedMsg, &value->row, end) + && pull16(ppReadPackedMsg, &value->freq_domain, end) && pull8(ppReadPackedMsg, &value->symb_l0, end) + && pull8(ppReadPackedMsg, &value->symb_l1, end) && pull8(ppReadPackedMsg, &value->cdm_type, end) + && pull8(ppReadPackedMsg, &value->freq_density, end) && pull16(ppReadPackedMsg, &value->scramb_id, end) + && pull8(ppReadPackedMsg, &value->power_control_offset, end) + && pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) && + // Precoding and Beamforming hardcoded to 0 + pull16(ppReadPackedMsg, &num_prgs, end) && pull16(ppReadPackedMsg, &prg_size, end) + && pull8(ppReadPackedMsg, &dig_bf_interfaces, end)); } +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; -static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + if (!(pull16(ppReadPackedMsg, &value->BWPSize, end) && pull16(ppReadPackedMsg, &value->BWPStart, end) + && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) + && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && pull8(ppReadPackedMsg, &value->DurationSymbols, end) + && pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) + && pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && pull8(ppReadPackedMsg, &value->RegBundleSize, end) + && pull8(ppReadPackedMsg, &value->InterleaverSize, end) && pull8(ppReadPackedMsg, &value->CoreSetType, end) + && pull16(ppReadPackedMsg, &value->ShiftIndex, end) && pull8(ppReadPackedMsg, &value->precoderGranularity, end) + && pull16(ppReadPackedMsg, &value->numDlDci, end))) { + return 0; + } - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && - pull8(ppReadPackedMsg, &value->RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->CoreSetType, end) && - pull16(ppReadPackedMsg, &value->ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->numDlDci, end)); + for (uint16_t i = 0; i < value->numDlDci; ++i) { + if (!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, end))) { + return 0; + } + for (int prg = 0; prg < value->dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, end)) { + return 0; + } + for (int digInt = 0; digInt < value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; digInt++) { + if (!pull16(ppReadPackedMsg, + &value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, + end)) { + return 0; + } + } + } + if (!(pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) + && unpack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppReadPackedMsg, end))) { + return 0; + } + } + // TODO: resolve the packaging of array (currently sending a single element) + return 1; } - - -static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->pduBitmap, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->pduIndex, end) && - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && - pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && - pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && - pull16(ppReadPackedMsg, &value->dataScramblingId, end) && - pull8(ppReadPackedMsg, &value->nrOfLayers, end) && - pull8(ppReadPackedMsg, &value->transmissionScheme, end) && - pull8(ppReadPackedMsg, &value->refPoint, end) && - pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && - pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && - pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && - pull8(ppReadPackedMsg, &value->SCID, end) && - pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && - pull16(ppReadPackedMsg, &value->dmrsPorts, end) && - pull8(ppReadPackedMsg, &value->resourceAlloc, end) && - pull16(ppReadPackedMsg, &value->rbStart, end) && - pull16(ppReadPackedMsg, &value->rbSize, end) && - pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && - pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && - pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSReOffset, end) - ); + uint8_t powerControlOffset = 0, powerControlOffsetSS = 0; + + if (!(pull16(ppReadPackedMsg, &value->pduBitmap, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull16(ppReadPackedMsg, &value->pduIndex, end) && pull16(ppReadPackedMsg, &value->BWPSize, end) + && pull16(ppReadPackedMsg, &value->BWPStart, end) && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) + && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && pull8(ppReadPackedMsg, &value->NrOfCodewords, end))) { + return 0; + } + for (int i = 0; i < value->NrOfCodewords; ++i) { + if (!(pull16(ppReadPackedMsg, &value->targetCodeRate[i], end) && pull8(ppReadPackedMsg, &value->qamModOrder[i], end) + && pull8(ppReadPackedMsg, &value->mcsIndex[i], end) && pull8(ppReadPackedMsg, &value->mcsTable[i], end) + && pull8(ppReadPackedMsg, &value->rvIndex[i], end) && pull32(ppReadPackedMsg, &value->TBSize[i], end))) { + return 0; + } + } + + if (!(pull16(ppReadPackedMsg, &value->dataScramblingId, end) && pull8(ppReadPackedMsg, &value->nrOfLayers, end) + && pull8(ppReadPackedMsg, &value->transmissionScheme, end) && pull8(ppReadPackedMsg, &value->refPoint, end) + && pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && pull8(ppReadPackedMsg, &value->dmrsConfigType, end) + && pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && pull8(ppReadPackedMsg, &value->SCID, end) + && pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && pull16(ppReadPackedMsg, &value->dmrsPorts, end) + && pull8(ppReadPackedMsg, &value->resourceAlloc, end) && pullarray8(ppReadPackedMsg, &value->rbBitmap[0], 36, 36, end) + && pull16(ppReadPackedMsg, &value->rbStart, end) && pull16(ppReadPackedMsg, &value->rbSize, end) + && pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) + && pull8(ppReadPackedMsg, &value->NrOfSymbols, end))) { + return 0; + } + // Check pduBitMap bit 1 to pull PTRS parameters or not + if (value->pduBitmap & 0b1) { + if (!(pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) + && pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + && pull8(ppReadPackedMsg, &value->nEpreRatioOfPDSCHToPTRS, end))) { + return 0; + } + } + + if (!(pull16(ppReadPackedMsg, &value->precodingAndBeamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->precodingAndBeamforming.dig_bf_interfaces, end))) { + return 0; + } + + for (int i = 0; i < value->precodingAndBeamforming.num_prgs; ++i) { + if (!pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prgs_list[i].pm_idx, end)) { + return 0; + } + for (int k = 0; k < value->precodingAndBeamforming.dig_bf_interfaces; ++k) { + if (!pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, end)) { + return 0; + } + } + } + // TODO Add TX power info + // Hardcoded values that represent 0db + + if (!(pull8(ppReadPackedMsg, &powerControlOffset, end) && // powerControlOffset + pull8(ppReadPackedMsg, &powerControlOffsetSS, end))) { // powerControlOffsetSS + return 0; + } + // TODO Add CBG Fields + return 1; } - -static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Unpacking ssb. \n"); + uint8_t byte3, byte2, byte1, byte0; nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; - return( - pull16(ppReadPackedMsg, &value->PhysCellId, end) && - pull8(ppReadPackedMsg, &value->BetaPss, end) && - pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && - pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && - pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && - pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && - pull32(ppReadPackedMsg, &value->bchPayload, end) && - pull8(ppReadPackedMsg, &value->ssbRsrp, end) - // TODO: pack precoding_and_beamforming too - ); -} + if (!(pull16(ppReadPackedMsg, &value->PhysCellId, end) && pull8(ppReadPackedMsg, &value->BetaPss, end) + && pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) + && pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) + && pull8(ppReadPackedMsg, &byte3, end) && pull8(ppReadPackedMsg, &byte2, end) && pull8(ppReadPackedMsg, &byte1, end) + && pull8(ppReadPackedMsg, &byte0, end))) { // this should be always 0, bchpayload is 24 bits + return 0; + } + // rebuild the bchpayload + value->bchPayload = byte3; + value->bchPayload = value->bchPayload << 8; + value->bchPayload |= byte2; + value->bchPayload = value->bchPayload << 8; + value->bchPayload |= byte1; + // TODO add Tx Power Info + if (!(pull8(ppReadPackedMsg, &byte1, end) && pull8(ppReadPackedMsg, &byte0, end) + && pull16(ppReadPackedMsg, &value->precoding_and_beamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->precoding_and_beamforming.dig_bf_interfaces, end))) { + return 0; + } + + for (int i = 0; i < value->precoding_and_beamforming.num_prgs; ++i) { + if (!pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prgs_list[i].pm_idx, end)) { + return 0; + } + for (int k = 0; k < value->precoding_and_beamforming.dig_bf_interfaces; ++k) { + if (!pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, end)) { + return 0; + } + } + } + return 1; +} // LTE: static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { @@ -4260,8 +4520,8 @@ static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppRe static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)msg; - if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->PDUType, end) )) + if(!(pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, (uint16_t *) &value->PDUSize, end))) return 0; // first match the pdu type, then call the respective function @@ -4470,189 +4730,180 @@ static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPa return 1; } - -static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && - pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe,256,pNfapiMsg->dl_tti_request_body.nGroup, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end))) { return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { + if (!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } int arr[12]; - - for(int i=0; idl_tti_request_body.nGroup; i++) { - for(int j=0; jdl_tti_request_body.nUe[i]; j++) { + if (!pullarray8(ppReadPackedMsg, pNfapiMsg->dl_tti_request_body.nUe, 256, pNfapiMsg->dl_tti_request_body.nGroup, end)) { + return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { + for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; } - if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) - return 0; - } - - for(int i=0; idl_tti_request_body.nPDUs; i++) { - if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + if (!(pullarrays32(ppReadPackedMsg, arr, 12, pNfapiMsg->dl_tti_request_body.nUe[i], end))) return 0; } return 1; } - -static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_prach_pdu_t *prach_pdu = (nfapi_nr_prach_pdu_t *)tlv; - return( - pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && - pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) - // TODO: ignoring beamforming tlv for now - ); + + if (!(pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) + && pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) + && pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && pull16(ppReadPackedMsg, &prach_pdu->num_cs, end))) { + return 0; + } + // TODO: ignoring beamforming tlv for now + if (prach_pdu->beamforming.prgs_list == NULL) { + prach_pdu->beamforming.prgs_list = calloc(prach_pdu->beamforming.num_prgs, sizeof(*prach_pdu->beamforming.prgs_list)); + } + if (prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list == NULL) { + prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list = + calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list)); + } + // Pack RX Beamforming PDU + if (!(pull16(ppReadPackedMsg, &prach_pdu->beamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &prach_pdu->beamforming.prg_size, end) + && pull8(ppReadPackedMsg, &prach_pdu->beamforming.dig_bf_interface, end))) { + return 0; + } + for (int prg = 0; prg < prach_pdu->beamforming.num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < prach_pdu->beamforming.dig_bf_interface; digBFInterface++) { + if (!pull16(ppReadPackedMsg, &prach_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, end)) { + return 0; + } + } + } + + return 1; } - -static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_pucch_pdu_t *pucch_pdu = (nfapi_nr_pucch_pdu_t *)tlv; - return( - pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && - pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pi_2bpsk, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && - pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && - pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && - pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && - pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && - pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && - pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + uint16_t dummy16 = 0; + uint8_t dummy8 = 0; + return (pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && pull32(ppReadPackedMsg, &pucch_pdu->handle, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) + && pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) + && pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) + && pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && pull8(ppReadPackedMsg, &pucch_pdu->pi_2bpsk, end) + && pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) + && pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) + && pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) + && pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) + && pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) + && pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) + && pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) + && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) + && pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) + && pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) + && pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) && // TODO: ignoring beamforming tlv for now - ); + pull16(ppReadPackedMsg, &dummy16, end) && pull16(ppReadPackedMsg, &dummy16, end) && pull8(ppReadPackedMsg, &dummy8, end)); } - -static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ nfapi_nr_pusch_pdu_t *pusch_pdu = (nfapi_nr_pusch_pdu_t *)tlv; - if (!( - pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && - pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && - pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && - pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && - pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && - pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && - pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && - pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && - pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && - pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) + && pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) + && pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) + && pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) + && pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) + && pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) + && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) + && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->scid, end) + && pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) + && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) + && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) + && pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) + && pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) + && pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) + && pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) + && pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) // TODO: ignoring beamforming tlv for now - )) + )) return 0; - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map) { + // Pack Optional Data only included if indicated in pduBitmap + switch (pusch_pdu->pdu_bit_map) { case PUSCH_PDU_BITMAP_PUSCH_DATA: { // pack optional TLVs - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && - pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && - pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) - ); - } - break; + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) + && pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) + && pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position, 1, 1, end))) { + return 0; + } + } break; case PUSCH_PDU_BITMAP_PUSCH_UCI: { - return( - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) - ); - } - break; + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end))) { + return 0; + } + } break; case PUSCH_PDU_BITMAP_PUSCH_PTRS: { - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) - ); - } - break; + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end))) { + return 0; + } + } break; case PUSCH_PDU_BITMAP_DFTS_OFDM: { - return( - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) - ); - } - break; + if (!(pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) + && pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) + && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end))) { + return 0; + } + } break; default: { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map); } } + uint16_t dummy16 = 0; + uint8_t dummy8 = 0; + if (!(pull16(ppReadPackedMsg, &dummy16, end) && pull16(ppReadPackedMsg, &dummy16, end) && pull8(ppReadPackedMsg, &dummy8, end))) { + return 0; + } return 1; } - static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_srs_pdu_t *srs_pdu = (nfapi_nr_srs_pdu_t *)tlv; return( @@ -4687,8 +4938,8 @@ static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMs static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_ul_tti_request_number_of_pdus_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t *)msg; - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) )) return 0; // first natch the pdu type, then call the respective function @@ -4741,8 +4992,8 @@ static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_ return 1; } - -static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; if (!pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end)) @@ -4751,21 +5002,20 @@ static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end)) return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end)) - return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end)) return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end)) return 0; if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end)) return 0; - - for(int i=0; i< pNfapiMsg->n_pdus; i++) { + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end)) + return 0; + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) return 0; } - for(int i=0; i< pNfapiMsg->n_group; i++) { + for (int i = 0; i < pNfapiMsg->n_group; i++) { if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) return 0; } @@ -4773,8 +5023,6 @@ static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo return 1; } - - static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; unpack_p7_tlv_t unpack_fns[] = { @@ -5557,43 +5805,66 @@ static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPack static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)msg; - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + if (!(pull16(ppReadPackedMsg, &value->PDUType, end) && pull16(ppReadPackedMsg, &value->PDUSize, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) + && pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end))) { + return 0; + } - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - - return (pull16(ppReadPackedMsg, &value->PDUType, end) && - pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); + for (uint16_t i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { + if (!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, end))) { + return 0; + } + for (int prg = 0; prg < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { + if (!pull16(ppReadPackedMsg, + &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, + end)) { + return 0; + } + for (int digInt = 0; digInt < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; + digInt++) { + if (!pull16(ppReadPackedMsg, + &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i] + .precodingAndBeamforming.prgs_list[prg] + .dig_bf_interface_list[digInt] + .beam_idx, + end)) { + return 0; + } + } + } + if (!(pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) + && unpack_dci_payload(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, + value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, + ppReadPackedMsg, + end))) { + return 0; + } + } + return 1; } static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { @@ -5624,25 +5895,25 @@ static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, v static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_pdu_t *pNfapiMsg = (nfapi_nr_pdu_t *)msg; - if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) && pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) - )) + pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) + )) return 0; uint16_t i = 0; uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; for(; i < total_number_of_tlvs; ++i) { - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end))) return 0; switch(pNfapiMsg->TLVs[i].tag) { case 0: { if (!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, - sizeof(pNfapiMsg->TLVs[i].value.direct) / sizeof(uint32_t), - pNfapiMsg->TLVs[i].length / sizeof(uint32_t), end)) + sizeof(pNfapiMsg->TLVs[i].value.direct) / sizeof(uint32_t), + (pNfapiMsg->TLVs[i].length+3)/4, end)) return 0; break; @@ -5650,8 +5921,8 @@ static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t case 1: { if (!pullarray32(ppReadPackedMsg,pNfapiMsg->TLVs[i].value.ptr, - pNfapiMsg->TLVs[i].length / sizeof(uint32_t), - pNfapiMsg->TLVs[i].length / sizeof(uint32_t), end)) + pNfapiMsg->TLVs[i].length, + pNfapiMsg->TLVs[i].length, end)) return 0; break; @@ -5667,17 +5938,25 @@ static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t return 1; } -static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) return 0; - for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) { - if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) { + printf("%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", + __FUNCTION__, + __LINE__, + i, + pNfapiMsg->pdu_list[i].PDU_length, + pNfapiMsg->pdu_list[i].PDU_index); + return 0; + } } return 1; @@ -5787,101 +6066,102 @@ static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end return 1; } -//RX DATA INDICATION +//RX DATA INDICATION -static uint8_t unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t* value, +static uint8_t unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, - nfapi_p7_codec_config_t* config) + nfapi_p7_codec_config_t *config) { - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull16(ppReadPackedMsg, &value->pdu_length, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; +if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull8(ppReadPackedMsg, &value->harq_id, end) && pull16(ppReadPackedMsg, &value->pdu_length, end) + && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) + return 0; - uint16_t length = value->pdu_length; - value->pdu = nfapi_p7_allocate(sizeof(*value->pdu) * length, config); - - if (pullarray8(ppReadPackedMsg, value->pdu, length, length, end) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pullarray8 failure\n", __FUNCTION__); - return 0; - } - return 1; +uint32_t length = value->pdu_length; +value->pdu = nfapi_p7_allocate(sizeof(*value->pdu) * length, config); +if (pullarray8(ppReadPackedMsg, value->pdu, length, length, end) == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pullarray8 failure\n", __FUNCTION__); + return 0; +} +return 1; } - static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) { - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - if (pNfapiMsg->number_of_pdus > 0) - { - pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); - } + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) - return 0; - } + if (pNfapiMsg->number_of_pdus > 0) + { + pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); + } -return 1; + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) + { + if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) + return 0; + } + + return 1; } //NR CRC INDICATION -static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) { - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull8(ppReadPackedMsg, &value->tb_crc_status, end) && - pull16(ppReadPackedMsg, &value->num_cb, end) && - //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; + if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull8(ppReadPackedMsg, &value->harq_id, end) && pull8(ppReadPackedMsg, &value->tb_crc_status, end) + && pull16(ppReadPackedMsg, &value->num_cb, end))) { + return 0; + } + if (value->num_cb != 0) { + if (!pullarray8(ppReadPackedMsg, + value->cb_crc_status, + (int)(value->num_cb / 8) + 1, + (int)(value->num_cb / 8) + 1, + end)) { // length is ceil(NumCb/8) + return 0; + } + } + if (!(pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) { + return 0; + } - //memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); + // memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); - return 1; + return 1; } static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t* config) { - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) - )) - return 0; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; - if (pNfapiMsg->number_crcs > 0) - { - pNfapiMsg->crc_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->crc_list) * pNfapiMsg->number_crcs, config); - } + if (pNfapiMsg->number_crcs > 0) + { + pNfapiMsg->crc_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->crc_list) * pNfapiMsg->number_crcs, config); + } - for (int i = 0; i < pNfapiMsg->number_crcs; i++) - { - if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end)) - return 0; - } + for (int i = 0; i < pNfapiMsg->number_crcs; i++) + { + if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end)) + return 0; + } -return 1; + return 1; } //SRS INDICATION @@ -6009,100 +6289,86 @@ static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, //NR RACH -static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t* value, +static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, - nfapi_p7_codec_config_t* config) + nfapi_p7_codec_config_t *config) { + if (!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && pull8(ppReadPackedMsg, &value->symbol_index, end) + && pull8(ppReadPackedMsg, &value->slot_index, end) && pull8(ppReadPackedMsg, &value->freq_index, end) + && pull8(ppReadPackedMsg, &value->avg_rssi, end) && pull8(ppReadPackedMsg, &value->avg_snr, end) + && pull8(ppReadPackedMsg, &value->num_preamble, end))) { + return 0; + } - if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && - pull8(ppReadPackedMsg, &value->symbol_index, end) && - pull8(ppReadPackedMsg, &value->slot_index, end) && - pull8(ppReadPackedMsg, &value->freq_index, end) && - pull8(ppReadPackedMsg, &value->avg_rssi, end) && - pull8(ppReadPackedMsg, &value->avg_snr, end) && - pull8(ppReadPackedMsg, &value->num_preamble, end) - )) - return 0; - - if (value->num_preamble > 0) { - value->preamble_list = nfapi_p7_allocate(sizeof(*value->preamble_list) * value->num_preamble, config); - for(int i = 0; i < value->num_preamble; i++) - { - if(!(pull8(ppReadPackedMsg, &value->preamble_list[i].preamble_index, end) && - pull16(ppReadPackedMsg, &value->preamble_list[i].timing_advance, end) && - pull32(ppReadPackedMsg, &value->preamble_list[i].preamble_pwr, end) - )) - return 0; - } - } - return 1; + if (value->num_preamble > 0) { + value->preamble_list = nfapi_p7_allocate(sizeof(*value->preamble_list) * value->num_preamble, config); + for (int i = 0; i < value->num_preamble; i++) { + nfapi_nr_prach_indication_preamble_t *preamble = &(value->preamble_list[i]); + if (!(pull8(ppReadPackedMsg, &preamble->preamble_index, end) && pull16(ppReadPackedMsg, &preamble->timing_advance, end) + && pull32(ppReadPackedMsg, &preamble->preamble_pwr, end))) { + return 0; + } + } + } + return 1; } -static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rach_indication_t* msg, nfapi_p7_codec_config_t* config) { +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_nr_rach_indication_t *msg, + nfapi_p7_codec_config_t *config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg; - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) { + return 0; + } - if (pNfapiMsg->number_of_pdus > 0) { - pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); - for(int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) - return 0; - } - } - return 1; + if (pNfapiMsg->number_of_pdus > 0) { + pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!unpack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppReadPackedMsg, end, config)) + return 0; + } + } + return 1; } -//NR UCI +//NR UCI static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, - nfapi_p7_codec_config_t *config) { + nfapi_p7_codec_config_t *config) +{ + if (!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && pull32(ppReadPackedMsg, &value->handle, end) + && pull16(ppReadPackedMsg, &value->rnti, end) && pull8(ppReadPackedMsg, &value->pucch_format, end) + && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) + return 0; + if (value->pduBitmap & 0x01) { // SR + if (!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end))) + return 0; + } - if (!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && - pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->pucch_format, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && - pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end) - )) - return 0; - } + if (((value->pduBitmap >> 1) & 0x01)) { // HARQ - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end))) + return 0; + if (value->harq.num_harq > 0) { + for (int i = 0; i < value->harq.num_harq; i++) { + if (!pull8(ppReadPackedMsg, &value->harq.harq_list[i].harq_value, end)) { + return 0; + } + } + } + } - - if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && - pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end) - )) - return 0; - if (value->harq.num_harq > 0) { - - for (int i = 0; i < value->harq.num_harq; i++) { - if (!pull8(ppReadPackedMsg, &value->harq.harq_list[i].harq_value, end)) { - return 0; - } - } - } - } - - return 1; + return 1; } - static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value, uint8_t **ppReadPackedMsg, uint8_t *end, @@ -6123,6 +6389,7 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* if (!pull16(ppReadPackedMsg, &value->rssi, end)) return 0; + value->pucch_format += 2; if (value->pduBitmap & 0x01) { //SR if (!pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end)) return 0; @@ -6214,60 +6481,148 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* return 1; } +static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!pull8(ppReadPackedMsg, &value->pduBitmap, end)) + return 0; + if (!pull32(ppReadPackedMsg, &value->handle, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rnti, end)) + return 0; + if (!pull8(ppReadPackedMsg, &value->ul_cqi, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->timing_advance, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rssi, end)) + return 0; + + // Bit 0 not used in PUSCH PDU + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end)) + return 0; + + value->harq.harq_payload = + nfapi_p7_allocate(sizeof(*value->harq.harq_payload) * (int)((value->harq.harq_bit_len / 8) + 1), config); + if (value->harq.harq_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->harq.harq_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, + value->harq.harq_payload, + (int)((value->harq.harq_bit_len / 8) + 1), + (int)((value->harq.harq_bit_len / 8) + 1), + end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end)) + return 0; + + value->csi_part1.csi_part1_payload = + nfapi_p7_allocate(sizeof(*value->csi_part1.csi_part1_payload) * (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + config); + if (value->csi_part1.csi_part1_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part1.csi_part1_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, + value->csi_part1.csi_part1_payload, + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), + end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end)) + return 0; + + value->csi_part2.csi_part2_payload = + nfapi_p7_allocate(sizeof(*value->csi_part2.csi_part2_payload) * (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + config); + if (value->csi_part2.csi_part2_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part2.csi_part2_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, + value->csi_part2.csi_part2_payload, + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), + end)) + return 0; + } + + return 1; +} + static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { - if (!pull16(ppReadPackedMsg, &value->pdu_type, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->pdu_size, end)) - return 0; + if (!pull16(ppReadPackedMsg, &value->pdu_type, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->pdu_size, end)) + return 0; - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *uci_pdu = &value->pusch_pdu; + if (!unpack_nr_uci_pusch(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + if (!unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + if (!unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + default: + NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected pdu type %d\n", value->pdu_type); + break; + } - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - if (!unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - if (!unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; - } - default: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected pdu type %d\n", value->pdu_type); - break; - } - - return 1; + return 1; } -static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->slot , end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)) - return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)) + return 0; - pNfapiMsg->uci_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->uci_list) * pNfapiMsg->num_ucis, config); - for (int i = 0; i < pNfapiMsg->num_ucis; i++) - { - if (!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppReadPackedMsg, end, config)) - return 0; - } + pNfapiMsg->uci_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->uci_list) * pNfapiMsg->num_ucis, config); + for (int i = 0; i < pNfapiMsg->num_ucis; i++) { + if (!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppReadPackedMsg, end, config)) + return 0; + } - return 1; + return 1; } static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { @@ -8093,41 +8448,29 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_UE_RELEASE_REQUEST: if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)){ nfapi_nr_slot_indication_scf_t* msg = (nfapi_nr_slot_indication_scf_t*) pMessageHeader; result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: @@ -8137,8 +8480,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->pdu_list->pdu = (uint8_t *) malloc(sizeof(uint8_t)); result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: @@ -8148,8 +8489,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->crc_list = (nfapi_nr_crc_t*) malloc(sizeof(nfapi_nr_crc_t)); result = unpack_nr_crc_indication(&pReadPackedMessage,end , msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: @@ -8158,8 +8497,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->uci_list = (nfapi_nr_uci_t*) malloc(sizeof(nfapi_nr_uci_t)); result = unpack_nr_uci_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: @@ -8168,8 +8505,6 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * msg->pdu_list = (nfapi_nr_srs_indication_pdu_t*) malloc(sizeof(nfapi_nr_srs_indication_pdu_t)); result = unpack_nr_srs_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: @@ -8177,36 +8512,26 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * nfapi_nr_rach_indication_t* msg = (nfapi_nr_rach_indication_t*) pMessageHeader; result = unpack_nr_rach_indication(&pReadPackedMessage, end, msg, config); } - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; break; case NFAPI_TIMING_INFO: if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; case NFAPI_UE_RELEASE_RESPONSE: if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; break; default: @@ -8230,8 +8555,9 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * break; } - if(result == 0) - return -1; - else - return 0; + if (result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + return 0; } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index a1be4d0edc..dd91d2fc71 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -249,18 +249,17 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } -//NR UPLINK INDICATION +//NR UPLINK INDICATION int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind) { - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } + if (config == NULL || ind == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); } int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 0b4e12ad5d..69070c5544 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -456,7 +456,6 @@ int32_t rate_matching_lte(uint32_t N_coded, unsigned int crcbit (unsigned char * inputptr, int octetlen, unsigned int poly); -int16_t reverseBits(int32_t ,int32_t); void phy_viterbi_dot11(int8_t *,uint8_t *,uint16_t); int32_t nr_segmentation(unsigned char *input_buffer, diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index ed3fd55079..9cf5e26cc7 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -28,6 +28,7 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "openair1/PHY/MODULATION/nr_modulation.h" #include "openair1/PHY/defs_RU.h" #include "openair1/PHY/CODING/nrLDPC_extern.h" @@ -525,6 +526,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) init_scrambling_luts(); init_pucch2_luts(); + nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH + load_nrLDPClib(NULL); if (gNB->ldpc_offload_flag) @@ -683,7 +686,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) int n_buf = Prx*max_ul_mimo_layers; int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB; - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); + int nb_re_pusch2 = (nb_re_pusch + 7) & ~7; gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c new file mode 100644 index 0000000000..c593c04cc5 --- /dev/null +++ b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c @@ -0,0 +1,70 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "PHY/defs_eNB.h" +#include "PHY/sse_intrin.h" +#include "PHY/NR_ESTIMATION/nr_ul_estimation.h" + +// Reference of openair1/PHY/LTE_ESTIMATION/freq_equalization.c + +// This is 4096/(1:4096) in simde__m128i format +static simde__m128i nr_inv_ch[4096]; /* = {0, 4096/1, 4096/2, 4096/3, 4096/4...}*/ + +void nr_init_fde() +{ + for (int i = 1;i < 4096; i++) + nr_inv_ch[i] = simde_mm_set1_epi16(4096/i); +} + +void nr_freq_equalization (NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdataF_comp, + int32_t *ul_ch_mag, + int32_t *ul_ch_magb, + uint8_t symbol, + uint16_t Msc_RS, + uint8_t Qm) +{ + simde__m128i *rxdataF_comp128 = (simde__m128i *)rxdataF_comp; + simde__m128i *ul_ch_mag128 = (simde__m128i *)ul_ch_mag; + simde__m128i *ul_ch_magb128 = (simde__m128i *)ul_ch_magb; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "symbol %d >= %d\n", + symbol, frame_parms->symbols_per_slot); + AssertFatal(Msc_RS <= frame_parms->N_RB_UL*12, "Msc_RS %d >= %d\n", + Msc_RS, frame_parms->N_RB_UL*12); + + for (uint16_t re = 0; re < (Msc_RS >> 2); re++) { + int16_t amp = (*((int16_t*)&ul_ch_mag128[re])); + + if (amp > 4095) + amp = 4095; + + rxdataF_comp128[re] = simde_mm_srai_epi16(simde_mm_mullo_epi16(rxdataF_comp128[re],nr_inv_ch[amp]),3); + + if (Qm == 4) + ul_ch_mag128[re] = simde_mm_set1_epi16(324); // this is 512*2/sqrt(10) + else if (Qm == 6) { + ul_ch_mag128[re] = simde_mm_set1_epi16(316); // this is 512*4/sqrt(42) + ul_ch_magb128[re] = simde_mm_set1_epi16(158); // this is 512*2/sqrt(42) + } else if(Qm != 2) + AssertFatal(1, "nr_freq_equalization(), Qm = %d, should be 2, 4 or 6. symbol=%d, Msc_RS=%d\n", Qm, symbol, Msc_RS); + } +} diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 98606e7f3c..11a316d77e 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -486,6 +486,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, * 2) Interpolate PTRS estimated value in TD after all PTRS symbols * 3) Compensated DMRS based estimated signal with PTRS estimation for slot *********************************************************************/ +// #define DEBUG_UL_PTRS void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul, @@ -495,7 +496,6 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint32_t nb_re_pusch) { NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; - //#define DEBUG_UL_PTRS 1 int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; @@ -573,13 +573,6 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, } } -#ifdef DEBUG_UL_PTRS - LOG_M("ptrsEstUl.m", "est", pusch_vars->ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1); - LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp", - &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size], - rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1); -#endif - /*------------------------------------------------------------------------------------------------------- */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */ /*--------------------------------------------------------------------------------------------------------*/ @@ -590,15 +583,15 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, #ifdef DEBUG_UL_PTRS printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); #endif - rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], &phase_per_symbol[i], - (c16_t *)&pusch_vars->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + (c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], ((*nb_rb) * NR_NB_SC_PER_RB), 15); - }// if not DMRS Symbol - }// symbol loop - }// last symbol check - }//Antenna loop + } // if not DMRS Symbol + } // symbol loop + } // last symbol check + } // Antenna loop } uint32_t calc_power(const int16_t *x, const uint32_t size) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index c75b4d4ed7..4934498a4a 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -83,4 +83,15 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, int32_t srs_estimated_channel_time_shifted[][1<num_ant_ports][gNB->frame_parms.ofdm_symbol_size], int8_t *snr_per_rb, int8_t *snr); + +void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, + int *rxdataF_comp, + int *ul_ch_mag, + int *ul_ch_mag_b, + unsigned char symbol, + unsigned short Msc_RS, + unsigned char Qm); + +void nr_init_fde(void); + #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index d244881c32..5f5a9260cd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -297,7 +297,8 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056; - if (A > 3824) { + int B; + if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload crc = crc24a(a,A)>>8; a[A>>3] = ((uint8_t *)&crc)[2]; @@ -305,7 +306,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, a[2+(A>>3)] = ((uint8_t *)&crc)[0]; //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - harq->B = A+24; + B = A + 24; // harq->b = a; AssertFatal((A / 8) + 4 <= max_bytes, "A %d is too big (A/8+4 = %d > %d)\n", @@ -320,7 +321,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, a[1+(A>>3)] = ((uint8_t *)&crc)[0]; //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - harq->B = A+16; + B = A + 16; // harq->b = a; AssertFatal((A / 8) + 3 <= max_bytes, "A %d is too big (A/8+3 = %d > %d)\n", @@ -333,11 +334,11 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; start_meas(dlsch_segmentation_stats); - impp.Kb = nr_segmentation(harq->b, harq->c, harq->B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); + impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); stop_meas(dlsch_segmentation_stats); if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",impp.n_segments,harq->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); return(-1); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 692776b8cb..dd2493984e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -236,7 +236,6 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, uint16_t M; uint8_t nushift; uint32_t unscrambling_mask; - uint64_t a_reversed=0; LOG_D(PHY, "PBCH generation started\n"); ///Payload generation NR_gNB_PBCH m_pbch; @@ -298,8 +297,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, #endif // Encoder reversal - for (int i=0; ipbch_a_prime>>i)&1)<<(31-i); + uint64_t a_reversed = reverse_bits((uint64_t)pbch->pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS); /// CRC, coding and rate matching polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, 0, 0, diff --git a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c index 9663b1f3d4..b54a5c2c0c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c +++ b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c @@ -76,3 +76,21 @@ void nr_codeword_unscrambling(int16_t* llr, uint32_t size, uint8_t q, uint32_t N } #endif } + +void nr_codeword_unscrambling_init(int16_t *s2, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI) +{ + uint32_t x1; + uint32_t x2 = (n_RNTI << 15) + (q << 14) + Nid; + simde__m128i *s128=(simde__m128i *)s2; + + uint32_t s = lte_gold_generic(&x1, &x2, 1); + uint8_t *s8=(uint8_t *)&s; + + for (int i = 0; i < (size +31) >> 5; i++) { + *s128++ = byte2m128i[s8[0]]; + *s128++ = byte2m128i[s8[1]]; + *s128++ = byte2m128i[s8[2]]; + *s128++ = byte2m128i[s8[3]]; + s = lte_gold_generic(&x1, &x2, 0); + } +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index 5437e2e815..64ffc9a36a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -73,6 +73,7 @@ void nr_codeword_scrambling(uint8_t *in, uint32_t* out); void nr_codeword_unscrambling(int16_t* llr, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI); +void nr_codeword_unscrambling_init(int16_t *s, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI); /**@}*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 2478748688..2583996b95 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -125,82 +125,11 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM @param slot Slot number @param harq_pid HARQ process ID */ -void nr_rx_pusch(PHY_VARS_gNB *gNB, - uint8_t UE_id, - uint32_t frame, - uint8_t slot, - unsigned char harq_pid); - -/** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented) - @param rxdataF pointer to the received frequency domain signal - @param rxdataF_ext pointer to the extracted frequency domain signal - @param rb_alloc RB allocation map (used for Resource Allocation Type 0 in NR) - @param symbol Symbol on which to act (within-in nr_TTI_rx) - @param start_rb The starting RB in the RB allocation (used for Resource Allocation Type 1 in NR) - @param nb_rb_pusch The number of RBs allocated (used for Resource Allocation Type 1 in NR) - @param frame_parms, Pointer to frame descriptor structure -*/ -void nr_ulsch_extract_rbs(c16_t **rxdataF, - NR_gNB_PUSCH *pusch_vars, - int slot, - unsigned char symbol, - uint8_t is_dmrs_symbol, - nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_DL_FRAME_PARMS *frame_parms); - -void nr_ulsch_scale_channel(int32_t **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_ULSCH_t *ulsch_gNB, - uint8_t symbol, - uint8_t is_dmrs_symbol, - uint32_t len, - uint8_t nrOfLayers, - uint16_t nb_rb, - int shift_ch_ext); - -/** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal - @param ul_ch_estimates_ext Channel estimates in allocated RBs - @param frame_parms Pointer to frame descriptor - @param avg Pointer to average signal strength - @param pilots_flag Flag to indicate pilots in symbol - @param nb_rb Number of allocated RBs -*/ -void nr_ulsch_channel_level(int **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t symbol, - uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb); - -/** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation. In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation) - @param rxdataF_ext Frequency-domain received signal in RBs to be demodulated - @param ul_ch_estimates_ext Frequency-domain channel estimates in RBs to be demodulated - @param ul_ch_mag First Channel magnitudes (16QAM/64QAM/256QAM) - @param ul_ch_magb Second weighted Channel magnitudes (64QAM/256QAM) - @param ul_ch_magc Third weighted Channel magnitudes (256QAM) - @param rxdataF_comp Compensated received waveform - @param frame_parms Pointer to frame descriptor - @param symbol Symbol on which to operate - @param Qm Modulation order of allocation - @param nb_rb Number of RBs in allocation - @param output_shift Rescaling for compensated output (should be energy-normalizing) -*/ -void nr_ulsch_channel_compensation(int **rxdataF_ext, - int **ul_ch_estimates_ext, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int **rxdataF_comp, - int ***rho, - NR_DL_FRAME_PARMS *frame_parms, - unsigned char symbol, - int length, - uint8_t is_dmrs_symbol, - unsigned char mod_order, - uint8_t nrOfLayers, - unsigned short nb_rb, - unsigned char output_shift); +int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, + uint8_t ulsch_id, + uint32_t frame, + uint8_t slot, + unsigned char harq_pid); /*! \brief This function implements the idft transform precoding in PUSCH @@ -209,6 +138,28 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, */ void nr_idft(int32_t *z, uint32_t Msc_PUSCH); +void nr_ulsch_qpsk_qpsk(c16_t *stream0_in, + c16_t *stream1_in, + c16_t *stream0_out, + c16_t *rho01, + uint32_t length); + +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); + +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); + /** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. @param rxdataF_comp Compensated channel output @param ulsch_llr llr output @@ -216,7 +167,7 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH); @param symbol OFDM symbol index in sub-frame */ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, - int16_t *ulsch_llr, + int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol); @@ -231,11 +182,9 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int32_t **ul_ch_mag, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol); - /** \brief This function generates log-likelihood ratios (decoder input) for single-stream 64 QAM received waveforms. @param rxdataF_comp Compensated channel output @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 @@ -248,7 +197,6 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, int32_t **ul_ch_mag, int32_t **ul_ch_magb, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol); @@ -266,7 +214,6 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, int32_t **ul_ch_magb, int32_t **ul_ch_magc, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol); @@ -284,7 +231,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, int32_t *ul_ch_magb, int32_t *ul_ch_magc, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol, uint8_t mod_order); @@ -292,15 +238,17 @@ 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 **ul_ch_mag, - int32_t ***rho, - int16_t **llr_layers, - uint8_t nb_antennas_rx, - uint32_t rb_size, +void nr_ulsch_compute_ML_llr(NR_gNB_PUSCH *pusch_vars, + uint32_t symbol, + c16_t* rxdataF_comp0, + c16_t* rxdataF_comp1, + c16_t* ul_ch_mag0, + c16_t* ul_ch_mag1, + c16_t* llr_layers0, + c16_t* llr_layers1, + c16_t* rho0, + c16_t* rho1, 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); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 69015660d8..1d4e5bf71c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -122,42 +122,25 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) static void nr_processULSegment(void *arg) { ldpcDecode_t *rdata = (ldpcDecode_t *)arg; - PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int length_dec; - int Kr; - int Kr_bytes; - int K_bits_F; - uint8_t crc_type; - int i; - int j; - int r = rdata->segment_r; - int A = rdata->A; - int E = rdata->E; - int Qm = rdata->Qm; - int rv_index = rdata->rv_index; - int r_offset = rdata->r_offset; - uint8_t kc = rdata->Kc; + const int Kr = ulsch_harq->K; + const int Kr_bytes = Kr >> 3; + const int K_bits_F = Kr - ulsch_harq->F; + const int r = rdata->segment_r; + const int A = rdata->A; + const int E = rdata->E; + const int Qm = rdata->Qm; + const int rv_index = rdata->rv_index; + const int r_offset = rdata->r_offset; + const uint8_t kc = rdata->Kc; short *ulsch_llr = rdata->ulsch_llr; - int max_ldpc_iterations = p_decoderParms->numMaxIter; + const int max_ldpc_iterations = p_decoderParms->numMaxIter; int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); - int16_t z[68 * 384 + 16] __attribute__((aligned(16))); - int8_t l[68 * 384 + 16] __attribute__((aligned(16))); - - simde__m128i *pv = (simde__m128i *)&z; - simde__m128i *pl = (simde__m128i *)&l; - - Kr = ulsch_harq->K; - Kr_bytes = Kr >> 3; - K_bits_F = Kr - ulsch_harq->F; - t_nrLDPC_time_stats procTime = {0}; t_nrLDPC_time_stats *p_procTime = &procTime; - // start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// @@ -172,7 +155,6 @@ static void nr_processULSegment(void *arg) // for (int i =0; i<16; i++) // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset); - stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); ////////////////////////////////////////////////////////////////////////////////////////// @@ -182,7 +164,6 @@ static void nr_processULSegment(void *arg) ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// - // start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); if (nr_rate_matching_ldpc_rx(rdata->tbslbrm, p_decoderParms->BG, @@ -196,43 +177,35 @@ static void nr_processULSegment(void *arg) ulsch_harq->F, Kr - ulsch_harq->F - 2 * (p_decoderParms->Z)) == -1) { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); rdata->decodeIterations = max_ldpc_iterations + 1; return; - } else { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); } ulsch_harq->d_to_be_cleared[r] = false; memset(ulsch_harq->c[r], 0, Kr_bytes); - - if (ulsch_harq->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = ulsch_harq->B; - } else { - crc_type = CRC24_B; - length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; - } - + p_decoderParms->crc_type = crcType(ulsch_harq->C, A); + p_decoderParms->block_length = lenWithCrc(ulsch_harq->C, A); // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); // set first 2*Z_c bits to zeros - memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t)); + + int16_t z[68 * 384 + 16] __attribute__((aligned(16))); + + memset(z, 0, 2 * ulsch_harq->Z * sizeof(*z)); // set Filler bits - memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t)); + memset(z + K_bits_F, 127, ulsch_harq->F * sizeof(*z)); // Move coded bits before filler bits - memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t)); + memcpy(z + 2 * ulsch_harq->Z, ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(*z)); // skip filler bits - memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t)); + memcpy(z + Kr, ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(*z)); // Saturate coded bits before decoding into 8 bits values - for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { + simde__m128i *pv = (simde__m128i *)&z; + int8_t l[68 * 384 + 16] __attribute__((aligned(16))); + simde__m128i *pl = (simde__m128i *)&l; + for (int i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -242,74 +215,167 @@ static void nr_processULSegment(void *arg) ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - p_decoderParms->block_length = length_dec; - p_decoderParms->crc_type = crc_type; - rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)pl, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); + rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); if (rdata->decodeIterations <= p_decoderParms->numMaxIter) memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); - //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); +} + +int decode_offload(PHY_VARS_gNB *phy_vars_gNB, + uint8_t ULSCH_id, + short *ulsch_llr, + nfapi_nr_pusch_pdu_t *pusch_pdu, + t_nrLDPC_dec_params *decParams, + uint8_t harq_pid, + uint32_t G) +{ + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + int8_t llrProcBuf[22 * 384] __attribute__((aligned(32))); + int16_t z_ol[68 * 384] __attribute__((aligned(32))); + int8_t l_ol[68 * 384] __attribute__((aligned(32))); + uint8_t Qm = pusch_pdu->qam_mod_order; + uint8_t n_layers = pusch_pdu->nrOfLayers; + const int Kr = harq_process->K; + const int Kr_bytes = Kr >> 3; + const int kc = decParams->BG == 2 ? 52 : 68; + const uint32_t A = (harq_process->TBS) << 3; + int decodeIterations = 2; + int dtx_det = 0; + int r_offset = 0, offset = 0; + for (int r = 0; r < harq_process->C; r++) { + int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); + memset(harq_process->c[r], 0, Kr_bytes); + + decParams->R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, + E, + decParams->BG, + decParams->Z, + &harq_process->llrLen, + harq_process->round); + + if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) { + memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short)); + simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; + simde__m128i *pl_ol128 = (simde__m128i *)&l_ol; + for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { + pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); + } + + int ret = nrLDPC_decoder_offload(decParams, + harq_pid, + ULSCH_id, + r, + pusch_pdu->pusch_data.rv_index, + harq_process->F, + E, + Qm, + (int8_t *)&pl_ol128[0], + llrProcBuf, + 1); + if (ret < 0) { + LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); + + decodeIterations = ulsch->max_ldpc_iterations + 1; + return -1; + } + for (int m = 0; m < Kr >> 3; m++) { + harq_process->c[r][m] = (uint8_t)llrProcBuf[m]; + } + + if (check_crc((uint8_t *)llrProcBuf, lenWithCrc(harq_process->C, A), crcType(harq_process->C, A))) { + PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); + decodeIterations = 2; + } else { + PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); + decodeIterations = ulsch->max_ldpc_iterations + 1; + } + + r_offset += E; + } else { + dtx_det = 0; + decodeIterations = ulsch->max_ldpc_iterations + 1; + } + bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations); + if (decodeSuccess) { + memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + harq_process->processedSegments++; + } else { + LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); + LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); + break; // don't even attempt to decode other segments + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0); + + if (harq_process->processedSegments == harq_process->C) { + LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS); + ulsch->active = false; + harq_process->round = 0; + + LOG_D(PHY, "ULSCH received ok \n"); + nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); + + } else { + LOG_D(PHY, + "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", + phy_vars_gNB->Mod_id, + ulsch->frame, + ulsch->slot, + harq_pid, + ulsch->active, + harq_process->round, + harq_process->TBS); + ulsch->handled = 1; + decodeIterations = ulsch->max_ldpc_iterations + 1; + LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); + nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); + } + ulsch->last_iteration_cnt = decodeIterations; + return 0; } int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, - uint8_t ULSCH_id, - short *ulsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *pusch_pdu, - uint32_t frame, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint32_t G) - { - if (!ulsch_llr) { - LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); - return -1; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1); - - NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; - NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; - - if (!harq_process) { - LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); - return -1; + uint8_t ULSCH_id, + short *ulsch_llr, + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t *pusch_pdu, + uint32_t frame, + uint8_t nr_tti_rx, + uint8_t harq_pid, + uint32_t G) +{ + if (!ulsch_llr) { + LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); + return -1; } - uint8_t dtx_det = 0; - int Kr; - int Kr_bytes; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1); + + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + + if (!harq_process) { + LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); + return -1; + } + + // ------------------------------------------------------------------ + const uint16_t nb_rb = pusch_pdu->rb_size; + const uint8_t Qm = pusch_pdu->qam_mod_order; + const uint8_t mcs = pusch_pdu->mcs_index; + const uint8_t n_layers = pusch_pdu->nrOfLayers; + // ------------------------------------------------------------------ harq_process->processedSegments = 0; - - // ------------------------------------------------------------------ - uint16_t nb_rb = pusch_pdu->rb_size; - uint8_t Qm = pusch_pdu->qam_mod_order; - uint8_t mcs = pusch_pdu->mcs_index; - uint8_t n_layers = pusch_pdu->nrOfLayers; - // ------------------------------------------------------------------ - harq_process->TBS = pusch_pdu->pusch_data.tb_size; - dtx_det = 0; - - uint32_t A = (harq_process->TBS) << 3; - - // target_code_rate is in 0.1 units - float Coderate = (float) pusch_pdu->target_code_rate / 10240.0f; - - LOG_D(PHY,"ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", - harq_pid, ulsch->rnti, A, G, mcs, n_layers, nb_rb, Qm, Coderate, pusch_pdu->pusch_data.rv_index, harq_process->round, harq_process->harq_to_be_cleared); t_nrLDPC_dec_params decParams = {0}; decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; - int kc; - if (decParams.BG == 2) { - kc = 52; - } else { - kc = 68; - } - + const uint32_t A = (harq_process->TBS) << 3; NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); if (stats) { stats->frame = frame; @@ -324,219 +390,101 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, stats->ulsch_stats.total_bytes_tx += harq_process->TBS; } } - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; - // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) + LOG_D(PHY, + "ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", + harq_pid, + ulsch->rnti, + A, + G, + mcs, + n_layers, + nb_rb, + Qm, + pusch_pdu->target_code_rate / 10240.0f, + pusch_pdu->pusch_data.rv_index, + harq_process->round, + harq_process->harq_to_be_cleared); + + // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F) nr_segmentation(NULL, NULL, - harq_process->B, + lenWithCrc(1, A), // size in case of 1 segment &harq_process->C, &harq_process->K, &harq_process->Z, // [hna] Z is Zc &harq_process->F, decParams.BG); - if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*n_layers) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); + uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * n_layers; // number of segments to be allocated + if (harq_process->C > a_segments) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); return(-1); } - - -#ifdef DEBUG_ULSCH_DECODING - printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); - if (!frame%100) - printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); -#endif - decParams.Z = harq_process->Z; - - decParams.numMaxIter = ulsch->max_ldpc_iterations; - decParams.outMode = 0; - - uint32_t r_offset = 0; - - uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*n_layers; //number of segments to be allocated - if (nb_rb != 273) { a_segments = a_segments*nb_rb; a_segments = a_segments/273 +1; } - if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); return -1; } + #ifdef DEBUG_ULSCH_DECODING + printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); + if (!frame % 100) + printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); #endif + decParams.Z = harq_process->Z; + decParams.numMaxIter = ulsch->max_ldpc_iterations; + decParams.outMode = 0; + if (harq_process->harq_to_be_cleared) { for (int r = 0; r < harq_process->C; r++) harq_process->d_to_be_cleared[r] = true; harq_process->harq_to_be_cleared = false; } - Kr = harq_process->K; - Kr_bytes = Kr >> 3; + if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) + return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G); - uint32_t offset = 0; - if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) { - int8_t llrProcBuf[22 * 384]; - // if (dtx_det==0) { - int16_t z_ol[68 * 384]; - int8_t l_ol[68 * 384]; - int crc_type; - int length_dec; - - if (harq_process->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } else { - crc_type = CRC24_B; - length_dec = (harq_process->B + 24 * harq_process->C) / harq_process->C; - } - int decodeIterations = 2; - for (int r = 0; r < harq_process->C; r++) { - int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); - memset(harq_process->c[r], 0, Kr_bytes); - - decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round); - - if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) { - // if (dtx_det==0){ - memcpy((&z_ol[0]), ulsch_llr + r_offset, E * sizeof(short)); - simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; - simde__m128i *pl_ol128 = (simde__m128i *)&l_ol; - for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { - pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); - } - - int ret = nrLDPC_decoder_offload(&decParams, harq_pid, ULSCH_id, r, pusch_pdu->pusch_data.rv_index, harq_process->F, E, Qm, (int8_t *)&pl_ol128[0], llrProcBuf, 1); - if (ret < 0) { - LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); - - decodeIterations = ulsch->max_ldpc_iterations + 1; - return -1; - } - for (int m = 0; m < Kr >> 3; m++) { - harq_process->c[r][m] = (uint8_t)llrProcBuf[m]; - } - - if (check_crc((uint8_t *)llrProcBuf, length_dec, crc_type)) { - PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); - decodeIterations = 2; - } else { - PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); - decodeIterations = ulsch->max_ldpc_iterations + 1; - } - //} - - r_offset += E; - - /*for (int k=0;k<8;k++) - { - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - printf("llrprocbuf [%d] = %x adr %p\n", k, llrProcBuf[k], llrProcBuf+k); - } - */ - } else { - dtx_det = 0; - decodeIterations = ulsch->max_ldpc_iterations + 1; - } - bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations); - if (decodeSuccess) { - memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - harq_process->processedSegments++; - } else { - LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); - LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - break; // don't even attempt to decode other segments - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0); - - bool crc_valid = false; - if (harq_process->processedSegments == harq_process->C) { - // When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the - // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block - crc_valid = true; - if (harq_process->C > 1) { - // Check ULSCH transport block CRC - crc_type = CRC16; - if (A > 3824) { - crc_type = CRC24_A; - } - crc_valid = check_crc(harq_process->b, harq_process->B, crc_type); - } - } - - if (crc_valid) { - LOG_D(PHY, "[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB->Mod_id, ulsch->slot, harq_process->TBS); - ulsch->active = false; - harq_process->round = 0; - - LOG_D(PHY, "ULSCH received ok \n"); - nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); - - } else { - LOG_D(PHY, - "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", - phy_vars_gNB->Mod_id, - ulsch->frame, - ulsch->slot, - harq_pid, - ulsch->active, - harq_process->round, - harq_process->TBS); - ulsch->handled = 1; - decodeIterations = ulsch->max_ldpc_iterations + 1; - LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); - } - ulsch->last_iteration_cnt = decodeIterations; - } - - else { - dtx_det = 0; - set_abort(&harq_process->abort_decode, false); - for (int r = 0; r < harq_process->C; r++) { - int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); - union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}}; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment); - ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req); - decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round); - rdata->gNB = phy_vars_gNB; - rdata->ulsch_harq = harq_process; - rdata->decoderParms = decParams; - rdata->ulsch_llr = ulsch_llr; - rdata->Kc = kc; - rdata->harq_pid = harq_pid; - rdata->segment_r = r; - rdata->nbSegments = harq_process->C; - rdata->E = E; - rdata->A = A; - rdata->Qm = Qm; - rdata->r_offset = r_offset; - rdata->Kr_bytes = Kr_bytes; - rdata->rv_index = pusch_pdu->pusch_data.rv_index; - rdata->offset = offset; - rdata->ulsch = ulsch; - rdata->ulsch_id = ULSCH_id; - rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; - pushTpool(&phy_vars_gNB->threadPool, req); - LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); - r_offset += E; - offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); - ////////////////////////////////////////////////////////////////////////////////////////// - } + uint32_t offset = 0, r_offset = 0; + set_abort(&harq_process->abort_decode, false); + for (int r = 0; r < harq_process->C; r++) { + int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); + union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}}; + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment); + ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req); + decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, + E, + decParams.BG, + decParams.Z, + &harq_process->llrLen, + harq_process->round); + rdata->gNB = phy_vars_gNB; + rdata->ulsch_harq = harq_process; + rdata->decoderParms = decParams; + rdata->ulsch_llr = ulsch_llr; + rdata->Kc = decParams.BG == 2 ? 52 : 68; + rdata->harq_pid = harq_pid; + rdata->segment_r = r; + rdata->nbSegments = harq_process->C; + rdata->E = E; + rdata->A = A; + rdata->Qm = Qm; + rdata->r_offset = r_offset; + rdata->Kr_bytes = harq_process->K >> 3; + rdata->rv_index = pusch_pdu->pusch_data.rv_index; + rdata->offset = offset; + rdata->ulsch = ulsch; + rdata->ulsch_id = ULSCH_id; + rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; + pushTpool(&phy_vars_gNB->threadPool, req); + LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); + r_offset += E; + offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); } return harq_process->C; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 6f491ffafa..18aea849f7 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -11,11 +11,6 @@ #include #include "PHY/sse_intrin.h" -//#define DEBUG_CH_COMP -//#define DEBUG_RB_EXT -//#define DEBUG_CH_MAG -//#define ML_DEBUG - #define INVALID_VALUE 255 void nr_idft(int32_t *z, uint32_t Msc_PUSCH) @@ -281,109 +276,117 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) } +static void nr_ulsch_extract_rbs (c16_t* const rxdataF, + c16_t* const chF, + c16_t *rxFext, + c16_t *chFext, + int rxoffset, + int choffset, + int aarx, + int is_dmrs_symbol, + nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_DL_FRAME_PARMS *frame_parms) +{ + uint8_t delta = 0; -void nr_ulsch_extract_rbs(c16_t **rxdataF, - NR_gNB_PUSCH *pusch_vars, - int slot, - unsigned char symbol, - uint8_t is_dmrs_symbol, - nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_DL_FRAME_PARMS *frame_parms) { + int start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size; + int nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; - unsigned short start_re, re, nb_re_pusch; - unsigned char aarx, aatx; - uint32_t rxF_ext_index = 0; - uint32_t ul_ch0_ext_index = 0; - uint32_t ul_ch0_index = 0; - int16_t *rxF,*rxF_ext; - int *ul_ch0,*ul_ch0_ext; - int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; -#ifdef DEBUG_RB_EXT - printf("--------------------symbol = %d-----------------------\n", symbol); - printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size); -#endif + c16_t *rxF = &rxdataF[rxoffset]; + c16_t *rxF_ext = &rxFext[0]; + c16_t *ul_ch0 = &chF[choffset]; + c16_t *ul_ch0_ext = &chFext[0]; - uint8_t is_data_re; - start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size; - nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; - - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); - - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol * frame_parms->ofdm_symbol_size)]; - rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch2]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 - - if (is_dmrs_symbol == 0) { - if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) { - memcpy((void*)rxF_ext, (void*)&rxF[start_re*2], nb_re_pusch*sizeof(int32_t)); - } else { - int neg_length = frame_parms->ofdm_symbol_size-start_re; - int pos_length = nb_re_pusch-neg_length; - memcpy((void*)rxF_ext,(void*)&rxF[start_re*2],neg_length*sizeof(int32_t)); - memcpy((void*)&rxF_ext[2*neg_length],(void*)rxF,pos_length*sizeof(int32_t)); + if (is_dmrs_symbol == 0) { + if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size) + memcpy(rxF_ext, &rxF[start_re], nb_re_pusch * sizeof(c16_t)); + else + { + int neg_length = frame_parms->ofdm_symbol_size - start_re; + int pos_length = nb_re_pusch - neg_length; + memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(c16_t)); + memcpy(&rxF_ext[neg_length], rxF, pos_length * sizeof(c16_t)); + } + memcpy(ul_ch0_ext, ul_ch0, nb_re_pusch * sizeof(c16_t)); + } + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) // 6 REs / PRB + { + AssertFatal(delta == 0 || delta == 1, "Illegal delta %d\n",delta); + c16_t *rxF32 = &rxF[start_re]; + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { + for (int idx = 1 - delta; idx < nb_re_pusch; idx += 2) + { + *rxF_ext++ = rxF32[idx]; + *ul_ch0_ext++ = ul_ch0[idx]; } - - for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) { - ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2]; - memcpy((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t)); + } + else // handle the two pieces around DC + { + int neg_length = frame_parms->ofdm_symbol_size - start_re; + int pos_length = nb_re_pusch - neg_length; + int idx, idx2; + for (idx = 1 - delta; idx < neg_length; idx += 2) + { + *rxF_ext++ = rxF32[idx]; + *ul_ch0_ext++= ul_ch0[idx]; } - - } else { - - for (aatx = 0; aatx < pusch_pdu->nrOfLayers; aatx++) { - ul_ch0 = &pusch_vars->ul_ch_estimates[aatx*frame_parms->nb_antennas_rx+aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*nb_re_pusch2]; - - rxF_ext_index = 0; - ul_ch0_ext_index = 0; - ul_ch0_index = 0; - for (re = 0; re < nb_re_pusch; re++) { - uint16_t k = start_re + re; - is_data_re = allowed_xlsch_re_in_dmrs_symbol(k, start_re, frame_parms->ofdm_symbol_size, pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dmrs_config_type); - if (++k >= frame_parms->ofdm_symbol_size) { - k -= frame_parms->ofdm_symbol_size; - } - - #ifdef DEBUG_RB_EXT - printf("re = %d, is_dmrs_symbol = %d, symbol = %d\n", re, is_dmrs_symbol, symbol); - #endif - - // save only data and respective channel estimates - if (is_data_re == 1) { - if (aatx == 0) { - rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); - rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); - rxF_ext_index +=2; - } - - ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index]; - ul_ch0_ext_index++; - - #ifdef DEBUG_RB_EXT - printf("dmrs symb %d: rxF_ext[%u] = (%d,%d), ul_ch0_ext[%u] = (%d,%d)\n", - is_dmrs_symbol,rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1], - ul_ch0_ext_index, ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[0], ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[1]); - #endif - } - ul_ch0_index++; - } + rxF32 = rxF; + idx2 = idx; + for (idx = 1 - delta; idx < pos_length; idx += 2, idx2 += 2) + { + *rxF_ext++ = rxF32[idx]; + *ul_ch0_ext++ = ul_ch0[idx2]; + } + } + } + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2) // 8 REs / PRB + { + AssertFatal(delta==0||delta==2||delta==4,"Illegal delta %d\n",delta); + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) + { + for (int idx = 0; idx < nb_re_pusch; idx ++) + { + if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1) + continue; + *rxF_ext++ = rxF[idx]; + *ul_ch0_ext++ = ul_ch0[idx]; + } + } + else + { + int neg_length = frame_parms->ofdm_symbol_size - start_re; + int pos_length = nb_re_pusch - neg_length; + c16_t *rxF64 = &rxF[start_re]; + int idx, idx2; + for (idx = 0; idx < neg_length; idx ++) + { + if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1) + continue; + *rxF_ext++ = rxF64[idx]; + *ul_ch0_ext++ = ul_ch0[idx]; + } + rxF64 = rxF; + idx2 = idx; + for (idx = 0; idx < pos_length; idx++, idx2++) + { + if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1) + continue; + *rxF_ext++ = rxF64[idx]; + *ul_ch0_ext++ = ul_ch0[idx2]; } } } } -void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - NR_gNB_ULSCH_t *ulsch_gNB, - uint8_t symbol, - uint8_t is_dmrs_symbol, - uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb, - int shift_ch_ext) +static void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + uint8_t is_dmrs_symbol, + uint32_t len, + uint8_t nrOfLayers, + unsigned short nb_rb, + int shift_ch_ext) { // Determine scaling amplitude based the symbol int b = 3; @@ -400,60 +403,55 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, simde__m128i ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 LOG_D(PHY, "Scaling PUSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n", symbol, ch_amp, is_dmrs_symbol, nb_rb, frame_parms->Ncp, symbol); - uint32_t nb_rb_0 = len / 12 + ((len % 12) ? 1 : 0); - int off = ((nb_rb & 1) == 1) ? 4 : 0; for (int aatx = 0; aatx < nrOfLayers; aatx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * (off + (nb_rb * NR_NB_SC_PER_RB))]; - for (int rb = 0; rb < nb_rb_0; rb++) { - ul_ch128[0] = simde_mm_mulhi_epi16(ul_ch128[0], ch_amp128); - ul_ch128[0] = simde_mm_slli_epi16(ul_ch128[0], b); - - ul_ch128[1] = simde_mm_mulhi_epi16(ul_ch128[1], ch_amp128); - ul_ch128[1] = simde_mm_slli_epi16(ul_ch128[1], b); - - ul_ch128[2] = simde_mm_mulhi_epi16(ul_ch128[2], ch_amp128); - ul_ch128[2] = simde_mm_slli_epi16(ul_ch128[2], b); - ul_ch128 += 3; + simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len]; + for (int i = 0; i < len >> 2; i++) { + ul_ch128[i] = simde_mm_mulhi_epi16(ul_ch128[i], ch_amp128); + ul_ch128[i] = simde_mm_slli_epi16(ul_ch128[i], b); } } } } -//compute average channel_level on each (TX,RX) antenna pair -void nr_ulsch_channel_level(int **ul_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t symbol, - uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb) +static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol) { + uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + if (dmrs_symbol_flag == 1) { + if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) + AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); + if (rel15_ul->dmrs_config_type == 0) { + // if no data in dmrs cdm group is 1 only even REs have no data + // if no data in dmrs cdm group is 2 both odd and even REs have no data + return(rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6))); + } + else return(rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4))); + } else return(rel15_ul->rb_size * NR_NB_SC_PER_RB); +} - short rb; - unsigned char aatx, aarx; +// compute average channel_level on each (TX,RX) antenna pair +static void nr_ulsch_channel_level(int **ul_ch_estimates_ext, + NR_DL_FRAME_PARMS *frame_parms, + int32_t *avg, + uint8_t symbol, + uint32_t len, + uint8_t nrOfLayers) +{ simde__m128i *ul_ch128, avg128U; int16_t x = factor2(len); int16_t y = (len)>>x; - - uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); - int off = ((nb_rb&1) == 1)? 4:0; - - for (aatx = 0; aatx < nrOfLayers; aatx++) { - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + for (int aatx = 0; aatx < nrOfLayers; aatx++) { + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128U = simde_mm_setzero_si128(); - ul_ch128=(simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol * len]; - for (rb = 0; rb < nb_rb_0; rb++) { - avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[0], ul_ch128[0]), x)); - avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[1], ul_ch128[1]), x)); - avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[2], ul_ch128[2]), x)); - ul_ch128+=3; + for (int i = 0; i < len >> 2; i++) { + avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[i], ul_ch128[i]), x)); } avg[aatx*frame_parms->nb_antennas_rx+aarx] = (((int32_t*)&avg128U)[0] + @@ -465,298 +463,109 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, simde_mm_empty(); simde_m_empty(); - } -static simde__m128i a_mult_conjb(simde__m128i a, simde__m128i b, unsigned char output_shift) +static void nr_ulsch_channel_compensation(c16_t *rxFext, + c16_t *chFext, + c16_t *ul_ch_maga, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, + int32_t **rxComp, + c16_t *rho, + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t* rel15_ul, + uint32_t symbol, + uint32_t buffer_length, + uint32_t output_shift) { - simde__m128i mmtmpD0 = simde_mm_madd_epi16(b, a); - simde__m128i mmtmpD1 = simde_mm_shufflelo_epi16(b, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i *)&conjugate[0]); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, a); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); - simde__m128i mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); - simde__m128i mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - return simde_mm_packs_epi32(mmtmpD2, mmtmpD3); -} + int mod_order = rel15_ul->qam_mod_order; + int nrOfLayers = rel15_ul->nrOfLayers; + int nb_rx_ant = frame_parms->nb_antennas_rx; -//============================================================================================== -// Pre-processing for LLR computation -//============================================================================================== -void nr_ulsch_channel_compensation(int **rxdataF_ext, - int **ul_ch_estimates_ext, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int **rxdataF_comp, - int ***rho, - NR_DL_FRAME_PARMS *frame_parms, - unsigned char symbol, - int length, - uint8_t is_dmrs_symbol, - unsigned char mod_order, - uint8_t nrOfLayers, - unsigned short nb_rb, - unsigned char output_shift) { + simde__m256i QAM_ampa_256 = simde_mm256_setzero_si256(); + simde__m256i QAM_ampb_256 = simde_mm256_setzero_si256(); + simde__m256i QAM_ampc_256 = simde_mm256_setzero_si256(); - int off = ((nb_rb&1) == 1)? 4:0; + if (mod_order == 4) { + QAM_ampa_256 = simde_mm256_set1_epi16(QAM16_n1); + QAM_ampb_256 = simde_mm256_setzero_si256(); + QAM_ampc_256 = simde_mm256_setzero_si256(); + } + else if (mod_order == 6) { + QAM_ampa_256 = simde_mm256_set1_epi16(QAM64_n1); + QAM_ampb_256 = simde_mm256_set1_epi16(QAM64_n2); + QAM_ampc_256 = simde_mm256_setzero_si256(); + } + else if (mod_order == 8) { + QAM_ampa_256 = simde_mm256_set1_epi16(QAM256_n1); + QAM_ampb_256 = simde_mm256_set1_epi16(QAM256_n2); + QAM_ampc_256 = simde_mm256_set1_epi16(QAM256_n3); + } -#ifdef DEBUG_CH_COMP - int16_t *rxF, *ul_ch; - int prnt_idx; - for (int nl=0; nlnb_antennas_rx; aarx++) { - rxF = (int16_t *) &rxdataF_ext[aarx][symbol * (off + (nb_rb * 12))]; - ul_ch = (int16_t *) &ul_ch_estimates_ext[nl * frame_parms->nb_antennas_rx + aarx][symbol * (off + (nb_rb * 12))]; + simde__m256i xmmp0, xmmp1, xmmp2, xmmp3, xmmp4; + simde__m256i complex_shuffle256 = simde_mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + simde__m256i conj256 = simde_mm256_set_epi16(1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1); - printf("--------symbol = %d, mod_order = %d, output_shift = %d, layer %i, antenna rx = %d -----------\n", - symbol, mod_order, output_shift, nl, aarx); - printf("----------------Before compensation------------------\n"); + for (int aatx = 0; aatx < nrOfLayers; aatx++) { + simde__m256i *rxComp_256 = (simde__m256i*) &rxComp[aatx * nb_rx_ant][symbol * buffer_length]; + simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * buffer_length]; + simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * buffer_length]; + simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * buffer_length]; + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + simde__m256i *rxF_256 = (simde__m256i*) &rxFext[aarx * buffer_length]; + simde__m256i *chF_256 = (simde__m256i*) &chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; - for (prnt_idx = 0; prnt_idx < 12 * 5 * 2; prnt_idx += 2) { - printf("rxF[%d] = (%d,%d)\n", prnt_idx >> 1, rxF[prnt_idx], rxF[prnt_idx + 1]); - printf("ul_ch[%d] = (%d,%d)\n", prnt_idx >> 1, ul_ch[prnt_idx], ul_ch[prnt_idx + 1]); + for (int i = 0; i < buffer_length >> 3; i++) + { + xmmp0 = simde_mm256_madd_epi16(chF_256[i], rxF_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, rxF_256[i]); + // xmmp1 contains imag part of 4 consecutive outputs (32-bit) of conj(H_m[i])*R_m[i] + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); + xmmp4 = simde_mm256_packs_epi32(xmmp2, xmmp3); + + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF_256[i]); // |h|^2 + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp0 = simde_mm256_packs_epi32(xmmp0, xmmp0); + xmmp1 = simde_mm256_unpacklo_epi16(xmmp0, xmmp0); + + xmmp2 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampa_256); + xmmp3 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampb_256); + xmmp1 = simde_mm256_mulhrs_epi16(xmmp1, QAM_ampc_256); + + // MRC + rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], xmmp4); + if (mod_order > 2) + rxF_ch_maga_256[i] = simde_mm256_add_epi16(rxF_ch_maga_256[i], xmmp2); + if (mod_order > 4) + rxF_ch_magb_256[i] = simde_mm256_add_epi16(rxF_ch_magb_256[i], xmmp3); + if (mod_order > 6) + rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], xmmp1); } - } - } -#endif - -#ifdef DEBUG_CH_MAG - int16_t *ch_mag; - int print_idx; - - - for (int ant=0; antnb_antennas_rx; ant++) { - ch_mag = (int16_t *)&ul_ch_mag[ant][symbol*(off+(nb_rb*12))]; - - printf("--------------------symbol = %d, mod_order = %d-----------------------\n", symbol, mod_order); - printf("----------------Before computation------------------\n"); - - for (print_idx=0;print_idx<5;print_idx++){ - - printf("ch_mag[%d] = %d\n", print_idx, ch_mag[print_idx]); - - } - } - -#endif - - - unsigned short rb; - unsigned char aatx,aarx; - simde__m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*ul_ch_mag128c,*rxdataF128,*rxdataF_comp128,*rho128; - simde__m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128c={0}; - QAM_amp128b = simde_mm_setzero_si128(); - - uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); - for (aatx=0; aatxnb_antennas_rx; aarx++) { - ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128 = (simde__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128b = (simde__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128c = (simde__m128i *)&ul_ch_magc[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - rxdataF128 = (simde__m128i *)&rxdataF_ext[aarx][symbol*(off+(nb_rb*12))]; - rxdataF_comp128 = (simde__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - - - for (rb=0; rb2) { - // get channel amplitude if not QPSK - - //print_shorts("ch:",(int16_t*)&ul_ch128[0]); - - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[0],ul_ch128[0]); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - - mmtmpD1 = simde_mm_madd_epi16(ul_ch128[1],ul_ch128[1]); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - - mmtmpD0 = simde_mm_packs_epi32(mmtmpD0,mmtmpD1); - - // store channel magnitude here in a new field of ulsch - - ul_ch_mag128[0] = simde_mm_unpacklo_epi16(mmtmpD0,mmtmpD0); - ul_ch_mag128b[0] = ul_ch_mag128[0]; - ul_ch_mag128c[0] = ul_ch_mag128[0]; - ul_ch_mag128[0] = simde_mm_mulhrs_epi16(ul_ch_mag128[0],QAM_amp128); - ul_ch_mag128b[0] = simde_mm_mulhrs_epi16(ul_ch_mag128b[0],QAM_amp128b); - ul_ch_mag128c[0] = simde_mm_mulhrs_epi16(ul_ch_mag128c[0],QAM_amp128c); - // print_ints("ch: = ",(int32_t*)&mmtmpD0); - // print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); - // print_shorts("mag:",(int16_t*)&ul_ch_mag128[0]); - - ul_ch_mag128[1] = simde_mm_unpackhi_epi16(mmtmpD0,mmtmpD0); - ul_ch_mag128b[1] = ul_ch_mag128[1]; - ul_ch_mag128c[1] = ul_ch_mag128[1]; - ul_ch_mag128[1] = simde_mm_mulhrs_epi16(ul_ch_mag128[1],QAM_amp128); - ul_ch_mag128b[1] = simde_mm_mulhrs_epi16(ul_ch_mag128b[1],QAM_amp128b); - ul_ch_mag128c[1] = simde_mm_mulhrs_epi16(ul_ch_mag128c[1],QAM_amp128c); - - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[2],ul_ch128[2]); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_packs_epi32(mmtmpD0,mmtmpD0); - - ul_ch_mag128[2] = simde_mm_unpacklo_epi16(mmtmpD1,mmtmpD1); - ul_ch_mag128b[2] = ul_ch_mag128[2]; - ul_ch_mag128c[2] = ul_ch_mag128[2]; - - ul_ch_mag128[2] = simde_mm_mulhrs_epi16(ul_ch_mag128[2],QAM_amp128); - ul_ch_mag128b[2] = simde_mm_mulhrs_epi16(ul_ch_mag128b[2],QAM_amp128b); - ul_ch_mag128c[2] = simde_mm_mulhrs_epi16(ul_ch_mag128c[2],QAM_amp128c); - } - - // Multiply received data by conjugated channel - rxdataF_comp128[0] = a_mult_conjb(rxdataF128[0], ul_ch128[0], output_shift); - rxdataF_comp128[1] = a_mult_conjb(rxdataF128[1], ul_ch128[1], output_shift); - rxdataF_comp128[2] = a_mult_conjb(rxdataF128[2], ul_ch128[2], output_shift); - - ul_ch128 += 3; - ul_ch_mag128 += 3; - ul_ch_mag128b += 3; - ul_ch_mag128c += 3; - rxdataF128 += 3; - rxdataF_comp128 += 3; - } - } - } - - if (rho) { - //we compute the Tx correlation matrix for each Rx antenna - //As an example the 2x2 MIMO case requires - //rho[aarx][nb_aatx*nb_aatx] = [cov(H_aarx_0,H_aarx_0) cov(H_aarx_0,H_aarx_1) - // cov(H_aarx_1,H_aarx_0) cov(H_aarx_1,H_aarx_1)], aarx=0,...,nb_antennas_rx-1 - - int avg_rho_re[frame_parms->nb_antennas_rx][nrOfLayers*nrOfLayers]; - int avg_rho_im[frame_parms->nb_antennas_rx][nrOfLayers*nrOfLayers]; - - for (aarx=0; aarx < frame_parms->nb_antennas_rx; aarx++) { - for (aatx=0; aatx < nrOfLayers; aatx++) { - for (int atx=0; atx< nrOfLayers; atx++) { - - avg_rho_re[aarx][aatx*nrOfLayers+atx] = 0; - avg_rho_im[aarx][aatx*nrOfLayers+atx] = 0; - rho128 = (simde__m128i *)&rho[aarx][aatx*nrOfLayers+atx][symbol*(off+(nb_rb*12))]; - ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - ul_ch128_2 = (simde__m128i *)&ul_ch_estimates_ext[atx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; - - for (rb=0; rb> 3; i++) { // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[0],ul_ch128_2[0]); - // print_ints("re",&mmtmpD0); + xmmp0 = simde_mm256_madd_epi16(chF_256[i], chF2_256[i]); + // xmmp0 contains real part of 4 consecutive outputs (32-bit) + xmmp1 = simde_mm256_shuffle_epi8(chF_256[i], complex_shuffle256); + xmmp1 = simde_mm256_sign_epi16(xmmp1, conj256); + xmmp1 = simde_mm256_madd_epi16(xmmp1, chF2_256[i]); + // xmmp0 contains imag part of 4 consecutive outputs (32-bit) + xmmp0 = simde_mm256_srai_epi32(xmmp0, output_shift); + xmmp1 = simde_mm256_srai_epi32(xmmp1, output_shift); + xmmp2 = simde_mm256_unpacklo_epi32(xmmp0, xmmp1); + xmmp3 = simde_mm256_unpackhi_epi32(xmmp0, xmmp1); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[0], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)&conjugate[0]); - // print_ints("im",&mmtmpD1); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,ul_ch128_2[0]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - // print_ints("re(shift)",&mmtmpD0); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - // print_ints("im(shift)",&mmtmpD1); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - // print_ints("c0",&mmtmpD2); - // print_ints("c1",&mmtmpD3); - rho128[0] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); - - //print_shorts("rx:",ul_ch128_2); - //print_shorts("ch:",ul_ch128); - //print_shorts("pack:",rho128); - - avg_rho_re[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[0])[0]+ - ((int16_t*)&rho128[0])[2] + - ((int16_t*)&rho128[0])[4] + - ((int16_t*)&rho128[0])[6])/16;// - - avg_rho_im[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[0])[1]+ - ((int16_t*)&rho128[0])[3] + - ((int16_t*)&rho128[0])[5] + - ((int16_t*)&rho128[0])[7])/16;// - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[1],ul_ch128_2[1]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[1], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)conjugate); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,ul_ch128_2[1]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - rho128[1] =simde_mm_packs_epi32(mmtmpD2,mmtmpD3); - //print_shorts("rx:",ul_ch128_2+1); - //print_shorts("ch:",ul_ch128+1); - //print_shorts("pack:",rho128+1); - - // multiply by conjugated channel - avg_rho_re[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[1])[0]+ - ((int16_t*)&rho128[1])[2] + - ((int16_t*)&rho128[1])[4] + - ((int16_t*)&rho128[1])[6])/16; - - avg_rho_im[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[1])[1]+ - ((int16_t*)&rho128[1])[3] + - ((int16_t*)&rho128[1])[5] + - ((int16_t*)&rho128[1])[7])/16; - - mmtmpD0 = simde_mm_madd_epi16(ul_ch128[2],ul_ch128_2[2]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(ul_ch128[2], SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)conjugate); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,ul_ch128_2[2]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - - rho128[2] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); - //print_shorts("rx:",ul_ch128_2+2); - //print_shorts("ch:",ul_ch128+2); - //print_shorts("pack:",rho128+2); - avg_rho_re[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[2])[0]+ - ((int16_t*)&rho128[2])[2] + - ((int16_t*)&rho128[2])[4] + - ((int16_t*)&rho128[2])[6])/16; - - avg_rho_im[aarx][aatx*nrOfLayers+atx] +=(((int16_t*)&rho128[2])[1]+ - ((int16_t*)&rho128[2])[3] + - ((int16_t*)&rho128[2])[5] + - ((int16_t*)&rho128[2])[7])/16; - - ul_ch128+=3; - ul_ch128_2+=3; - rho128+=3; - } - if (is_dmrs_symbol==1) { - //measurements->rx_correlation[0][0][aarx] = signal_energy(&rho[aarx][aatx*nb_aatx+atx][symbol*nb_rb*12],rb*12); - avg_rho_re[aarx][aatx*nrOfLayers+atx] = 16*avg_rho_re[aarx][aatx*nrOfLayers+atx]/(nb_rb*12); - avg_rho_im[aarx][aatx*nrOfLayers+atx] = 16*avg_rho_im[aarx][aatx*nrOfLayers+atx]/(nb_rb*12); - //printf("rho[rx]%d tx%d tx%d = Re: %d Im: %d\n",aarx, aatx,atx, avg_rho_re[aarx][aatx*nb_aatx+atx], avg_rho_im[aarx][aatx*nb_aatx+atx]); + rho_256[i] = simde_mm256_adds_epi16(rho_256[i], simde_mm256_packs_epi32(xmmp2, xmmp3)); } } } @@ -765,114 +574,17 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, simde_mm_empty(); simde_m_empty(); - - -#ifdef DEBUG_CH_COMP - for (int nl2=0; nl2nb_antennas_rx; aarx2++) { - rxF = (int16_t *)&rxdataF_comp[nl2*frame_parms->nb_antennas_rx+aarx2][(symbol*(off+(nb_rb*12)))]; - - printf("--------After compansation, layer %i, antenna rx %i----------\n", nl2, aarx2); - - for (prnt_idx=0;prnt_idx<12*5*2;prnt_idx+=2){ - printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]); - } - } - } -#endif - -#ifdef DEBUG_CH_MAG - - - for (int ant=0; antnb_antennas_rx; ant++) { - ch_mag = (int16_t *)&ul_ch_mag[ant][(symbol*(off+(nb_rb*12)))]; - - printf("----------------After computation------------------\n"); - - for (print_idx=0;print_idx<12*5*2;print_idx+=2){ - - printf("ch_mag[%d] = (%d,%d)\n", print_idx>>1, ch_mag[print_idx],ch_mag[print_idx+1]); - - } - } - -#endif - } -void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, - int32_t **ul_ch_mag, - int32_t **ul_ch_magb, - int32_t **ul_ch_magc, - int32_t ***rho, - uint8_t nrOfLayers, - uint8_t symbol, - uint16_t nb_rb, - int length) { - int n_rx = frame_parms->nb_antennas_rx; - simde__m128i *rxdataF_comp128[2],*ul_ch_mag128[2],*ul_ch_mag128b[2],*ul_ch_mag128c[2]; - int32_t i; - uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); - - int off = ((nb_rb&1) == 1)? 4:0; - - if (n_rx > 1) { - - int nb_re = nb_rb * 12; - - for (int aatx = 0; aatx < nrOfLayers; aatx++) { - - rxdataF_comp128[0] = (simde__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - ul_ch_mag128[0] = (simde__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - ul_ch_mag128b[0] = (simde__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - ul_ch_mag128c[0] = (simde__m128i *)&ul_ch_magc[aatx*frame_parms->nb_antennas_rx][(symbol*(nb_re + off))]; - - for (int aa=1;aa < n_rx;aa++) { - rxdataF_comp128[1] = (simde__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - ul_ch_mag128[1] = (simde__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - ul_ch_mag128b[1] = (simde__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aa][(symbol*(nb_re + off))]; - ul_ch_mag128c[1] = (simde__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; i 2) { if (mod_order == 4) { @@ -1487,16 +1160,16 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, QAM_amp128b = simde_mm_set1_epi16(QAM64_n2); // 2/sqrt{42} QAM_amp128c = simde_mm_setzero_si128(); } else if (mod_order == 8) { - QAM_amp128 = simde_mm_set1_epi16(QAM256_n1); + QAM_amp128 = simde_mm_set1_epi16(QAM256_n1); QAM_amp128b = simde_mm_set1_epi16(QAM256_n2); QAM_amp128c = simde_mm_set1_epi16(QAM256_n3); } - ul_ch_mag128_0 = (simde__m128i *)&ul_ch_mag[0][symbol * (off + nb_rb * 12)]; - ul_ch_mag128b_0 = (simde__m128i *)&ul_ch_magb[0][symbol * (off + nb_rb * 12)]; - ul_ch_mag128c_0 = (simde__m128i *)&ul_ch_magc[0][symbol * (off + nb_rb * 12)]; - ul_ch_mag128_1 = (simde__m128i *)&ul_ch_mag[frame_parms->nb_antennas_rx][symbol * (off + nb_rb * 12)]; - ul_ch_mag128b_1 = (simde__m128i *)&ul_ch_magb[frame_parms->nb_antennas_rx][symbol * (off + nb_rb * 12)]; - ul_ch_mag128c_1 = (simde__m128i *)&ul_ch_magc[frame_parms->nb_antennas_rx][symbol * (off + nb_rb * 12)]; + ul_ch_mag128_0 = (simde__m128i *) &ul_ch_mag[0]; + ul_ch_mag128b_0 = (simde__m128i *)&ul_ch_magb[0]; + ul_ch_mag128c_0 = (simde__m128i *)&ul_ch_magc[0]; + ul_ch_mag128_1 = (simde__m128i *) &((int *)ul_ch_mag)[1 * buffer_length]; + ul_ch_mag128b_1 = (simde__m128i *)&((int *)ul_ch_magb)[1 * buffer_length]; + ul_ch_mag128c_1 = (simde__m128i *)&((int *)ul_ch_magc)[1 * buffer_length]; } for (int rb = 0; rb < 3 * nb_rb_0; rb++) { @@ -1586,38 +1259,212 @@ uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, return(0); } -//============================================================================================== - -/* Main Function */ -void nr_rx_pusch(PHY_VARS_gNB *gNB, - uint8_t ulsch_id, - uint32_t frame, - uint8_t slot, - unsigned char harq_pid) +static void inner_rx (PHY_VARS_gNB *gNB, + int ulsch_id, + int slot, + NR_DL_FRAME_PARMS *frame_parms, + NR_gNB_PUSCH *pusch_vars, + nfapi_nr_pusch_pdu_t *rel15_ul, + c16_t **rxF, + c16_t **ul_ch, + int16_t **llr, + int soffset, + int length, + int symbol, + int output_shift, + uint32_t nvar) { + int nb_layer = rel15_ul->nrOfLayers; + int nb_rx_ant = frame_parms->nb_antennas_rx; + int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + int buffer_length = (rel15_ul->rb_size * NR_NB_SC_PER_RB + 7) & ~7; + c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32))); + c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32))); - uint8_t aarx, aatx; - uint32_t nb_re_pusch, bwp_start_subcarrier; - int avgs = 0; + memset(rxFext, 0, sizeof(c16_t) * nb_rx_ant * buffer_length); + memset(chFext, 0, sizeof(c16_t) * nb_layer * nb_rx_ant* buffer_length); + + for (int aarx = 0; aarx < nb_rx_ant; aarx++) { + for (int aatx = 0; aatx < nb_layer; aatx++) { + nr_ulsch_extract_rbs(rxF[aarx], + (c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx], + rxFext[aarx], + chFext[aatx][aarx], + soffset+(symbol * frame_parms->ofdm_symbol_size), + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + dmrs_symbol_flag, + rel15_ul, + frame_parms); + } + } + c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(32))); + c16_t rxF_ch_maga [nb_layer][buffer_length] __attribute__((aligned(32))); + c16_t rxF_ch_magb [nb_layer][buffer_length] __attribute__((aligned(32))); + c16_t rxF_ch_magc [nb_layer][buffer_length] __attribute__((aligned(32))); + + memset(rho, 0, sizeof(c16_t) * nb_layer * nb_layer* buffer_length); + memset(rxF_ch_maga, 0, sizeof(c16_t) * nb_layer * buffer_length); + memset(rxF_ch_magb, 0, sizeof(c16_t) * nb_layer * buffer_length); + memset(rxF_ch_magc, 0, sizeof(c16_t) * nb_layer * buffer_length); + for (int i = 0; i < nb_layer; i++) + memset(&pusch_vars->rxdataF_comp[i*nb_rx_ant][symbol * buffer_length], 0, sizeof(int32_t) * buffer_length); + + nr_ulsch_channel_compensation((c16_t*)rxFext, + (c16_t*)chFext, + (c16_t*)rxF_ch_maga, + (c16_t*)rxF_ch_magb, + (c16_t*)rxF_ch_magc, + pusch_vars->rxdataF_comp, + (nb_layer == 1) ? NULL : (c16_t*)rho, + frame_parms, + rel15_ul, + symbol, + buffer_length, + output_shift); + + if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { + if (rel15_ul->qam_mod_order > 2) + nr_freq_equalization(frame_parms, + &pusch_vars->rxdataF_comp[0][symbol * buffer_length], + (int *)rxF_ch_maga, + (int *)rxF_ch_magb, + symbol, + pusch_vars->ul_valid_re_per_slot[symbol], + rel15_ul->qam_mod_order); + nr_idft(&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]); + } + if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + nr_pusch_ptrs_processing(gNB, + frame_parms, + rel15_ul, + ulsch_id, + slot, + symbol, + buffer_length); + pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot; + } + + if (nb_layer == 2) { + if (rel15_ul->qam_mod_order < 6) { + nr_ulsch_compute_ML_llr(pusch_vars, + symbol, + (c16_t*)&pusch_vars->rxdataF_comp[0][symbol * buffer_length], + (c16_t*)&pusch_vars->rxdataF_comp[nb_rx_ant][symbol * buffer_length], + rxF_ch_maga[0], + rxF_ch_maga[1], + (c16_t*)&llr[0][pusch_vars->llr_offset[symbol]], + (c16_t*)&llr[1][pusch_vars->llr_offset[symbol]], + rho[0][1], + rho[1][0], + pusch_vars->ul_valid_re_per_slot[symbol], + rel15_ul->qam_mod_order); + } + else { + nr_ulsch_mmse_2layers(frame_parms, + (int32_t **)pusch_vars->rxdataF_comp, + (int **)rxF_ch_maga, + (int **)rxF_ch_magb, + (int **)rxF_ch_magc, + (int **)chFext, + rel15_ul->rb_size, + frame_parms->nb_antennas_rx, + rel15_ul->qam_mod_order, + pusch_vars->log2_maxh, + symbol, + pusch_vars->ul_valid_re_per_slot[symbol], + nvar, + buffer_length); + } + } + if (nb_layer != 2 || rel15_ul->qam_mod_order >= 6) + for (int aatx = 0; aatx < nb_layer; aatx++) + nr_ulsch_compute_llr((int32_t*)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * buffer_length], + (int32_t*)rxF_ch_maga[aatx], + (int32_t*)rxF_ch_magb[aatx], + (int32_t*)rxF_ch_magc[aatx], + &llr[aatx][pusch_vars->llr_offset[symbol]], + pusch_vars->ul_valid_re_per_slot[symbol], + symbol, + rel15_ul->qam_mod_order); +} + +static void nr_pusch_symbol_processing(void *arg) +{ + puschSymbolProc_t *rdata=(puschSymbolProc_t*)arg; + + PHY_VARS_gNB *gNB = rdata->gNB; + NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; + nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; + int ulsch_id = rdata->ulsch_id; + int slot = rdata->slot; + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; + for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) { + int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + if (dmrs_symbol_flag == 1) + { + if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) + AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); + gNB->pusch_vars[ulsch_id].dmrs_symbol = symbol; + } + + if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0) + continue; + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + inner_rx(gNB, + ulsch_id, + slot, + frame_parms, + pusch_vars, + rel15_ul, + gNB->common_vars.rxdataF, + (c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates, + rdata->llr_layers, + soffset, + gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol], + symbol, + gNB->pusch_vars[ulsch_id].log2_maxh, + rdata->nvar); + + int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; + // layer de-mapping + int16_t* llr_ptr = &rdata->llr_layers[0][pusch_vars->llr_offset[symbol]]; + if (rel15_ul->nrOfLayers != 1) { + llr_ptr = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch); i++) + for (int l = 0; l < rel15_ul->nrOfLayers; l++) + for (int m = 0; m < rel15_ul->qam_mod_order; m++) + llr_ptr[i*rel15_ul->nrOfLayers*rel15_ul->qam_mod_order+l*rel15_ul->qam_mod_order+m] = rdata->llr_layers[l][pusch_vars->llr_offset[symbol] + i*rel15_ul->qam_mod_order+m]; + } + // unscrambling + int16_t *llr16 = (int16_t*)&rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers]; + for (int i = 0; i < (nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers); i++) + llr16[i] = llr_ptr[i] * rdata->s[i]; + } +} + + +int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, + uint8_t ulsch_id, + uint32_t frame, + uint8_t slot, + unsigned char harq_pid) +{ + uint8_t aarx; + uint32_t bwp_start_subcarrier; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ulsch_id]; - nfapi_nr_pusch_pdu_t *rel15_ul = &ulsch->harq_process->ulsch_pdu; - int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; + nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id].harq_process->ulsch_pdu; NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; pusch_vars->dmrs_symbol = INVALID_VALUE; - pusch_vars->cl_done = 0; - + gNB->nbSymb=0; bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos); - LOG_D(PHY,"ulsch RX %x : start_rb %d nb_rb %d mcs %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_ports %d\n", - rel15_ul->rnti,rel15_ul->rb_start,rel15_ul->rb_size,rel15_ul->mcs_index, - rel15_ul->nrOfLayers,0,rel15_ul->bwp_start,0,rel15_ul->start_symbol_index,rel15_ul->nr_of_symbols, - rel15_ul->num_dmrs_cdm_grps_no_data,rel15_ul->ul_dmrs_symb_pos,rel15_ul->dmrs_ports); + //---------------------------------------------------------- - //--------------------- Channel estimation --------------------- + //------------------- Channel estimation ------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_channel_estimation_stats); int max_ch = 0; @@ -1643,279 +1490,199 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, &nvar_tmp); nvar += nvar_tmp; } - - nr_gnb_measurements(gNB, ulsch, pusch_vars, symbol, rel15_ul->nrOfLayers); + // measure the SNR from the channel estimation + nr_gnb_measurements(gNB, + &gNB->ulsch[ulsch_id], + pusch_vars, + symbol, + rel15_ul->nrOfLayers); allocCast2D(n0_subband_power, unsigned int, gNB->measurements.n0_subband_power, frame_parms->nb_antennas_rx, frame_parms->N_RB_UL, false); - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - if (symbol == rel15_ul->start_symbol_index) { + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + { + if (symbol == rel15_ul->start_symbol_index) + { pusch_vars->ulsch_power[aarx] = 0; pusch_vars->ulsch_noise_power[aarx] = 0; } - for (aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) { + for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) { pusch_vars->ulsch_power[aarx] += signal_energy_nodc( &pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size], rel15_ul->rb_size * 12); } - for (int rb = 0; rb < rel15_ul->rb_size; rb++) { - pusch_vars->ulsch_noise_power[aarx] += - n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size; - } - LOG_D(PHY, - "aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n", - aarx, - rel15_ul->bwp_start, - rel15_ul->rb_start, - rel15_ul->rb_size, - pusch_vars->ulsch_power[aarx], - pusch_vars->ulsch_noise_power[aarx]); + for (int rb = 0; rb < rel15_ul->rb_size; rb++) + pusch_vars->ulsch_noise_power[aarx] += + n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size; } } } nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx); - if (gNB->chest_time == 1) { // averaging time domain channel estimates + // averaging time domain channel estimates + if (gNB->chest_time == 1) + { nr_chest_time_domain_avg(frame_parms, pusch_vars->ul_ch_estimates, rel15_ul->nr_of_symbols, rel15_ul->start_symbol_index, rel15_ul->ul_dmrs_symb_pos, rel15_ul->rb_size); - - pusch_vars->dmrs_symbol = - get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols); + pusch_vars->dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, + rel15_ul->start_symbol_index, + rel15_ul->nr_of_symbols); } + stop_meas(&gNB->ulsch_channel_estimation_stats); - int off = ((rel15_ul->rb_size&1) == 1)? 4:0; - uint32_t rxdataF_ext_offset = 0; + start_meas(&gNB->rx_pusch_init_stats); + + // Scrambling initialization + int number_dmrs_symbols = 0; + for (int l = rel15_ul->start_symbol_index; l < rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; l++) + number_dmrs_symbols += ((rel15_ul->ul_dmrs_symb_pos)>>l) & 0x01; + int nb_re_dmrs; + if (rel15_ul->dmrs_config_type == pusch_dmrs_type1) + nb_re_dmrs = 6*rel15_ul->num_dmrs_cdm_grps_no_data; + else + nb_re_dmrs = 4*rel15_ul->num_dmrs_cdm_grps_no_data; + + // get how many bit in a slot // + int G = nr_get_G(rel15_ul->rb_size, + rel15_ul->nr_of_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + rel15_ul->qam_mod_order, + rel15_ul->nrOfLayers); + // initialize scrambling sequence // + int16_t s[G+96] __attribute__((aligned(32))); + + nr_codeword_unscrambling_init(s, G, 0, rel15_ul->data_scrambling_id, rel15_ul->rnti); + + // first the computation of channel levels + + int nb_re_pusch = 0, meas_symbol = -1; + for(meas_symbol = rel15_ul->start_symbol_index; + meas_symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); + meas_symbol++) + if ((nb_re_pusch = get_nb_re_pusch(frame_parms,rel15_ul,meas_symbol)) > 0) + break; + + AssertFatal(nb_re_pusch>0 && meas_symbol>=0,"nb_re_pusch %d cannot be 0 or meas_symbol %d cannot be negative here\n",nb_re_pusch,meas_symbol); + + // extract the first dmrs for the channel level computation + // extract the data in the OFDM frame, to the start of the array + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + + if (nb_re_pusch & 7) + nb_re_pusch += 8 - (nb_re_pusch & 7); + + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) + nr_ulsch_extract_rbs(gNB->common_vars.rxdataF[aarx], + (c16_t *)pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx], + (c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch], + (c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][meas_symbol * nb_re_pusch], + soffset + meas_symbol * frame_parms->ofdm_symbol_size, + pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size, + aarx, + (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, + rel15_ul, + frame_parms); + + int avgs = 0; + int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; 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; - } + //---------------------------------------------------------- + //--------------------- Channel Scaling -------------------- + //---------------------------------------------------------- + nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext, + frame_parms, + meas_symbol, + (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, + nb_re_pusch, + rel15_ul->nrOfLayers, + rel15_ul->rb_size, + shift_ch_ext); + + nr_ulsch_channel_level(pusch_vars->ul_ch_estimates_ext, + frame_parms, + avg, + meas_symbol, // index of the start symbol + nb_re_pusch, // number of the re in pusch + rel15_ul->nrOfLayers); - int ad_shift = 0; - if (rel15_ul->nrOfLayers == 1) { - ad_shift = 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); - } 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 (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + avgs = cmax(avgs, avg[aatx*frame_parms->nb_antennas_rx+aarx]); + + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1); - int num_re_total = 0; - for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { - uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - if (dmrs_symbol_flag == 1) { - if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) - AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); + if (rel15_ul->nrOfLayers == 2 && rel15_ul->qam_mod_order >= 6) + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) - 3; // for MMSE + else if (rel15_ul->nrOfLayers == 1) + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + 1 + log2_approx(frame_parms->nb_antennas_rx >> 2); + + if (pusch_vars->log2_maxh < 0) + pusch_vars->log2_maxh = 0; - if (gNB->chest_time == 0) // Non averaging time domain channel estimates - pusch_vars->dmrs_symbol = symbol; + stop_meas(&gNB->rx_pusch_init_stats); - if (rel15_ul->dmrs_config_type == 0) { - // if no data in dmrs cdm group is 1 only even REs have no data - // if no data in dmrs cdm group is 2 both odd and even REs have no data - nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6)); - } - else { - nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)); - } - } - else { - nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; + start_meas(&gNB->rx_pusch_symbol_processing_stats); + int numSymbols = gNB->num_pusch_symbols_per_thread; + + for(uint8_t symbol = rel15_ul->start_symbol_index; + symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); + symbol += numSymbols) + { + int total_res = 0; + for (int s = 0; s < numSymbols;s++) { + pusch_vars->ul_valid_re_per_slot[symbol+s] = get_nb_re_pusch(frame_parms,rel15_ul,symbol+s); + pusch_vars->llr_offset[symbol+s] = ((symbol+s) == rel15_ul->start_symbol_index) ? + 0 : + pusch_vars->llr_offset[symbol+s-1] + pusch_vars->ul_valid_re_per_slot[symbol+s-1] * rel15_ul->qam_mod_order; + total_res+=pusch_vars->ul_valid_re_per_slot[symbol+s]; } + if (total_res > 0) { + union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}}; + id.p=1+symbol; + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing); // create a job for Tpool + puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job - num_re_total += nb_re_pusch; - pusch_vars->ul_valid_re_per_slot[symbol] = nb_re_pusch; - LOG_D(PHY, "symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, pusch_vars->dmrs_symbol); + rdata->gNB = gNB; + rdata->frame_parms = frame_parms; + rdata->rel15_ul = rel15_ul; + rdata->slot = slot; + rdata->startSymbol = symbol; + rdata->numSymbols = numSymbols; + rdata->ulsch_id = ulsch_id; + rdata->llr = pusch_vars->llr; + rdata->llr_layers = pusch_vars->llr_layers; + rdata->s = &s[pusch_vars->llr_offset[symbol]*rel15_ul->nrOfLayers]; + rdata->nvar = nvar; - //---------------------------------------------------------- - //--------------------- RBs extraction --------------------- - //---------------------------------------------------------- - if (nb_re_pusch > 0) { - start_meas(&gNB->ulsch_rbs_extraction_stats); - nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, rel15_ul, frame_parms); - stop_meas(&gNB->ulsch_rbs_extraction_stats); - - //---------------------------------------------------------- - //--------------------- Channel Scaling -------------------- - //---------------------------------------------------------- - nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext, - frame_parms, - ulsch, - symbol, - dmrs_symbol_flag, - nb_re_pusch, - rel15_ul->nrOfLayers, - rel15_ul->rb_size, - shift_ch_ext); - - if (pusch_vars->cl_done == 0) { - nr_ulsch_channel_level(pusch_vars->ul_ch_estimates_ext, - frame_parms, - avg, - symbol, - nb_re_pusch, - rel15_ul->nrOfLayers, - rel15_ul->rb_size); - - avgs = 0; - - for (aatx=0;aatxnrOfLayers;aatx++) - for (aarx=0;aarxnb_antennas_rx;aarx++) - avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]); - - pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + ad_shift; - if (pusch_vars->log2_maxh < 0) { - pusch_vars->log2_maxh = 0; - } - pusch_vars->cl_done = 1; - } - - //---------------------------------------------------------- - //--------------------- Channel Compensation --------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_channel_compensation_stats); - LOG_D(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n" ,pusch_vars->log2_maxh, avgs,avg[0], avg[1]); - nr_ulsch_channel_compensation(pusch_vars->rxdataF_ext, - pusch_vars->ul_ch_estimates_ext, - pusch_vars->ul_ch_mag0, - pusch_vars->ul_ch_magb0, - pusch_vars->ul_ch_magc0, - pusch_vars->rxdataF_comp, - (rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL, - frame_parms, - symbol, - nb_re_pusch, - dmrs_symbol_flag, - rel15_ul->qam_mod_order, - rel15_ul->nrOfLayers, - rel15_ul->rb_size, - pusch_vars->log2_maxh); - stop_meas(&gNB->ulsch_channel_compensation_stats); - - start_meas(&gNB->ulsch_mrc_stats); - nr_ulsch_detection_mrc(frame_parms, - pusch_vars->rxdataF_comp, - pusch_vars->ul_ch_mag0, - pusch_vars->ul_ch_magb0, - pusch_vars->ul_ch_magc0, - (rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL, - rel15_ul->nrOfLayers, - symbol, - rel15_ul->rb_size, - nb_re_pusch); - - // Apply MMSE for 2 Tx layers - if (ml_rx == false && rel15_ul->nrOfLayers == 2) { - nr_ulsch_mmse_2layers(frame_parms, - pusch_vars->rxdataF_comp, - pusch_vars->ul_ch_mag0, - pusch_vars->ul_ch_magb0, - pusch_vars->ul_ch_magc0, - pusch_vars->ul_ch_estimates_ext, - rel15_ul->rb_size, - frame_parms->nb_antennas_rx, - rel15_ul->qam_mod_order, - pusch_vars->log2_maxh, - symbol, - nb_re_pusch, - nvar); - } - - stop_meas(&gNB->ulsch_mrc_stats); - - if (rel15_ul->transform_precoding == transformPrecoder_enabled) { - // For odd number of resource blocks need byte alignment to multiple of 8 - int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); - - // perform IDFT operation on the compensated rxdata if transform precoding is enabled - nr_idft(&pusch_vars->rxdataF_comp[0][symbol * nb_re_pusch2], nb_re_pusch); - LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d\n", symbol, nb_re_pusch); - } - - //---------------------------------------------------------- - //--------------------- PTRS Processing -------------------- - //---------------------------------------------------------- - /* In case PTRS is enabled then LLR will be calculated after PTRS symbols are processed * - * otherwise LLR are calculated for each symbol based upon DMRS channel estimates only. */ if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - start_meas(&gNB->ulsch_ptrs_processing_stats); - nr_pusch_ptrs_processing(gNB, - frame_parms, - rel15_ul, - ulsch_id, - slot, - symbol, - nb_re_pusch); - stop_meas(&gNB->ulsch_ptrs_processing_stats); - - /* Subtract total PTRS RE's in the symbol from PUSCH RE's */ - pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot; - } - - /*---------------------------------------------------------------------------------------------------- */ - /*-------------------- LLRs computation -------------------------------------------------------------*/ - /*-----------------------------------------------------------------------------------------------------*/ - start_meas(&gNB->ulsch_llr_stats); - 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); - } + nr_pusch_symbol_processing(rdata); } 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, - 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 + pushTpool(&gNB->threadPool, req); + gNB->nbSymb++; } - stop_meas(&gNB->ulsch_llr_stats); - rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol]; + + LOG_D(PHY,"%d.%d Added symbol %d (count %d) to process, in pipe\n",frame,slot,symbol,gNB->nbSymb); } } // symbol loop - if (!(frame % 128)) { - int num_llr = num_re_total*rel15_ul->qam_mod_order; - GnbScopeUpdate(gNB, puschLLRe, num_llr); - GnbScopeUpdate(gNB, puschIQe, num_re_total); + + while (gNB->nbSymb > 0) { + notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool); + gNB->nbSymb--; + delNotifiedFIFO_elt(req); } + + stop_meas(&gNB->rx_pusch_symbol_processing_stats); + return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index f4d526960e..1649f57878 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -30,6 +30,7 @@ * \warning */ +#include "PHY/defs_gNB.h" #include "PHY/defs_nr_common.h" #include "PHY/sse_intrin.h" #include "PHY/impl_defs_top.h" @@ -46,16 +47,9 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, { c16_t *rxF = (c16_t *)rxdataF_comp; c16_t *llr32 = (c16_t *)ulsch_llr; - - if (!llr32) { - LOG_E(PHY,"nr_ulsch_qpsk_llr: llr is null, symbol %d, llr32 = %p\n",symbol, llr32); - } for (int i = 0; i < nb_re; i++) { - //*llr32 = *rxF; - llr32->r = rxF->r >> 3; - llr32->i = rxF->i >> 3; - rxF++; - llr32++; + llr32[i].r = rxF[i].r >> 3; + llr32[i].i = rxF[i].i >> 3; } } @@ -66,72 +60,34 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol) { + simde__m256i *rxF_256 = (simde__m256i*)rxdataF_comp; + simde__m256i *ch_mag = (simde__m256i*)ul_ch_mag; + int64_t *llr_64 = (int64_t*)ulsch_llr; - simde__m256i *rxF = (simde__m256i*)rxdataF_comp; - simde__m256i *ch_mag; - simde__m256i llr256[2]; - register simde__m256i xmm0; - uint32_t *llr32; - int i; + simde__m256i xmm0, xmm1, xmm2; - int off = ((nb_rb&1) == 1)? 4:0; - - llr32 = (uint32_t*)ulsch_llr; - - ch_mag = (simde__m256i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - unsigned char len_mod8 = nb_re&7; - nb_re >>= 3; // length in quad words (4 REs) - nb_re += (len_mod8 == 0 ? 0 : 1); - - for (i=0; i |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + for (int i = 0; i < ((nb_re + 7) >> 3); i++) { + xmm0 = simde_mm256_abs_epi16(rxF_256[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm256_subs_epi16(ch_mag[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - llr256[0] = simde_mm256_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs - llr256[1] = simde_mm256_unpackhi_epi32(rxF[i],xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + xmm1 = simde_mm256_unpacklo_epi32(rxF_256[i], xmm0); + xmm2 = simde_mm256_unpackhi_epi32(rxF_256[i], xmm0); + + // xmm1 |1st 2ed 3rd 4th 9th 10th 13rd 14th| + // xmm2 |5th 6th 7th 8th 11st 12ed 15th 16th| - // 1st RE - llr32[0] = simde_mm256_extract_epi32(llr256[0],0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I - llr32[1] = simde_mm256_extract_epi32(llr256[0],1); // llr32[1] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 2nd RE - llr32[2] = simde_mm256_extract_epi32(llr256[0],2); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I - llr32[3] = simde_mm256_extract_epi32(llr256[0],3); // llr32[3] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 3rd RE - llr32[4] = simde_mm256_extract_epi32(llr256[1],0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I - llr32[5] = simde_mm256_extract_epi32(llr256[1],1); // llr32[5] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 4th RE - llr32[6] = simde_mm256_extract_epi32(llr256[1],2); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I - llr32[7] = simde_mm256_extract_epi32(llr256[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 5th RE - llr32[8] = simde_mm256_extract_epi32(llr256[0],4); // llr32[8] low 16 bits-> y_R , high 16 bits-> y_I - llr32[9] = simde_mm256_extract_epi32(llr256[0],5); // llr32[9] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 6th RE - llr32[10] = simde_mm256_extract_epi32(llr256[0],6); // llr32[10] low 16 bits-> y_R , high 16 bits-> y_I - llr32[11] = simde_mm256_extract_epi32(llr256[0],7); // llr32[11] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 7th RE - llr32[12] = simde_mm256_extract_epi32(llr256[1],4); // llr32[12] low 16 bits-> y_R , high 16 bits-> y_I - llr32[13] = simde_mm256_extract_epi32(llr256[1],5); // llr32[13] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - // 8th RE - llr32[14] = simde_mm256_extract_epi32(llr256[1],6); // llr32[14] low 16 bits-> y_R , high 16 bits-> y_I - llr32[15] = simde_mm256_extract_epi32(llr256[1],7); // llr32[15] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 - - llr32+=16; - + *llr_64++ = simde_mm256_extract_epi64(xmm1, 0); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 1); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 0); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 1); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 2); + *llr_64++ = simde_mm256_extract_epi64(xmm1, 3); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 2); + *llr_64++ = simde_mm256_extract_epi64(xmm2, 3); } - - simde_mm_empty(); - simde_m_empty(); } //---------------------------------------------------------------------------------------------- @@ -142,232 +98,110 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int32_t *ul_ch_magb, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol) { - int off = ((nb_rb&1) == 1)? 4:0; - simde__m256i *rxF = (simde__m256i*)rxdataF_comp; - simde__m256i *ch_mag,*ch_magb; - register simde__m256i xmm0,xmm1,xmm2; + simde__m256i xmm0, xmm1, xmm2; - int i; + simde__m256i *ch_maga = (simde__m256i*)ul_ch_mag; + simde__m256i *ch_magb = (simde__m256i*)ul_ch_magb; - ch_mag = (simde__m256i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - ch_magb = (simde__m256i*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; + int32_t *llr_32 = (int32_t *)ulsch_llr; - int len_mod8 = nb_re&7; - nb_re = nb_re>>3; // length in quad words (4 REs) - nb_re += ((len_mod8 == 0) ? 0 : 1); - - for (i=0; i> 3); i++) { xmm0 = rxF[i]; - xmm1 = simde_mm256_abs_epi16(xmm0); - xmm1 = simde_mm256_subs_epi16(ch_mag[i],xmm1); + xmm1 = simde_mm256_abs_epi16(xmm0); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm1 = simde_mm256_subs_epi16(ch_maga[i], xmm1); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm2 = simde_mm256_abs_epi16(xmm1); - xmm2 = simde_mm256_subs_epi16(ch_magb[i],xmm2); - - // --------------------------------------- - // 1st RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,0); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,1); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,0); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,1); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,0); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,1); - // --------------------------------------- + xmm2 = simde_mm256_subs_epi16(ch_magb[i], xmm2); + // xmm0 |1st 4th 7th 10th 13th 16th 19th 22ed| + // xmm1 |2ed 5th 8th 11th 14th 17th 20th 23rd| + // xmm2 |3rd 6th 9th 12th 15th 18th 21st 24th| - ulsch_llr+=6; - - // --------------------------------------- - // 2nd RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,2); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,3); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,2); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,3); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,2); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,3); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,0); + *llr_32++ = simde_mm256_extract_epi32(xmm1,0); + *llr_32++ = simde_mm256_extract_epi32(xmm2,0); - ulsch_llr+=6; - - // --------------------------------------- - // 3rd RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,4); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,5); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,4); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,5); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,4); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,5); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,1); + *llr_32++ = simde_mm256_extract_epi32(xmm1,1); + *llr_32++ = simde_mm256_extract_epi32(xmm2,1); - ulsch_llr+=6; - - // --------------------------------------- - // 4th RE - // --------------------------------------- - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,6); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,7); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,6); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,7); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,6); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,7); - // --------------------------------------- + *llr_32++ = simde_mm256_extract_epi32(xmm0,2); + *llr_32++ = simde_mm256_extract_epi32(xmm1,2); + *llr_32++ = simde_mm256_extract_epi32(xmm2,2); - ulsch_llr+=6; - ulsch_llr[0] = simde_mm256_extract_epi16(xmm0,8); - ulsch_llr[1] = simde_mm256_extract_epi16(xmm0,9); - ulsch_llr[2] = simde_mm256_extract_epi16(xmm1,8); - ulsch_llr[3] = simde_mm256_extract_epi16(xmm1,9); - ulsch_llr[4] = simde_mm256_extract_epi16(xmm2,8); - ulsch_llr[5] = simde_mm256_extract_epi16(xmm2,9); + *llr_32++ = simde_mm256_extract_epi32(xmm0,3); + *llr_32++ = simde_mm256_extract_epi32(xmm1,3); + *llr_32++ = simde_mm256_extract_epi32(xmm2,3); - ulsch_llr[6] = simde_mm256_extract_epi16(xmm0,10); - ulsch_llr[7] = simde_mm256_extract_epi16(xmm0,11); - ulsch_llr[8] = simde_mm256_extract_epi16(xmm1,10); - ulsch_llr[9] = simde_mm256_extract_epi16(xmm1,11); - ulsch_llr[10] = simde_mm256_extract_epi16(xmm2,10); - ulsch_llr[11] = simde_mm256_extract_epi16(xmm2,11); + *llr_32++ = simde_mm256_extract_epi32(xmm0,4); + *llr_32++ = simde_mm256_extract_epi32(xmm1,4); + *llr_32++ = simde_mm256_extract_epi32(xmm2,4); - ulsch_llr[12] = simde_mm256_extract_epi16(xmm0,12); - ulsch_llr[13] = simde_mm256_extract_epi16(xmm0,13); - ulsch_llr[14] = simde_mm256_extract_epi16(xmm1,12); - ulsch_llr[15] = simde_mm256_extract_epi16(xmm1,13); - ulsch_llr[16] = simde_mm256_extract_epi16(xmm2,12); - ulsch_llr[17] = simde_mm256_extract_epi16(xmm2,13); + *llr_32++ = simde_mm256_extract_epi32(xmm0,5); + *llr_32++ = simde_mm256_extract_epi32(xmm1,5); + *llr_32++ = simde_mm256_extract_epi32(xmm2,5); - ulsch_llr[18] = simde_mm256_extract_epi16(xmm0,14); - ulsch_llr[19] = simde_mm256_extract_epi16(xmm0,15); - ulsch_llr[20] = simde_mm256_extract_epi16(xmm1,14); - ulsch_llr[21] = simde_mm256_extract_epi16(xmm1,15); - ulsch_llr[22] = simde_mm256_extract_epi16(xmm2,14); - ulsch_llr[23] = simde_mm256_extract_epi16(xmm2,15); + *llr_32++ = simde_mm256_extract_epi32(xmm0,6); + *llr_32++ = simde_mm256_extract_epi32(xmm1,6); + *llr_32++ = simde_mm256_extract_epi32(xmm2,6); - ulsch_llr+=24; + *llr_32++ = simde_mm256_extract_epi32(xmm0,7); + *llr_32++ = simde_mm256_extract_epi32(xmm1,7); + *llr_32++ = simde_mm256_extract_epi32(xmm2,7); } - - simde_mm_empty(); - simde_m_empty(); } void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int32_t *ul_ch_magb, - int32_t *ul_ch_magc, - int16_t *ulsch_llr, - uint32_t nb_rb, - uint32_t nb_re, - uint8_t symbol) + int32_t *ul_ch_magc, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol) { - int off = ((nb_rb&1) == 1)? 4:0; - simde__m256i *rxF = (simde__m256i*)rxdataF_comp; - simde__m256i *ch_mag,*ch_magb,*ch_magc; - register simde__m256i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; + simde__m256i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; simde__m256i *llr256=(simde__m256i*)ulsch_llr; - ch_mag = (simde__m256i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - ch_magb = (simde__m256i*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; - ch_magc = (simde__m256i*)&ul_ch_magc[(symbol*(off+(nb_rb*12)))]; - int len_mod8 = nb_re&7; - int nb_re256 = nb_re>>3; // length in 256-bit words (8 REs) + simde__m256i* ch_maga = (simde__m256i*)ul_ch_mag; + simde__m256i* ch_magb = (simde__m256i*)ul_ch_magb; + simde__m256i* ch_magc = (simde__m256i*)ul_ch_magc; - for (int i=0; i |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmtmpD2 contains 16 LLRs - xmm1 = simde_mm256_abs_epi16(xmm0); - xmm1 = simde_mm256_subs_epi16(ch_magb[i],xmm1); // contains 16 LLRs - xmm2 = simde_mm256_abs_epi16(xmm1); - xmm2 = simde_mm256_subs_epi16(ch_magc[i],xmm2); // contains 16 LLRs - // rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6 - // xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4 - // xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2 - // xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0 - xmm3 = simde_mm256_unpacklo_epi32(rxF[i],xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 - xmm4 = simde_mm256_unpackhi_epi32(rxF[i],xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 - xmm5 = simde_mm256_unpacklo_epi32(xmm1,xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 - xmm6 = simde_mm256_unpackhi_epi32(xmm1,xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 - - xmm0 = simde_mm256_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0 A4 B4 C4 D4 - xmm1 = simde_mm256_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1 A5 B5 C5 D5 - xmm2 = simde_mm256_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2 A6 B6 C6 D6 - xmm3 = simde_mm256_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3 A7 B7 C7 D7 - llr256[0] = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1 - llr256[1] = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3 - llr256[2] = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5 - llr256[3] = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7 - llr256+=4; + for (int i = 0; i < ((nb_re + 7) >> 3); i++) { + xmm0 = simde_mm256_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = simde_mm256_subs_epi16(ch_maga[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + // xmmtmpD2 contains 16 LLRs + xmm1 = simde_mm256_abs_epi16(xmm0); + xmm1 = simde_mm256_subs_epi16(ch_magb[i], xmm1); // contains 16 LLRs + xmm2 = simde_mm256_abs_epi16(xmm1); + xmm2 = simde_mm256_subs_epi16(ch_magc[i], xmm2); // contains 16 LLRs + // rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6 + // xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4 + // xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2 + // xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0 + xmm3 = simde_mm256_unpacklo_epi32(rxF[i], xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 + xmm4 = simde_mm256_unpackhi_epi32(rxF[i], xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 + xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 + xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 + xmm0 = simde_mm256_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 A4 B4 C4 D4 + xmm1 = simde_mm256_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 A5 B5 C5 D5 + xmm2 = simde_mm256_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2 A6 B6 C6 D6 + xmm3 = simde_mm256_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3 A7 B7 C7 D7 + *llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x20); // A0 B0 C0 D0 A1 B1 C1 D1 + *llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3 + *llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5 + *llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7 } - simde__m128i *llr128 = (simde__m128i*)llr256; - if (len_mod8 >= 4) { - int nb_re128 = nb_re>>2; - simde__m128i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6; - simde__m128i *rxF = (simde__m128i*)rxdataF_comp; - simde__m128i *ch_mag = (simde__m128i*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - simde__m128i *ch_magb = (simde__m128i*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; - simde__m128i *ch_magc = (simde__m128i*)&ul_ch_magc[(symbol*(off+(nb_rb*12)))]; - - xmm0 = simde_mm_abs_epi16(rxF[nb_re128-1]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_epi16(ch_mag[nb_re128-1],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmtmpD2 contains 8 LLRs - xmm1 = simde_mm_abs_epi16(xmm0); - xmm1 = simde_mm_subs_epi16(ch_magb[nb_re128-1],xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_epi16(xmm1); - xmm2 = simde_mm_subs_epi16(ch_magc[nb_re128-1],xmm2); // contains 8 LLRs - // rxF[i] A0 A1 A2 A3 - // xmm0 B0 B1 B2 B3 - // xmm1 C0 C1 C2 C3 - // xmm2 D0 D1 D2 D3 - xmm3 = simde_mm_unpacklo_epi32(rxF[nb_re128-1],xmm0); // A0 B0 A1 B1 - xmm4 = simde_mm_unpackhi_epi32(rxF[nb_re128-1],xmm0); // A2 B2 A3 B3 - xmm5 = simde_mm_unpacklo_epi32(xmm1,xmm2); // C0 D0 C1 D1 - xmm6 = simde_mm_unpackhi_epi32(xmm1,xmm2); // C2 D2 C3 D3 - - llr128[0] = simde_mm_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0 - llr128[1] = simde_mm_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1 - llr128[2] = simde_mm_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2 - llr128[3] = simde_mm_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3 - llr128+=4; - } - if (len_mod8 == 6) { - int nb_re64 = nb_re>>1; - simde__m64 *llr64 = (simde__m64 *)llr128; - simde__m64 xmm0,xmm1,xmm2; - simde__m64 *rxF = (simde__m64*)rxdataF_comp; - simde__m64 *ch_mag = (simde__m64*)&ul_ch_mag[(symbol*(off+(nb_rb*12)))]; - simde__m64 *ch_magb = (simde__m64*)&ul_ch_magb[(symbol*(off+(nb_rb*12)))]; - simde__m64 *ch_magc = (simde__m64*)&ul_ch_magc[(symbol*(off+(nb_rb*12)))]; - - xmm0 = simde_mm_abs_pi16(rxF[nb_re64-1]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_subs_pi16(ch_mag[nb_re-1],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - // xmmtmpD2 contains 4 LLRs - xmm1 = simde_mm_abs_pi16(xmm0); - xmm1 = simde_mm_subs_pi16(ch_magb[nb_re64-1],xmm1); // contains 4 LLRs - xmm2 = simde_mm_abs_pi16(xmm1); - xmm2 = simde_mm_subs_pi16(ch_magc[nb_re64-1],xmm2); // contains 4 LLRs - // rxF[i] A0 A1 - // xmm0 B0 B1 - // xmm1 C0 C1 - // xmm2 D0 D1 - llr64[0] = simde_m_punpckldq(rxF[nb_re64-1],xmm0); // A0 B0 - llr64[2] = simde_m_punpckhdq(rxF[nb_re64-1],xmm0); // A1 B1 - llr64[1] = simde_m_punpckldq(xmm1,xmm2); // C0 D0 - llr64[3] = simde_m_punpckhdq(xmm1,xmm2); // C1 D1 - } - } + void nr_ulsch_compute_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int32_t *ul_ch_magb, int32_t *ul_ch_magc, int16_t *ulsch_llr, - uint32_t nb_rb, uint32_t nb_re, uint8_t symbol, uint8_t mod_order) @@ -383,7 +217,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, nr_ulsch_16qam_llr(rxdataF_comp, ul_ch_mag, ulsch_llr, - nb_rb, nb_re, symbol); break; @@ -392,7 +225,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, ul_ch_mag, ul_ch_magb, ulsch_llr, - nb_rb, nb_re, symbol); break; @@ -402,7 +234,6 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, ul_ch_magb, ul_ch_magc, ulsch_llr, - nb_rb, nb_re, symbol); break; @@ -3786,46 +3617,7 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, simde_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, - 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 *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))]; - 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: - 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: - 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); - } -} - -void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift) +static void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift) { simde__m128i *llr_layers0 = (simde__m128i *)&llr_layers[0][rxdataF_ext_offset * mod_order]; simde__m128i *llr_layers1 = (simde__m128i *)&llr_layers[1][rxdataF_ext_offset * mod_order]; @@ -3848,3 +3640,35 @@ void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_e llr_layers1[i] = simde_mm_srai_epi16(llr_layers1[i], shift); } } + +void nr_ulsch_compute_ML_llr(NR_gNB_PUSCH *pusch_vars, + uint32_t symbol, + c16_t* rxdataF_comp0, + c16_t* rxdataF_comp1, + c16_t* ul_ch_mag0, + c16_t* ul_ch_mag1, + c16_t* llr_layers0, + c16_t* llr_layers1, + c16_t* rho0, + c16_t* rho1, + uint32_t nb_re, + uint8_t mod_order) +{ + 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); + nr_ulsch_shift_llr(pusch_vars->llr_layers, nb_re, pusch_vars->llr_offset[symbol] >> 1, 2, 4); + 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: + 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, Qm = %d\n", mod_order); + } +} diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 305a90d819..de3555bf29 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1693,12 +1693,16 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // run polar decoder on llrs decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size); - LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]); + // Decoder reversal + decodedPayload[0] = reverse_bits(decodedPayload[0], nb_bit); + if (decoderState>0) decoderState=1; corr_dB = dB_fixed64(corr); LOG_D(PHY,"metric %d dB\n",corr_dB); } + LOG_D(PHY, "UCI decoderState %d, payload[0] %llu\n", decoderState, (unsigned long long)decodedPayload[0]); + // estimate CQI for MAC (from antenna port 0 only) // TODO this computation is wrong -> to be ignored at MAC for now int SNRtimes10 = dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[0]], @@ -1761,7 +1765,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3); uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<bit_len_csi_part1 < 64 ? decodedPayload[0] >> pucch_pdu->bit_len_csi_part1 : 0; + decodedPayload[0] = pucch_pdu->bit_len_csi_part1 < 64 ? decodedPayload[0] >> bit_left : 0; } if (pucch_pdu->bit_len_csi_part2>0) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index f3ee7b0e7b..c993ec3709 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -44,6 +44,7 @@ #include "executables/nr-uesoftmodem.h" #include "PHY/CODING/nrLDPC_extern.h" #include "common/utils/nr/nr_common.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "openair1/PHY/TOOLS/phy_scope_interface.h" //#define ENABLE_PHY_PAYLOAD_DEBUG 1 @@ -116,10 +117,8 @@ static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, if (*num_seg_ok == harq_process->C) { if (harq_process->C > 1) { /* check global CRC */ - int A = tbs; - int crc_length = A > 3824 ? 3 : 2; - int crc_type = A > 3824 ? CRC24_A : CRC16; - if (!check_crc(b, A + crc_length * 8, crc_type)) { + // we have regrouped the transport block, so it is "1" segment + if (!check_crc(b, lenWithCrc(1, tbs), crcType(1, tbs))) { harq_process->ack = 0; dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; LOG_E(PHY, " Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n", proc->frame_rx, proc->nr_slot_rx, harq_process->C); @@ -166,10 +165,8 @@ static void nr_processDLSegment(void *arg) NR_UE_DLSCH_t *dlsch = rdata->dlsch; NR_DL_UE_HARQ_t *harq_process= rdata->harq_process; t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int length_dec; int Kr; int K_bits_F; - uint8_t crc_type; int r = rdata->segment_r; int A = rdata->A; int E = rdata->E; @@ -240,19 +237,6 @@ static void nr_processDLSegment(void *arg) LOG_D(PHY,"\n"); } - - if (harq_process->C == 1) { - if (A > NR_MAX_PDSCH_TBS) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } else { - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - { start_meas(&rdata->ts_ldpc_decode); //set first 2*Z_c bits to zeros @@ -272,9 +256,9 @@ static void nr_processDLSegment(void *arg) } //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); - p_decoderParms->block_length=length_dec; - nrLDPC_initcall(p_decoderParms, (int8_t*)&pl[0], LDPCoutput); - p_decoderParms->crc_type = crc_type; + p_decoderParms->block_length = lenWithCrc(harq_process->C, A); + p_decoderParms->crc_type = crcType(harq_process->C, A); + nrLDPC_initcall(p_decoderParms, (int8_t *)&pl[0], LDPCoutput); rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], LDPCoutput, &procTime, &harq_process->abort_decode); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); @@ -311,8 +295,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // HARQ stats phy_vars_ue->dl_stats[harq_process->DLround]++; - LOG_D(PHY,"Round %d RV idx %d\n",harq_process->DLround,dlsch->dlsch_config.rv); - uint8_t kc; + LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv); uint16_t nb_rb;// = 30; uint8_t dmrs_Type = dlsch->dlsch_config.dmrsConfigType; AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); @@ -377,33 +360,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d Coderate %f\n", frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, dlsch->dlsch_config.mcs, dlsch->Nl, nb_symb_sch, nb_rb, dlsch->dlsch_config.qamModOrder, Coderate); - - if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { - p_decParams->BG = 2; - kc = 52; - } else { - p_decParams->BG = 1; - kc = 68; - } + p_decParams->BG = get_BG(A, dlsch->dlsch_config.targetCodeRate); + unsigned int kc = p_decParams->BG == 2 ? 52 : 68; if (harq_process->first_rx == 1) { // This is a new packet, so compute quantities regarding segmentation - if (A > NR_MAX_PDSCH_TBS) - harq_process->B = A+24; - else - harq_process->B = A+16; - nr_segmentation(NULL, NULL, - harq_process->B, + lenWithCrc(1, A), // We give a max size in case of 1 segment &harq_process->C, &harq_process->K, &harq_process->Z, // [hna] Z is Zc &harq_process->F, p_decParams->BG); - + if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); return(-1); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index ee79bdc47b..c7d10b69f4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -493,12 +493,8 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, } // printf("polar decoder output 0x%08x\n",pbch_a_prime); // Decoder reversal - uint32_t a_reversed=0; + pbch_a_prime = (uint32_t)reverse_bits(pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS); - for (int i=0; i>i)&1)<<(31-i); - - pbch_a_prime = a_reversed; //payload un-scrambling M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 9f9b123781..b0ea45b7ec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -53,8 +53,6 @@ typedef struct { SCH_status_t status; /// Last TPC command uint8_t TPC; - /// The payload + CRC size in bits, "B" from 36-212 - uint32_t B; /// Length of ACK information (bits) uint8_t O_ACK; /// Index of current HARQ round for this ULSCH @@ -117,8 +115,6 @@ typedef struct { uint8_t Ndi; /// DLSCH status flag indicating SCH_status_t status; - /// The payload + CRC size in bits - uint32_t B; /// Pointers to transport block segments uint8_t **c; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 42fe941848..1c4d7c0fec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -92,8 +92,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, */ int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056; - - if (A > 3824) { + int B; + if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload crc = crc24a(harq_process->a,A)>>8; harq_process->a[A>>3] = ((uint8_t*)&crc)[2]; @@ -102,13 +102,12 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - harq_process->B = A+24; + B = A + 24; AssertFatal((A/8)+4 <= max_payload_bytes,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,max_payload_bytes); memcpy(harq_process->b,harq_process->a,(A/8)+4); - } - else { + } else { // Add 16-bit crc (polynomial A) to payload crc = crc16(harq_process->a,A)>>16; harq_process->a[A>>3] = ((uint8_t*)&crc)[1]; @@ -116,7 +115,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, //printf("CRC %x (A %d)\n",crc,A); //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - harq_process->B = A+16; + B = A + 16; AssertFatal((A/8)+3 <= max_payload_bytes,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,max_payload_bytes); @@ -128,26 +127,25 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ///////////////////////// b---->| block segmentation |---->c ///////////////////////// /////////// - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { harq_process->BG = 2; - } - else{ + } else { harq_process->BG = 1; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); start_meas(&ue->ulsch_segmentation_stats); - uint32_t Kb=nr_segmentation(harq_process->b, - harq_process->c, - harq_process->B, - &harq_process->C, - &harq_process->K, - pz, - &harq_process->F, - harq_process->BG); + uint32_t Kb = nr_segmentation(harq_process->b, + harq_process->c, + B, + &harq_process->C, + &harq_process->K, + pz, + &harq_process->F, + harq_process->BG); if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) { - LOG_E(PHY,"nr_segmentation.c: too many segments %d, B %d\n",harq_process->C,harq_process->B); + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", harq_process->C, B); return(-1); } stop_meas(&ue->ulsch_segmentation_stats); @@ -169,7 +167,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, for (int r=0; rC; r++) { //channel_input[r] = &harq_process->d[r][0]; #ifdef DEBUG_ULSCH_CODING - printf("Encoder: B %d F %d \n",harq_process->B, harq_process->F); + printf("Encoder: B %d F %d \n", B, harq_process->F); printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); for (int cnt =0 ; cnt < 22*(*pz)/8; cnt ++){ diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index d59da8be97..f5c4276562 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -644,7 +644,9 @@ static void nr_uci_encoding(uint64_t payload, b[7] = b[0]; AssertFatal(nrofPRB<=16,"Number of PRB >16\n"); } else if (A>=12) { - AssertFatal(A<65,"Polar encoding not supported yet for UCI with more than 64 bits\n"); + // Encoder reversal + payload = reverse_bits(payload, A); + polar_encoder_fast(&payload, b, 0,0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, A, diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index c2e6dfba75..5252d7a4e3 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -75,8 +75,6 @@ typedef struct { nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu; /// pointer to pdu from MAC interface (this is "a" in 36.212) uint8_t *pdu; - /// The payload + CRC size in bits, "B" from 36-212 - uint32_t B; /// Pointer to the payload uint8_t *b; /// Pointers to transport block segments @@ -199,8 +197,6 @@ typedef struct { uint32_t TBS; /// Pointer to the payload (38.212 V15.4.0 section 5.1) uint8_t *b; - /// The payload + CRC (24 bits) in bits (38.212 V15.4.0 section 5.1) - uint32_t B; /// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2) uint8_t **c; /// Number of bits in each code block (38.212 V15.4.0 section 5.2.2) @@ -227,6 +223,18 @@ typedef struct { int llrLen; ////////////////////////////////////////////////////////////// } NR_UL_gNB_HARQ_t; +static inline int lenWithCrc(int nbSeg, int len) +{ + if (nbSeg > 1) + return (len + 24 + 24 * nbSeg) / nbSeg; + return len + (len > NR_MAX_PDSCH_TBS ? 24 : 16); +} +static inline int crcType(int nbSeg, int len) +{ + if (nbSeg > 1) + return CRC24_B; + return len > NR_MAX_PDSCH_TBS ? CRC24_A : CRC16; +} typedef struct { //! estimated received spatial signal power (linear) @@ -409,8 +417,8 @@ typedef struct { /// \brief Total RE count after DMRS/PTRS RE's are extracted from respective symbol. /// - first index: ? [0...14] smybol per slot int16_t *ul_valid_re_per_slot; - /// flag to verify if channel level computation is done - uint8_t cl_done; + /// \brief offset for llr corresponding to each symbol + int llr_offset[14]; /// flag to indicate DTX on reception int DTX; } NR_gNB_PUSCH; @@ -728,18 +736,14 @@ typedef struct PHY_VARS_gNB_s { time_stats_t dlsch_segmentation_stats; time_stats_t rx_pusch_stats; + time_stats_t rx_pusch_init_stats; + time_stats_t rx_pusch_symbol_processing_stats; time_stats_t ul_indication_stats; time_stats_t schedule_response_stats; time_stats_t ulsch_decoding_stats; - time_stats_t ulsch_rate_unmatching_stats; time_stats_t ulsch_ldpc_decoding_stats; time_stats_t ulsch_deinterleaving_stats; - time_stats_t ulsch_unscrambling_stats; time_stats_t ulsch_channel_estimation_stats; - time_stats_t ulsch_ptrs_processing_stats; - time_stats_t ulsch_channel_compensation_stats; - time_stats_t ulsch_rbs_extraction_stats; - time_stats_t ulsch_mrc_stats; time_stats_t ulsch_llr_stats; time_stats_t rx_srs_stats; time_stats_t generate_srs_stats; @@ -754,6 +758,7 @@ typedef struct PHY_VARS_gNB_s { time_stats_t rx_dft_stats; time_stats_t ulsch_freq_offset_estimation_stats; */ + notifiedFIFO_t respPuschSymb; notifiedFIFO_t respDecode; notifiedFIFO_t resp_L1; notifiedFIFO_t L1_tx_free; @@ -761,6 +766,8 @@ typedef struct PHY_VARS_gNB_s { notifiedFIFO_t L1_tx_out; notifiedFIFO_t resp_RU_tx; tpool_t threadPool; + int nbSymb; + int num_pusch_symbols_per_thread; pthread_t L1_rx_thread; int L1_rx_thread_core; pthread_t L1_tx_thread; @@ -771,6 +778,32 @@ typedef struct PHY_VARS_gNB_s { rt_L1_profiling_t rt_L1_profiling; } PHY_VARS_gNB; +typedef struct puschSymbolProc_s { + PHY_VARS_gNB *gNB; + NR_DL_FRAME_PARMS *frame_parms; + nfapi_nr_pusch_pdu_t *rel15_ul; + int ulsch_id; + int slot; + int startSymbol; + int numSymbols; + int16_t *llr; + int16_t **llr_layers; + int16_t *s; + uint32_t nvar; +} puschSymbolProc_t; + +struct puschSymbolReqId { + uint16_t ulsch_id; + uint16_t frame; + uint8_t slot; + uint16_t spare; +} __attribute__((packed)); + +union puschSymbolReqUnion { + struct puschSymbolReqId s; + uint64_t p; +}; + typedef struct LDPCDecode_s { PHY_VARS_gNB *gNB; NR_UL_gNB_HARQ_t *ulsch_harq; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index ad04ee9436..c5af8b8415 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -43,7 +43,7 @@ #define nr_slot_t lte_subframe_t #define MAX_NUM_SUBCARRIER_SPACING 5 -#define NR_MAX_OFDM_SYMBOL_SIZE 4096 +#define NR_MAX_OFDM_SYMBOL_SIZE 8192 #define NR_SYMBOLS_PER_SLOT NR_NUMBER_OF_SYMBOLS_PER_SLOT diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 184e3ec63b..cf47c699d9 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -266,12 +266,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block bool crc_valid = true; if (ulsch_harq->C > 1) { - // Check ULSCH transport block CRC - int crc_type = CRC16; - if (rdata->A > 3824) { - crc_type = CRC24_A; - } - crc_valid = check_crc(ulsch_harq->b, ulsch_harq->B, crc_type); + crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, rdata->A), crcType(1, rdata->A)); } if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) { @@ -397,19 +392,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - - nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, - pusch_pdu->nrOfLayers, - pusch_pdu->qam_mod_order, - G, - gNB->pusch_vars[ULSCH_id].llr_layers); - - //---------------------------------------------------------- - //------------------- ULSCH unscrambling ------------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_unscrambling_stats); - nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); - stop_meas(&gNB->ulsch_unscrambling_stats); + //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- //---------------------------------------------------------- @@ -417,7 +400,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int start_meas(&gNB->ulsch_decoding_stats); int nbDecode = nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G); - stop_meas(&gNB->ulsch_decoding_stats); + return nbDecode; } @@ -899,7 +882,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); start_meas(&gNB->rx_pusch_stats); - nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; pusch_vars->ulsch_power_tot = 0; pusch_vars->ulsch_noise_power_tot = 0; @@ -953,7 +936,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } - if (totalDecode > 0 && gNB->ldpc_offload_flag == 0) { while (totalDecode > 0) { notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); if (req == NULL) @@ -962,7 +944,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) delNotifiedFIFO_elt(req); totalDecode--; } - } + stop_meas(&gNB->ulsch_decoding_stats); for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; if (srs) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 5ee660d1e0..762487c759 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -561,10 +561,12 @@ int main(int argc, char *argv[]) RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; gNB->ofdm_offset_divisor = UINT_MAX; - initNotifiedFIFO(&gNB->respDecode); + gNB->num_pusch_symbols_per_thread = 1; initFloatingCoresTpool(threadCnt, &gNB->threadPool, false, "gNB-tpool"); initNotifiedFIFO(&gNB->respDecode); + + initNotifiedFIFO(&gNB->respPuschSymb); initNotifiedFIFO(&gNB->L1_tx_free); initNotifiedFIFO(&gNB->L1_tx_filled); initNotifiedFIFO(&gNB->L1_tx_out); @@ -719,7 +721,6 @@ int main(int argc, char *argv[]) NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; - // nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_process->ulsch_pdu; NR_Sched_Rsp_t *Sched_INFO = malloc(sizeof(*Sched_INFO)); memset((void*)Sched_INFO,0,sizeof(*Sched_INFO)); nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; @@ -927,15 +928,10 @@ int main(int argc, char *argv[]) roundStats = 0; reset_meas(&gNB->phy_proc_rx); reset_meas(&gNB->rx_pusch_stats); + reset_meas(&gNB->rx_pusch_init_stats); + reset_meas(&gNB->rx_pusch_symbol_processing_stats); reset_meas(&gNB->ulsch_decoding_stats); - reset_meas(&gNB->ulsch_deinterleaving_stats); - reset_meas(&gNB->ulsch_rate_unmatching_stats); - reset_meas(&gNB->ulsch_ldpc_decoding_stats); - reset_meas(&gNB->ulsch_unscrambling_stats); reset_meas(&gNB->ulsch_channel_estimation_stats); - reset_meas(&gNB->ulsch_llr_stats); - reset_meas(&gNB->ulsch_channel_compensation_stats); - reset_meas(&gNB->ulsch_rbs_extraction_stats); reset_meas(&UE->ulsch_ldpc_encoding_stats); reset_meas(&UE->ulsch_rate_matching_stats); reset_meas(&UE->ulsch_interleaving_stats); @@ -1588,25 +1584,22 @@ int main(int argc, char *argv[]) dump_pusch_stats(fd,gNB); fclose(fd); - if (print_perf==1) { - printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); - printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time"); - printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); - printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); - printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); - printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); - printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); - printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); - printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); + if (print_perf==1) + { + printf("gNB RX\n"); + printDistribution(&gNB->phy_proc_rx,table_rx, "Total PHY proc rx"); + printStatIndent(&gNB->rx_pusch_stats, "RX PUSCH time"); + printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time"); + printStatIndent2(&gNB->rx_pusch_init_stats, "RX PUSCH Initialization time"); + printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time"); printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); + + printf("\nUE TX\n"); printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time"); printStatIndent2(&UE->ulsch_segmentation_stats,"ULSCH segmentation time"); printStatIndent2(&UE->ulsch_ldpc_encoding_stats,"ULSCH LDPC encoder time"); printStatIndent2(&UE->ulsch_rate_matching_stats,"ULSCH rate-matching time"); printStatIndent2(&UE->ulsch_interleaving_stats,"ULSCH interleaving time"); - //printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); - //printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); - //printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); printStatIndent(&gNB->rx_srs_stats,"RX SRS time"); printStatIndent2(&gNB->generate_srs_stats,"Generate SRS sequence time"); printStatIndent2(&gNB->get_srs_signal_stats,"Get SRS signal time"); diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index b47a763089..8f8a047ee5 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -301,6 +301,10 @@ typedef struct f1ap_rb_failed_to_be_setup_s { long rb_id; } f1ap_rb_failed_to_be_setup_t; +typedef struct f1ap_drb_to_be_released_t { + long rb_id; +} f1ap_drb_to_be_released_t; + typedef struct cu_to_du_rrc_information_s { uint8_t * cG_ConfigInfo; uint32_t cG_ConfigInfo_length; @@ -354,6 +358,8 @@ typedef struct f1ap_ue_context_setup_s { f1ap_srb_to_be_setup_t *srbs_to_be_setup; uint8_t srbs_to_be_setup_length; uint8_t srbs_failed_to_be_setup_length; + uint8_t drbs_to_be_released_length; + f1ap_drb_to_be_released_t *drbs_to_be_released; f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup; ReconfigurationCompl_t ReconfigComplOutcome; uint8_t *rrc_container; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 9e9a85d9e5..1fb4981330 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -1531,14 +1531,14 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context } /* optional */ - if(0){ + if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) { /* c15. DRBs_ToBeReleased_List */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; ie15->criticality = F1AP_Criticality_reject; ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; - for (int i=0; i<1; i++) { + for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) { // asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list, F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies); @@ -1549,7 +1549,10 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item= &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; /* dRBID */ - drbs_toBeReleased_item->dRBID = 30L; + drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; + newGtpuDeleteOneTunnel(getCxt(instance)->gtpInst, + f1ap_ue_context_modification_req->gNB_CU_ue_id, + f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id); } } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index f3ee222bea..b9d29303f0 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -881,6 +881,24 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t } } } + + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, + F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false); + if (ieDrb != NULL) { + f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count; + f1ap_ue_context_modification_req->drbs_to_be_released = + calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t)); + AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released, + "could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n"); + for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) { + F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i]; + DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); + DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); + f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; + newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->gNB_DU_ue_id, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id); + } + } + /* RRC Reconfiguration Complete indicator */ F1AP_UEContextModificationRequestIEs_t *ieReconf; F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c index 7ea6df92fc..aa1042491b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c @@ -26,6 +26,7 @@ #define INDEX_MAX_TBS_TABLE (93) #include "common/utils/nr/nr_common.h" +#include "openair1/PHY/defs_nr_common.h" #include //Table 5.1.2.2-2 @@ -64,7 +65,7 @@ uint32_t nr_compute_tbs(uint16_t Qm, uint32_t nr_tbs=0; uint32_t Np_info, C, n; - if (Ninfo <=3824) { + if (Ninfo <= NR_MAX_PDSCH_TBS) { n = max(3, floor(log2(Ninfo)) - 6); Np_info = max(24, (Ninfo>>n)<>10; - if (Ninfo <=3824) { + if (Ninfo <= NR_MAX_PDSCH_TBS) { n = max(3, floor(log2(Ninfo)) - 6); Np_info = max(24, (Ninfo>>n)< #include @@ -4080,7 +4081,7 @@ void csi_period_offset(NR_CSI_ReportConfig_t *csirep, uint8_t get_BG(uint32_t A, uint16_t R) { float code_rate = (float) R / 10240.0f; - if ((A <=292) || ((A<=3824) && (code_rate <= 0.6667)) || code_rate <= 0.25) + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (code_rate <= 0.6667)) || code_rate <= 0.25) return 2; else return 1; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 54d91e9971..9328d75b37 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -71,6 +71,7 @@ void init_RA(module_id_t mod_id, ra->first_Msg3 = 1; ra->starting_preamble_nb = 0; ra->RA_backoff_cnt = 0; + ra->RA_window_cnt = -1; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; @@ -653,7 +654,9 @@ uint8_t nr_ue_get_rach(module_id_t mod_id, if (ra->ra_state > RA_UE_IDLE && ra->ra_state < RA_SUCCEEDED) { if (ra->RA_active == 0) { - /* RA not active - checking if RRC is ready to initiate the RA procedure */ + NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP.rach_ConfigCommon; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + init_RA(mod_id, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); LOG_D(NR_MAC, "In %s: RA not active. Checking for data to transmit from upper layers...\n", __FUNCTION__); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 6a8a4c213d..e2548fc7b1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2471,7 +2471,6 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr if (is_nr_prach_slot) { AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); - init_RA(module_idP, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); nr_get_RA_window(mac); uint16_t format = prach_occasion_info_p->format; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index a3ab4eb74c..995e5b5d83 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -53,7 +53,7 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { +int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { /* we assume that this function is mutex-protected from outside */ const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b1b60a9816..b9bb149310 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2750,6 +2750,14 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup); + + /* remove the rlc_BearerToReleaseList, we don't need it anymore */ + if (UE->CellGroup->rlc_BearerToReleaseList != NULL) { + struct NR_CellGroupConfig__rlc_BearerToReleaseList *l = UE->CellGroup->rlc_BearerToReleaseList; + asn_sequence_del(&l->list, l->list.count, /* free */1); + free(UE->CellGroup->rlc_BearerToReleaseList); + UE->CellGroup->rlc_BearerToReleaseList = NULL; + } } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 692e1b681c..174a50bead 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -39,7 +39,7 @@ //#define SRS_IND_DEBUG -const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) +int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) { /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index a39945d8fb..b5c8ac4a97 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -393,8 +393,8 @@ void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, const NR_ServingCellConfigCommon_t *scc); void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); -const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); -const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot); +int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); +int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 0e383e4eaf..e18c9ea5b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -138,6 +138,42 @@ static int handle_ue_context_drbs_setup(int rnti, return drbs_len; } +static int handle_ue_context_drbs_release(int rnti, + int drbs_len, + const f1ap_drb_to_be_released_t *req_drbs, + NR_CellGroupConfig_t *cellGroupConfig) +{ + DevAssert(req_drbs != NULL && cellGroupConfig != NULL); + + cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList)); + AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n"); + + /* Note: the actual GTP tunnels are already removed in the F1AP message + * decoding */ + for (int i = 0; i < drbs_len; i++) { + const f1ap_drb_to_be_released_t *drb = &req_drbs[i]; + + long lcid = drb->rb_id + 3; /* LCID is DRB + 3 */ + int idx = 0; + while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { + const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx]; + if (bc->logicalChannelIdentity == lcid) + break; + ++idx; + } + if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { + nr_rlc_release_entity(rnti, lcid); + asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); + long *plcid = malloc(sizeof(*plcid)); + AssertFatal(plcid != NULL, "out of memory\n"); + *plcid = lcid; + int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToReleaseList->list, plcid); + DevAssert(ret == 0); + } + } + return drbs_len; +} + static NR_UE_NR_Capability_t *get_ue_nr_cap(int rnti, uint8_t *buf, uint32_t len) { if (buf == NULL || len == 0) @@ -287,6 +323,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) NR_SCHED_LOCK(&mac->sched_lock); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->gNB_DU_ue_id); + if (!UE) { + LOG_E(NR_MAC, "could not find UE with RNTI %04x\n", req->gNB_DU_ue_id); + NR_SCHED_UNLOCK(&mac->sched_lock); + return; + } NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); @@ -306,6 +347,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) new_CellGroup); } + if (req->drbs_to_be_released_length > 0) { + resp.drbs_to_be_released_length = + handle_ue_context_drbs_release(req->gNB_DU_ue_id, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); + } + if (req->rrc_container != NULL) nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, DCCH, req->rrc_container, req->rrc_container_length); @@ -323,7 +369,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || ue_cap != NULL) { + if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0) { resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 14c75deb26..5aa4f10a8c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -166,21 +166,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset UE->rnti, stats->ulsch_total_bytes_scheduled, stats->ul.total_bytes); - for (int lc_id = 0; lc_id < 63; lc_id++) { - if (stats->dl.lc_bytes[lc_id] > 0) - output += snprintf(output, - end - output, - "UE %04x: LCID %d: %"PRIu64" bytes TX\n", - UE->rnti, - lc_id, - stats->dl.lc_bytes[lc_id]); - if (stats->ul.lc_bytes[lc_id] > 0) - output += snprintf(output, - end - output, - "UE %04x: LCID %d: %"PRIu64" bytes RX\n", - UE->rnti, - lc_id, - stats->ul.lc_bytes[lc_id]); + for (int i = 0; i < sched_ctrl->dl_lc_num; i++) { + int lc_id = sched_ctrl->dl_lc_ids[i]; + output += snprintf(output, + end - output, + "UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n", + UE->rnti, + lc_id, + stats->dl.lc_bytes[lc_id], + stats->ul.lc_bytes[lc_id]); } } NR_SCHED_UNLOCK(&gNB->UE_info.mutex); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index f19ae36819..d5766a7814 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1081,7 +1081,7 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_release_srb(ue_id_t ue_id, int srb_id) +void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); @@ -1094,7 +1094,7 @@ void nr_release_srb(ue_id_t ue_id, int srb_id) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_release_drb(ue_id_t ue_id, int drb_id) +void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); @@ -1274,7 +1274,7 @@ nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager() { } /* returns false in case of error, true if everything ok */ -const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out) +bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out) { nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index e6e7ca9273..36568b58ba 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -68,8 +68,8 @@ void nr_pdcp_reestablishment(ue_id_t ue_id); void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering); void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering); -void nr_release_srb(ue_id_t ue_id, int srb_id); -void nr_release_drb(ue_id_t ue_id, int drb_id); +void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id); +void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id); void add_srb(int is_gnb, ue_id_t rntiMaybeUEid, @@ -123,6 +123,6 @@ void nr_pdcp_tick(int frame, int subframe); nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager(); -const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out); +bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out); #endif /* NR_PDCP_OAI_API_H */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index c2d41cedb4..91985393cb 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -1638,7 +1638,10 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) entity->common.bstatus.tx_size -= pdu_size; /* assign SN to SDU */ - sdu->sdu->sn = entity->tx_next; + if (sdu->sdu->sn == -1) { + sdu->sdu->sn = entity->tx_next; + entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus; + } /* segment if necessary */ if (pdu_size > size) { @@ -1656,10 +1659,6 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) + next_sdu->size; } - /* update tx_next if the SDU segment is the last */ - if (sdu->is_last) - entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus; - /* put SDU/SDU segment in the wait list */ /* speedup: check end of wait list, probably the new sdu comes after */ if (entity->wait_end == NULL diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 04c1186f6e..2aec005e6d 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -100,7 +100,7 @@ static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_i } } -void nr_release_rlc_entity(int rnti, logical_chan_id_t channel_id) +void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id) { nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); @@ -1177,7 +1177,7 @@ void nr_rlc_activate_avg_time_to_tx( } /* returns false in case of error, true if everything ok */ -const bool nr_rlc_get_statistics( +bool nr_rlc_get_statistics( int rnti, int srb_flag, int rb_id, diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index c40e5c923a..be12b236e8 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -51,7 +51,7 @@ bool nr_rlc_update_rnti(int from_rnti, int to_rnti); /* test function for CI to trigger reestablishments */ void nr_rlc_test_trigger_reestablishment(int rnti); -void nr_release_rlc_entity(int rnti, logical_chan_id_t channel_id); +void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id); void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Config, struct NR_LogicalChannelConfig *lc_Config); @@ -75,4 +75,4 @@ void nr_rlc_activate_srb0(int rnti, struct gNB_MAC_INST_s *mac, void *rawUE, sdu_size_t sdu_len, void *rawUE)); -const bool nr_rlc_get_statistics(int rnti, int srb_flag, int rb_id, nr_rlc_statistics_t *out); +bool nr_rlc_get_statistics(int rnti, int srb_flag, int rb_id, nr_rlc_statistics_t *out); diff --git a/openair2/LAYER2/nr_rlc/tests/test.c b/openair2/LAYER2/nr_rlc/tests/test.c index 716a6aef11..2086dba3c6 100644 --- a/openair2/LAYER2/nr_rlc/tests/test.c +++ b/openair2/LAYER2/nr_rlc/tests/test.c @@ -426,8 +426,8 @@ int test_main(void) } } - gnb->delete(gnb); - ue->delete(ue); + gnb->delete_entity(gnb); + ue->delete_entity(ue); free(sdu); free(pdu); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 4f042d4f05..2e3e00f12d 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1125,7 +1125,7 @@ int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t r return((enc_rval.encoded+7)/8); } -NR_MeasConfig_t *get_defaultMeasConfig(int arfcn, int band, int scs) +NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs) { NR_MeasConfig_t *mc = calloc(1, sizeof(*mc)); mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList)); @@ -1137,7 +1137,7 @@ NR_MeasConfig_t *get_defaultMeasConfig(int arfcn, int band, int scs) mo1->measObjectId = 1; mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR; NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1)); - asn1cCallocOne(monr1->ssbFrequency, arfcn); + asn1cCallocOne(monr1->ssbFrequency, ssb_arfcn); asn1cCallocOne(monr1->ssbSubcarrierSpacing, scs); monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility)); monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 5dcff1501a..5bd932ffd4 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -150,7 +150,7 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP, int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier); -NR_MeasConfig_t *get_defaultMeasConfig(int absFreqSSB, int band, int scs); +NR_MeasConfig_t *get_defaultMeasConfig(uint32_t absFreqSSB, int band, int scs); void free_defaultMeasConfig(NR_MeasConfig_t *mc); uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 88c5ad125e..6ead51e3da 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -94,6 +94,13 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); } + if (req->drbs_to_be_released_length > 0) { + int n = req->drbs_to_be_released_length; + f1ap_msg->drbs_to_be_released_length = n; + f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released)); + AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n"); + memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released)); + } if (req->rrc_container_length > 0) { f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 215fc9851d..c37979598a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -238,6 +238,7 @@ typedef enum { typedef struct gNB_RRC_UE_s { drb_t established_drbs[MAX_DRBS_PER_UE]; uint8_t DRB_active[MAX_DRBS_PER_UE]; + NR_DRB_ToReleaseList_t *DRB_ReleaseList; NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity NR_MeasConfig_t *measConfig; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 9160d7213e..e5dcc79dfd 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -46,6 +46,7 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/utils/LOG/log.h" #include "RRC/NR/MESSAGES/asn1_msg.h" +#include "openair2/E1AP/e1ap_asnc.h" #include "NR_BCCH-BCH-Message.h" #include "NR_UL-DCCH-Message.h" @@ -558,8 +559,8 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); - int arfcn = get_dl_arfcn(cell_info); - NR_MeasConfig_t *measconfig = get_defaultMeasConfig(arfcn, band, scs); + uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1); + NR_MeasConfig_t *measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs); uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ue_p, @@ -672,7 +673,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c xid, SRBs, DRBs, - NULL, + ue_p->DRB_ReleaseList, NULL, NULL, dedicatedNAS_MessageList, @@ -680,6 +681,9 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); freeSRBlist(SRBs); freeDRBlist(DRBs); + ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList); + ue_p->DRB_ReleaseList = NULL; + 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", @@ -2855,6 +2859,147 @@ rrc_gNB_generate_RRCRelease( /* UE will be freed after UE context release complete */ } +void rrc_gNB_trigger_new_bearer(int rnti) +{ + /* get RRC and UE */ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti); + if (ue_context_p == NULL) { + LOG_E(RRC, "unknown UE RNTI %04x\n", rnti); + return; + } + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; + + /* get the existing PDU sessoin */ + if (ue->nb_of_pdusessions < 1) { + LOG_E(RRC, "no PDU session set up yet, cannot create additional bearer\n"); + return; + } + + if (ue->established_drbs[0].status != DRB_INACTIVE + && ue->established_drbs[1].status != DRB_INACTIVE) { + LOG_E(RRC, "already have two established bearers, aborting\n"); + return; + } + + e1ap_bearer_setup_req_t bearer_req = {0}; + bearer_req.gNB_cu_cp_ue_id = ue->rrc_ue_id; + bearer_req.cipheringAlgorithm = ue->ciphering_algorithm; + memcpy(bearer_req.encryptionKey, ue->kgnb, sizeof(ue->kgnb)); + bearer_req.integrityProtectionAlgorithm = ue->integrity_algorithm; + memcpy(bearer_req.integrityProtectionKey, ue->kgnb, sizeof(ue->kgnb)); + bearer_req.ueDlAggMaxBitRate = 10000; /* probably does not matter */ + + pdu_session_to_setup_t *pdu = &bearer_req.pduSession[0]; + //bearer_req.numPDUSessions++; + bearer_req.numPDUSessions = 1; + //pdu->sessionId = session->pdusession_id; + //pdu->sst = msg->allowed_nssai[i].sST; + //pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed; + + //pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed; + //pdu->teId = session->gtp_teid; + pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding + DRB_nGRAN_to_setup_t *drb = &pdu->DRBnGRanList[0]; + int drb_id = 2; + drb->id = drb_id; + + drb->defaultDRB = E1AP_DefaultDRB_false; + drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap); + drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap); + + drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18; + drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18; + + drb->discardTimer = E1AP_DiscardTimer_infinity; + drb->reorderingTimer = E1AP_T_Reordering_ms0; + + drb->rLC_Mode = E1AP_RLC_Mode_rlc_am; + + drb->numCellGroups = 1; // assume one cell group associated with a DRB + + for (int k=0; k < drb->numCellGroups; k++) { + cell_group_t *cellGroup = drb->cellGroupList + k; + cellGroup->id = 0; // MCG + } + + int xid = rrc_gNB_get_next_transaction_identifier(0); + /* generate a new bearer, it will be put into internal RRC state and picked + * up later */ + generateDRB(ue, + drb_id, + &ue->pduSession[0], + rrc->configuration.enable_sdap, + rrc->security.do_drb_integrity, + rrc->security.do_drb_ciphering); + + /* associate the new bearer to it */ + ue->xids[xid] = RRC_PDUSESSION_MODIFY; + ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session + LOG_W(RRC, "trigger new bearer %ld for UE %04x xid %d\n", drb->id, ue->rnti, xid); + rrc->cucp_cuup.bearer_context_setup(&bearer_req, 0); +} + +void rrc_gNB_trigger_release_bearer(int rnti) +{ + /* get RRC and UE */ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti); + if (ue_context_p == NULL) { + LOG_E(RRC, "unknown UE RNTI %04x\n", rnti); + return; + } + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; + + if (ue->established_drbs[1].status == DRB_INACTIVE) { + LOG_E(RRC, "no second bearer, aborting\n"); + return; + } + + // don't use E1: bearer release is not implemented, call directly + // into PDCP/SDAP and then send corresponding message via F1 + + int drb_id = 2; + ue->established_drbs[1].status = DRB_INACTIVE; + ue->DRB_ReleaseList = calloc(1, sizeof(*ue->DRB_ReleaseList)); + AssertFatal(ue->DRB_ReleaseList != NULL, "out of memory\n"); + NR_DRB_Identity_t *asn1_drb = malloc(sizeof(*asn1_drb)); + AssertFatal(asn1_drb != NULL, "out of memory\n"); + int idx = 0; + NR_DRB_ToAddModList_t *drb_list = createDRBlist(ue, false); + while (idx < drb_list->list.count) { + const NR_DRB_ToAddMod_t *drbc = drb_list->list.array[idx]; + if (drbc->drb_Identity == drb_id) + break; + ++idx; + } + if (idx < drb_list->list.count) { + nr_pdcp_release_drb(rnti, drb_id); + asn_sequence_del(&drb_list->list, idx, 1); + } + *asn1_drb = drb_id; + asn1cSeqAdd(&ue->DRB_ReleaseList->list, asn1_drb); + + f1ap_drb_to_be_released_t drbs_to_be_released[1] = {{.rb_id = drb_id}}; + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id); + f1ap_ue_context_modif_req_t ue_context_modif_req = { + .gNB_CU_ue_id = ue->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .plmn.mcc = rrc->configuration.mcc[0], + .plmn.mnc = rrc->configuration.mnc[0], + .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, /* TODO: correct value? */ + .srbs_to_be_setup_length = 0, + .srbs_to_be_setup = NULL, + .drbs_to_be_setup_length = 0, + .drbs_to_be_setup = NULL, + .drbs_to_be_released_length = 1, + .drbs_to_be_released = drbs_to_be_released, + }; + rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req); +} + int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t instance, uint8_t CC_id){ const unsigned int Ttab[4] = {32,64,128,256}; uint8_t Tc; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 17bfc108ea..a6a0d9dd07 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -759,7 +759,7 @@ void nr_rrc_manage_rlc_bearers(const NR_CellGroupConfig_t *cellGroupConfig, for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i]; AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n"); - nr_release_rlc_entity(rnti, *lcid); + nr_rlc_release_entity(rnti, *lcid); } } @@ -1460,7 +1460,7 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB NR_UE_RRC_INST_t *ue_rrc = &NR_UE_rrc_inst[ctxt_pP->module_id]; if (radioBearerConfig->srb3_ToRelease) - nr_release_srb(ctxt_pP->rntiMaybeUEid, 3); + nr_pdcp_release_srb(ctxt_pP->rntiMaybeUEid, 3); uint8_t kRRCenc[16] = {0}; uint8_t kRRCint[16] = {0}; @@ -1514,7 +1514,7 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) { NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt]; if (DRB_id) - nr_release_drb(ctxt_pP->rntiMaybeUEid, *DRB_id); + nr_pdcp_release_drb(ctxt_pP->rntiMaybeUEid, *DRB_id); } } diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index b1920b6522..20e9c8c127 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -803,6 +803,32 @@ int gtpv1u_create_x2u_tunnel( AssertFatal( false, "to be developped\n"); } +int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) +{ + pthread_mutex_lock(&globGtp.gtp_lock); + getInstRetInt(compatInst(instance)); + map::iterator ue_it = inst->ue2te_mapping.find(ue_id); + if (ue_it == inst->ue2te_mapping.end()) { + LOG_E(GTPU, "%s() no such UE %ld\n", __func__, ue_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return !GTPNOK; + } + map::iterator rb_it = ue_it->second.bearers.find(rb_id); + if (rb_it == ue_it->second.bearers.end()) { + LOG_E(GTPU, "%s() UE %ld has no bearer %d, available\n", __func__, ue_id, rb_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return !GTPNOK; + } + int teid = rb_it->second.teid_incoming; + globGtp.te2ue_mapping.erase(teid); + ue_it->second.bearers.erase(rb_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id); + for (auto b: ue_it->second.bearers) + LOG_I(GTPU, "bearer %ld\n", b.first); + return !GTPNOK; +} + int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index d57769c509..7ac025f14a 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -98,6 +98,7 @@ extern "C" { in_addr_t newOutgoingAddr, teid_t newOutgoingTeid); + int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id); int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id); int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id); instance_t gtpv1Init(openAddr_t context);