Merge branch 'integration_2023_w39' into 'develop'
integration_2023_w39 See merge request oai/openairinterface5g!2363 * !2142 Fix packing/unpacking procedures for P7 messages * !2253 Parallelize the Compensation, LLR, layer de-mapping, and unscrambling with symbol * !2319 Fix NR UE init RA * !2343 Reverse bits in UCI message when using polar encoding/decoding * !2348 Resolve "SIGSEGV in nr-softmodem @ 100MHz on USRP" * fix phytest-timing thresholds after merge of !2253 * !2320 Reduce ITTI log message volume when queues full * !2360 nr rlc: minor: fix tests * !2359 nr rlc am: bugfix: correct usage of tx_next * !2356 Const return values * !2357 Fix compile error when --build-e2 option included * !2340 Resolve "gNB build on ubuntu 22.04 fails with dpkg error" * !2362 Implement F1 bearer release and add telnet module * !2324 Refactor gNB ULSCH decoding * fix for SSB ARFCN in RRC MeasConfig
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<eNB_instance>1</eNB_instance>
|
||||
<eNB_serverId>1</eNB_serverId>
|
||||
<forced_workspace_cleanup>True</forced_workspace_cleanup>
|
||||
<proxy_commit>f390610304baf6b66e4ec8cc00bf91398a651172</proxy_commit>
|
||||
<proxy_commit>b64d9bce986b38ca59e8582864ade3fcdd05c0dc</proxy_commit>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<eNB_instance>1</eNB_instance>
|
||||
<eNB_serverId>1</eNB_serverId>
|
||||
<forced_workspace_cleanup>True</forced_workspace_cleanup>
|
||||
<proxy_commit>f390610304baf6b66e4ec8cc00bf91398a651172</proxy_commit>
|
||||
<proxy_commit>b64d9bce986b38ca59e8582864ade3fcdd05c0dc</proxy_commit>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "byte_array.h"
|
||||
|
||||
#include "common/utils/assertions.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ../../..
|
||||
)
|
||||
|
||||
|
||||
@@ -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 <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <execinfo.h>
|
||||
|
||||
#include <nfapi_interface.h>
|
||||
#include <nfapi_nr_interface_scf.h>
|
||||
#include <nfapi.h>
|
||||
#include <debug.h>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+1462
-1136
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -83,4 +83,15 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB,
|
||||
int32_t srs_estimated_channel_time_shifted[][1<<srs_pdu->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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)pbch->pbch_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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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<nb_re; 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_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<nb_re; i++) {
|
||||
for (int i = 0; i < ((nb_re + 7) >> 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<nb_re256; 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_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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_left)-1);
|
||||
decodedPayload[0] = pucch_pdu->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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)pbch_a_prime>>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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; r<harq_process->C; 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 ++){
|
||||
|
||||
@@ -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,
|
||||
|
||||
+45
-12
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 <math.h>
|
||||
|
||||
//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)<<n);
|
||||
for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
|
||||
@@ -123,7 +124,7 @@ uint32_t nr_compute_tbslbrm(uint16_t table,
|
||||
// Intermediate number of information bits
|
||||
Ninfo = (nb_re * R * Qm * Nl)>>10;
|
||||
|
||||
if (Ninfo <=3824) {
|
||||
if (Ninfo <= NR_MAX_PDSCH_TBS) {
|
||||
n = max(3, floor(log2(Ninfo)) - 6);
|
||||
Np_info = max(24, (Ninfo>>n)<<n);
|
||||
for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
|
||||
@@ -132,8 +133,7 @@ uint32_t nr_compute_tbslbrm(uint16_t table,
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
n = log2(Ninfo-24)-5;
|
||||
Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "openair1/PHY/defs_nr_common.h"
|
||||
#include <limits.h>
|
||||
#include <executables/softmodem-common.h>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
+148
-3
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<uint64_t, teidData_t>::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<ue_id_t, gtpv1u_bearer_t>::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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user