Commit 9bac5338 authored by Florian Kaltenberger's avatar Florian Kaltenberger

Merge branch '409-merge-ulschsim-containing-pusch-encoding-and-decoding' into 'develop-nr'

Resolve "Merge ulschsim containing PUSCH encoding and decoding"

See merge request oai/openairinterface5g!532
parents aef2d908 4af9f321
cmake_targets/log/
cmake_targets/ran_build/
cmake_targets/*/build/
targets/bin/
......@@ -252,9 +252,9 @@ case $key in
VM_NAME=ci-phy-sim
ARCHIVES_LOC=phy_sim
LOG_PATTERN=.Rel15.txt
NB_PATTERN_FILES=8
NB_PATTERN_FILES=9
BUILD_OPTIONS="--phy_simulators"
VM_MEMORY=4096
VM_MEMORY=8192
RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b"
NBARGS=$[$NBARGS+256]
shift
......@@ -331,9 +331,9 @@ case $key in
VM_NAME=ci-phy-sim
ARCHIVES_LOC=phy_sim
LOG_PATTERN=.Rel15.txt
NB_PATTERN_FILES=8
NB_PATTERN_FILES=9
BUILD_OPTIONS="--phy_simulators"
VM_MEMORY=4096
VM_MEMORY=8192
RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b"
NBARGS=$[$NBARGS+256]
;;
......
......@@ -671,7 +671,7 @@ add_boolean_option(EXMIMO_IOT True "????")
add_boolean_option(LOCALIZATION False "???")
add_integer_option(MAX_NUM_CCs 1 "????")
add_boolean_option(MU_RECEIVER False "????")
add_boolean_option(PHYSIM True "for L1 simulators (dlsim, ulsim, ...)")
add_boolean_option(PHYSIM False "for L1 simulators (dlsim, ulsim, ...)")
add_boolean_option(PHY_CONTEXT True "not clear: must remain False for dlsim")
add_boolean_option(PHY_EMUL False "not clear: must remain False for dlsim")
add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator")
......@@ -1275,6 +1275,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c
......@@ -1304,6 +1305,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
......@@ -2526,6 +2528,12 @@ add_executable(nr_dlsim
${T_SOURCE})
target_link_libraries(nr_dlsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_NR -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl)
add_executable(nr_ulschsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c
${OPENAIR_DIR}/common/utils/backtrace.c
${T_SOURCE})
target_link_libraries(nr_ulschsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl)
foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim)
......
......@@ -691,7 +691,7 @@ function main() {
echo_info "Compiling unitary tests simulators"
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
#simlist="dlsim_tm4 dlsim ulsim pucchsim prachsim pdcchsim pbchsim mbmssim"
simlist="dlsim ulsim polartest ldpctest nr_pbchsim nr_dlschsim nr_dlsim"
simlist="dlsim ulsim polartest ldpctest nr_pbchsim nr_dlschsim nr_dlsim nr_ulschsim"
for f in $simlist ; do
compilations \
phy_simulators $f \
......
......@@ -673,4 +673,45 @@ typedef struct {
nfapi_vendor_extension_tlv_t vendor_extension;
} nfapi_nr_dl_config_request_t;
typedef enum {nr_pusch_freq_hopping_disabled = 0 ,
nr_pusch_freq_hopping_enabled = 1
} nr_pusch_freq_hopping_t;
typedef struct{
uint8_t aperiodicSRS_ResourceTrigger;
} nfapi_nr_ul_srs_config_t;
typedef struct {
uint8_t bandwidth_part_ind;
uint16_t number_rbs;
uint16_t start_rb;
uint8_t frame_offset;
uint16_t number_symbols;
uint16_t start_symbol;
nr_pusch_freq_hopping_t pusch_freq_hopping;
uint8_t mcs;
uint8_t Qm;
uint8_t ndi;
uint8_t rv;
uint8_t harq_process_nbr;
int8_t accumulated_delta_PUSCH;
int8_t absolute_delta_PUSCH;
uint8_t n_layers;
uint8_t tpmi;
uint8_t n_dmrs_cdm_groups;
uint8_t dmrs_ports[4];
uint8_t n_front_load_symb;
nfapi_nr_ul_srs_config_t srs_config;
uint8_t csi_reportTriggerSize;
uint8_t maxCodeBlockGroupsPerTransportBlock;
uint8_t ptrs_dmrs_association_port;
uint8_t beta_offset_ind;
} nfapi_nr_ul_config_ulsch_pdu_rel15_t;
typedef struct {
uint16_t rnti;
nfapi_nr_ul_config_ulsch_pdu_rel15_t ulsch_pdu_rel15;
} nfapi_nr_ul_config_ulsch_pdu;
#endif
......@@ -453,7 +453,7 @@ int32_t nr_segmentation(unsigned char *input_buffer,
unsigned int B,
unsigned int *C,
unsigned int *K,
unsigned int *Zout,
unsigned int *Zout,
unsigned int *F);
uint32_t nr_compute_tbs(uint8_t mcs,
......
......@@ -32,6 +32,7 @@
#include "coding_defs.h"
#include "assertions.h"
/*ref 36-212 v8.6.0 , pp 8-9 */
/* the highest degree is set by default */
......@@ -275,7 +276,7 @@ int check_crc(uint8_t* decoded_bytes, uint32_t n, uint32_t F, uint8_t crc_type)
break;
default:
crc_len=3;
AssertFatal(1,"Invalid crc_type \n");
}
for (int i=0; i<crc_len; i++)
......@@ -309,6 +310,9 @@ int check_crc(uint8_t* decoded_bytes, uint32_t n, uint32_t F, uint8_t crc_type)
crc = crc8(decoded_bytes,
n-8)>>24;
break;
default:
AssertFatal(1,"Invalid crc_type \n");
}
if (crc == oldcrc)
......
......@@ -34,7 +34,7 @@ int32_t nr_segmentation(unsigned char *input_buffer,
unsigned int B,
unsigned int *C,
unsigned int *K,
unsigned int *Zout,
unsigned int *Zout, // [hna] Zout is Zc
unsigned int *F)
{
......
......@@ -33,6 +33,7 @@
#include "assertions.h"
#include <math.h>
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
#include "SCHED_NR/fapi_nr_l1.h"
......@@ -77,12 +78,14 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
unsigned char abstraction_flag) {
// shortcuts
NR_DL_FRAME_PARMS *const fp = &gNB->frame_parms;
nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
NR_gNB_COMMON *const common_vars = &gNB->common_vars;
LTE_eNB_PUSCH **const pusch_vars = gNB->pusch_vars;
LTE_eNB_SRS *const srs_vars = gNB->srs_vars;
LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars;
LTE_eNB_PUSCH **const pusch_vars = gNB->pusch_vars;
LTE_eNB_SRS *const srs_vars = gNB->srs_vars;
LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars;
int i, UE_id;
LOG_I(PHY,"[gNB %d] %s() About to wait for gNB to be configured\n", gNB->Mod_id, __FUNCTION__);
gNB->total_dlsch_bitrate = 0;
gNB->total_transmitted_bits = 0;
......@@ -110,7 +113,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
init_dfts();
// PBCH DMRS gold sequences generation
nr_init_pbch_dmrs(gNB);
// Polar encoder init for PBCH
//PDCCH DMRS init
gNB->nr_gold_pdcch_dmrs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **));
uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs;
......@@ -148,6 +150,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
}
nr_init_pdsch_dmrs(gNB, cfg->sch_config.physical_cell_id.value);
/// Transport init necessary for NR synchro
init_nr_transport(gNB);
......@@ -167,14 +170,15 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
gNB->first_run_I0_measurements =
1; ///This flag used to be static. With multiple gNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
common_vars->rxdata = (int32_t **)NULL;
common_vars->txdataF = (int32_t **)malloc16(15*sizeof(int32_t *));
common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t *));
for (i=0; i<15; i++) {
common_vars->txdataF[i] = (int32_t *)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t) );
LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n",
i,common_vars->txdataF[i],
fp->samples_per_frame_wCP*sizeof(int32_t));
common_vars->txdataF = (int32_t **)malloc16(15*sizeof(int32_t*));
common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t*));
for (i=0;i<15;i++){
common_vars->txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t) ); // [hna] samples_per_frame without CP
LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n",
i,common_vars->txdataF[i],
fp->samples_per_frame_wCP*sizeof(int32_t));
}
// Channel estimates for SRS
......@@ -422,6 +426,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
gNB_config->rf_config.ul_carrier_bandwidth.value,
gNB_config->sch_config.physical_cell_id.value,
fp->dl_CarrierFreq );
nr_init_frame_parms(gNB_config, fp);
if (RC.gNB[Mod_id][CC_id]->configured == 1) {
......@@ -441,6 +446,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB) {
LOG_I(PHY, "Initialise nr transport\n");
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
for (j=0; j<2; j++) {
......@@ -450,29 +456,38 @@ void init_nr_transport(PHY_VARS_gNB *gNB) {
LOG_E(PHY,"Can't get gNB dlsch structures for UE %d \n", i);
exit(-1);
}/* else {
gNB->dlsch[i][j]->rnti=0;
LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,gNB->dlsch[i][j], gNB->dlsch[i][j]->rnti);
gNB->dlsch[i][j]->rnti=0;
LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,gNB->dlsch[i][j], gNB->dlsch[i][j]->rnti);
}*/
///////////////////////// Initializing gNB ULSCH /////////////////////////
LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i);
// ULSCH for RA
if(i==0) {
gNB->ulsch[i][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0);
if (!gNB->ulsch[i][j]) {
LOG_E(PHY,"Can't get gNB ulsch structures\n");
exit(-1);
}
}
// ULSCH for data
gNB->ulsch[i+1][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0);
if (!gNB->ulsch[i+1][j]) {
LOG_E(PHY,"Can't get gNB ulsch structures\n");
exit(-1);
}
//////////////////////////////////////////////////////////////////////////
}
//LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i);
//gNB->ulsch[1+i] = new_gNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0);
/*if (!gNB->ulsch[1+i]) {
LOG_E(PHY,"Can't get gNB ulsch structures\n");
exit(-1);
}*/
// this is the transmission mode for the signalling channels
// this will be overwritten with the real transmission mode by the RRC once the UE is connected
//gNB->transmission_mode[i] = fp->nb_antenna_ports_gNB==1 ? 1 : 2;
}
// ULSCH for RA
//gNB->ulsch[0] = new_gNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0);
/*if (!gNB->ulsch[0]) {
LOG_E(PHY,"Can't get gNB ulsch structures\n");
exit(-1);
}*/
gNB->dlsch_SI = new_gNB_dlsch(1,8,NSOFT, 0, fp, cfg);
LOG_D(PHY,"gNB %d.%d : SI %p\n",gNB->Mod_id,gNB->CC_id,gNB->dlsch_SI);
gNB->dlsch_ra = new_gNB_dlsch(1,8,NSOFT, 0, fp, cfg);
......
......@@ -361,8 +361,13 @@ void phy_config_harq_ue(module_id_t Mod_id,int CC_id,uint8_t eNB_id,
uint16_t max_harq_tx )
{
int num_of_threads,num_of_code_words;
PHY_VARS_NR_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id];
phy_vars_ue->ulsch[eNB_id]->Mlimit = max_harq_tx;
for (num_of_threads=0;num_of_threads<RX_NB_TH_MAX;num_of_threads++)
for (num_of_code_words=0;num_of_code_words<NR_MAX_NB_CODEWORDS;num_of_code_words++)
phy_vars_ue->ulsch[eNB_id][num_of_threads][num_of_code_words]->Mlimit = max_harq_tx;
}
extern uint16_t beta_cqi[16];
......@@ -920,14 +925,14 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue,int abstraction_flag) {
for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
for (j=0; j<2; j++) {
for (k=0; k<RX_NB_TH_MAX; k++) {
AssertFatal((ue->dlsch[k][i][j] = new_nr_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag))!=NULL,"Can't get ue dlsch structures\n");
AssertFatal((ue->dlsch[k][i][j] = new_nr_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag))!=NULL,"Can't get ue dlsch structures\n");
LOG_D(PHY,"dlsch[%d][%d][%d] => %p\n",k,i,j,ue->dlsch[k][i][j]);
LOG_D(PHY,"dlsch[%d][%d][%d] => %p\n",k,i,j,ue->dlsch[k][i][j]);
AssertFatal((ue->ulsch[k][i][j] = new_nr_ue_ulsch(ue->frame_parms.N_RB_UL, NUMBER_OF_HARQ_PID_MAX, abstraction_flag))!=NULL,"Can't get ue ulsch structures\n");
LOG_D(PHY,"ulsch[%d][%d][%d] => %p\n",k,i,j,ue->ulsch[k][i][j]);
}
}
//AssertFatal((ue->ulsch[i] = new_ue_ulsch(ue->frame_parms.N_RB_UL, abstraction_flag))!=NULL,"Can't get ue ulsch structures\n");
ue->dlsch_SI[i] = new_nr_ue_dlsch(1,1,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag);
ue->dlsch_ra[i] = new_nr_ue_dlsch(1,1,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag);
......
......@@ -69,7 +69,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch)
#endif
if (dlsch->harq_processes[i]->b) {
free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES);
free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES); //this should be MAX_NR_DLSCH_PAYLOAD_BYTES
dlsch->harq_processes[i]->b = NULL;
#ifdef DEBUG_DLSCH_FREE
printf("Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b);
......@@ -195,8 +195,11 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(unsigned char Kmimo,
if (abstraction_flag==0) {
for (r=0; r<MAX_NUM_NR_DLSCH_SEGMENTS/bw_scaling; r++) {
// account for filler in first segment and CRCs for multiple segment case
// [hna] 8448 is the maximum CB size in NR
// 68*348 = 68*(maximum size of Zc)
// In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc)
dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(8448);
dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384);
dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output
if (dlsch->harq_processes[i]->c[r]) {
bzero(dlsch->harq_processes[i]->c[r],8448);
} else {
......@@ -272,7 +275,6 @@ int nr_dlsch_encoding(unsigned char *a,
unsigned int G;
unsigned int crc=1;
uint8_t harq_pid = dlsch->harq_ids[slot];
nfapi_nr_dl_config_dlsch_pdu_rel15_t rel15 = dlsch->harq_processes[harq_pid]->dlsch_pdu.dlsch_pdu_rel15;
uint16_t nb_rb = rel15.n_prb;
......@@ -302,7 +304,9 @@ int nr_dlsch_encoding(unsigned char *a,
A = rel15.transport_block_size;
G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15.nb_layers);
LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order);
Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, rel15.nb_layers);
......@@ -328,6 +332,7 @@ int nr_dlsch_encoding(unsigned char *a,
dlsch->harq_processes[harq_pid]->B = A+24;
// dlsch->harq_processes[harq_pid]->b = a;
memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);
nr_segmentation(dlsch->harq_processes[harq_pid]->b,
......@@ -335,7 +340,7 @@ int nr_dlsch_encoding(unsigned char *a,
dlsch->harq_processes[harq_pid]->B,
&dlsch->harq_processes[harq_pid]->C,
&dlsch->harq_processes[harq_pid]->K,
pz,
pz, // [hna] pz is Zc
&dlsch->harq_processes[harq_pid]->F);
F = dlsch->harq_processes[harq_pid]->F;
......@@ -388,6 +393,7 @@ int nr_dlsch_encoding(unsigned char *a,
//stop_meas(te_stats);
//printf("end ldpc encoder -- output\n");
//write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4);
#ifdef DEBUG_DLSCH_CODING
write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4);
write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[0][0],(3*8*Kr_bytes)+12,1,4);
......@@ -429,6 +435,7 @@ int nr_dlsch_encoding(unsigned char *a,
rel15.redundancy_version,
E);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset);
......@@ -442,6 +449,7 @@ int nr_dlsch_encoding(unsigned char *a,
dlsch->harq_processes[harq_pid]->f+r_offset);
//stop_meas(i_stats);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset);
......@@ -455,5 +463,5 @@ int nr_dlsch_encoding(unsigned char *a,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return(0);
return 0;
}
......@@ -38,7 +38,7 @@
#define MAX_NUM_NR_ULSCH_SEGMENTS MAX_NUM_NR_DLSCH_SEGMENTS
#define MAX_NR_DLSCH_PAYLOAD_BYTES (MAX_NUM_NR_DLSCH_SEGMENTS*1056)
#define MAX_NR_ULSCH_PAYLOAD_BYTES (MAX_NUM_NR_DLSCH_SEGMENTS*1056)
#define MAX_NR_ULSCH_PAYLOAD_BYTES (MAX_NUM_NR_ULSCH_SEGMENTS*1056)
#define MAX_NUM_NR_CHANNEL_BITS (14*273*12*6) // 14 symbols, 273 RB
#define MAX_NUM_NR_RE (14*273*12)
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_TRANSPORT/nr_ulsch.h
* \brief functions used for PUSCH/ULSCH physical and transport channels for gNB
* \author Ahmed Hussein
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: ahmed.hussein@iis.fraunhofer.de
* \note
* \warning
*/
#include "PHY/defs_gNB.h"
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch);
NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag);
uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t UE_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
uint8_t llr8_flag);
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding.c
* \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12
* \author Ahmed Hussein
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: ahmed.hussein@iis.fraunhofer.de
* \note
* \warning
*/
// [from gNB coding]
#include "PHY/defs_gNB.h"
#include "PHY/phy_extern.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "SCHED_NR/sched_nr.h"
#include "defs.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/LOG/log.h"
#include <syscall.h>
//#define DEBUG_ULSCH_DECODING
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
static uint64_t nb_total_decod =0;
static uint64_t nb_error_decod =0;
//extern double cpuf;
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch)
{
int i,r;
if (ulsch) {
for (i=0; i<NR_MAX_ULSCH_HARQ_PROCESSES; i++) {
if (ulsch->harq_processes[i]) {
if (ulsch->harq_processes[i]->b) {
free16(ulsch->harq_processes[i]->b,MAX_NR_ULSCH_PAYLOAD_BYTES);
ulsch->harq_processes[i]->b = NULL;
}
for (r=0; r<MAX_NUM_NR_ULSCH_SEGMENTS; r++) {
free16(ulsch->harq_processes[i]->c[r],(8448)*sizeof(uint8_t));
ulsch->harq_processes[i]->c[r] = NULL;
}
for (r=0; r<MAX_NUM_NR_ULSCH_SEGMENTS; r++) {
if (ulsch->harq_processes[i]->d[r]) {
free16(ulsch->harq_processes[i]->d[r],(68*384)*sizeof(int16_t));
ulsch->harq_processes[i]->d[r] = NULL;
}
}
for (r=0; r<(MAX_NUM_NR_ULSCH_SEGMENTS); r++) {
if (ulsch->harq_processes[i]->p_nrLDPC_procBuf[r]){
nrLDPC_free_mem(ulsch->harq_processes[i]->p_nrLDPC_procBuf[r]);
ulsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL;
}
}
free16(ulsch->harq_processes[i],sizeof(NR_UL_gNB_HARQ_t));
ulsch->harq_processes[i] = NULL;
}
}
free16(ulsch,sizeof(NR_gNB_ULSCH_t));
ulsch = NULL;
}
}
NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag)
{
NR_gNB_ULSCH_t *ulsch;
uint8_t exit_flag = 0,i,r;
unsigned char bw_scaling =1;
switch (N_RB_UL) {
case 106:
bw_scaling =2;
break;
default:
bw_scaling =1;
break;
}
ulsch = (NR_gNB_ULSCH_t *)malloc16(sizeof(NR_gNB_ULSCH_t));
if (ulsch) {
memset(ulsch,0,sizeof(NR_gNB_ULSCH_t));
ulsch->max_ldpc_iterations = max_ldpc_iterations;
ulsch->Mlimit = 4;
for (i=0; i<NR_MAX_ULSCH_HARQ_PROCESSES; i++) {
ulsch->harq_processes[i] = (NR_UL_gNB_HARQ_t *)malloc16(sizeof(NR_UL_gNB_HARQ_t));
if (ulsch->harq_processes[i]) {
memset(ulsch->harq_processes[i],0,sizeof(NR_UL_gNB_HARQ_t));
ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling);
if (ulsch->harq_processes[i]->b)
memset(ulsch->harq_processes[i]->b,0,MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling);
else
exit_flag=3;
if (abstraction_flag == 0) {
for (r=0; r<MAX_NUM_NR_ULSCH_SEGMENTS/bw_scaling; r++) {
ulsch->harq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem();
ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(8448*sizeof(uint8_t));
if (ulsch->harq_processes[i]->c[r])
memset(ulsch->harq_processes[i]->c[r],0,8448*sizeof(uint8_t));
else
exit_flag=2;
ulsch->harq_processes[i]->d[r] = (int16_t*)malloc16((68*384)*sizeof(int16_t));
if (ulsch->harq_processes[i]->d[r])
memset(ulsch->harq_processes[i]->d[r],0,(68*384)*sizeof(int16_t));
else
exit_flag=2;
}
}
} else {
exit_flag=1;
}
}
if (exit_flag==0)
return(ulsch);
}
printf("new_gNB_ulsch with size %zu: exit_flag = %u\n",sizeof(NR_UL_gNB_HARQ_t), exit_flag);
free_gNB_ulsch(ulsch);
return(NULL);
}
uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t UE_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
uint8_t llr8_flag)
{
uint32_t A,E;
uint32_t G;
uint32_t ret,offset;
int32_t no_iteration_ldpc, length_dec;
uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0;
uint8_t crc_type;
int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32)));
NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid];
nfapi_nr_ul_config_ulsch_pdu_rel15_t *nfapi_ulsch_pdu_rel15 = &harq_process->ulsch_pdu.ulsch_pdu_rel15;
t_nrLDPC_dec_params decParams;
t_nrLDPC_dec_params* p_decParams = &decParams;
t_nrLDPC_time_stats procTime;
t_nrLDPC_time_stats* p_procTime = &procTime ;
t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf;
int16_t z [68*384];
int8_t l [68*384];
int16_t inv_d [68*384];
uint8_t kc;
uint8_t Ilbrm = 0;
uint32_t Tbslbrm = 950984;
uint16_t nb_rb = 30; //to update
uint8_t nb_re_dmrs = 6;
uint16_t length_dmrs = 1;
double Coderate = 0.0;
uint32_t i,j;
__m128i *pv = (__m128i*)&z;
__m128i *pl = (__m128i*)&l;
if (!ulsch_llr) {
printf("ulsch_decoding.c: NULL ulsch_llr pointer\n");
return(ulsch->max_ldpc_iterations);
}
if (!harq_process) {
printf("ulsch_decoding.c: NULL harq_process pointer\n");
return(ulsch->max_ldpc_iterations);
}
if (!frame_parms) {
printf("ulsch_decoding.c: NULL frame_parms pointer\n");
return(ulsch->max_ldpc_iterations);
}
nb_rb = nfapi_ulsch_pdu_rel15->number_rbs;
// harq_process->trials[nfapi_ulsch_pdu_rel15->round]++;
harq_process->TBS = nr_compute_tbs(nfapi_ulsch_pdu_rel15->mcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->n_layers);
A = harq_process->TBS;
ret = ulsch->max_ldpc_iterations;
harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->Qm,nfapi_ulsch_pdu_rel15->n_layers);
G = harq_process->G;
LOG_I(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nfapi_ulsch_pdu_rel15->mcs, nfapi_ulsch_pdu_rel15->n_layers, nb_symb_sch,nb_rb);
if (harq_process->round == 0) {
// This is a new packet, so compute quantities regarding segmentation
harq_process->B = A+24;
// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F)
nr_segmentation(NULL,
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z, // [hna] Z is Zc
&harq_process->F);
p_decParams->Z = harq_process->Z;
#ifdef DEBUG_ULSCH_DECODING
printf("ulsch decoding nr segmentation Z %d\n", p_decParams->Z);
if (!frame%100)
printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl);
#endif
}
Coderate = (float) A /(float) G;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){
p_decParams->BG = 2;
if (Coderate < 0.3333) {
p_decParams->R = 15;
kc = 52;
}
else if (Coderate <0.6667) {
p_decParams->R = 13;
kc = 32;
}
else {
p_decParams->R = 23;
kc = 17;
}
} else {
p_decParams->BG = 1;
if (Coderate < 0.6667) {
p_decParams->R = 13;
kc = 68;
}
else if (Coderate <0.8889) {
p_decParams->R = 23;
kc = 35;
}
else {
p_decParams->R = 89;
kc = 27;
}
}
//printf("coderate %f kc %d \n", Coderate, kc);
p_decParams->numMaxIter = ulsch->max_ldpc_iterations;
p_decParams->outMode= 0;
err_flag = 0;
r_offset = 0;
unsigned char bw_scaling =1;
switch (frame_parms->N_RB_UL) {
case 106:
bw_scaling =2;
break;
default:
bw_scaling =1;
break;
}
if (harq_process->C > MAX_NUM_NR_ULSCH_SEGMENTS/bw_scaling) {
LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,MAX_NUM_NR_ULSCH_SEGMENTS/bw_scaling);
return((1+ulsch->max_ldpc_iterations));
}
#ifdef DEBUG_ULSCH_DECODING
printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
#endif
opp_enabled=1;
Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb"
Kr_bytes = Kr>>3;
K_bytes_F = Kr_bytes-(harq_process->F>>3);
Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, nfapi_ulsch_pdu_rel15->n_layers);
for (r=0; r<harq_process->C; r++) {
E = nr_get_E(G, harq_process->C, nfapi_ulsch_pdu_rel15->Qm, nfapi_ulsch_pdu_rel15->n_layers, r);
#if gNB_TIMING_TRACE
start_meas(ulsch_deinterleaving_stats);
#endif
////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// ulsch_llr =====> harq_process->e //////////////////////////////
nr_deinterleaving_ldpc(E,
nfapi_ulsch_pdu_rel15->Qm,
harq_process->e[r],
ulsch_llr+r_offset);
//for (int i =0; i<16; i++)
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
#if gNB_TIMING_TRACE
stop_meas(ulsch_deinterleaving_stats);
#endif
#if gNB_TIMING_TRACE
start_meas(ulsch_rate_unmatching_stats);
#endif
#ifdef DEBUG_ULSCH_DECODING
LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
harq_pid,r, G,
Kr*3,
harq_process->TBS,
nfapi_ulsch_pdu_rel15->Qm,
nfapi_ulsch_pdu_rel15->number_rbs,
nfapi_ulsch_pdu_rel15->n_layers,
nfapi_ulsch_pdu_rel15->rv,
harq_process->round);
#endif
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// harq_process->e =====> harq_process->d /////////////////////////
if (nr_rate_matching_ldpc_rx(Ilbrm,
Tbslbrm,
p_decParams->BG,
p_decParams->Z,
harq_process->d[r],
harq_process->e[r],
harq_process->C,
nfapi_ulsch_pdu_rel15->rv,
(harq_process->round==0)?1:0,
E)==-1) {
#if gNB_TIMING_TRACE
stop_meas(ulsch_rate_unmatching_stats);
#endif
LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n");
return(ulsch->max_ldpc_iterations);
} else {
#if gNB_TIMING_TRACE
stop_meas(ulsch_rate_unmatching_stats);
#endif
}
r_offset += E;
#ifdef DEBUG_ULSCH_DECODING
if (r==0) {
write_output("decoder_llr.m","decllr",ulsch_llr,G,1,0);
write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
}
printf("decoder input(segment %d) :",r);
int i;
for (i=0;i<(3*8*Kr_bytes)+12;i++)
printf("%d : %d\n",i,harq_process->d[r][i]);
printf("\n");
#endif
// printf("Clearing c, %p\n",harq_process->c[r]);
memset(harq_process->c[r],0,Kr_bytes);
// printf("done\n");
if (harq_process->C == 1) {
crc_type = CRC24_A;
length_dec = harq_process->B;
}
else {
crc_type = CRC24_B;
length_dec = (harq_process->B+24*harq_process->C)/harq_process->C;
}
if (err_flag == 0) {
#if gNB_TIMING_TRACE
start_meas(ulsch_turbo_decoding_stats);
#endif
//LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A);
memset(pv,0,2*harq_process->Z*sizeof(int16_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) {
pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
}
for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) {
pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) {
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
p_nrLDPC_procBuf[r],
p_procTime);
if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
printf("Segment %d CRC OK\n",r);
ret = 2;
} else {
printf("CRC NOK\n");
ret = 1+ulsch->max_ldpc_iterations;
}
nb_total_decod++;
if (no_iteration_ldpc > ulsch->max_ldpc_iterations){
nb_error_decod++;
}
ret=no_iteration_ldpc;
for (int m=0; m < Kr>>3; m ++) {
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
#ifdef DEBUG_ULSCH_DECODING
//printf("output decoder %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 k=0;k<A>>3;k++)
printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
printf("no_iterations_ldpc %d (ret %d)\n",no_iteration_ldpc,ret);
//write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4);
#endif
#if gNB_TIMING_TRACE
stop_meas(ulsch_turbo_decoding_stats);
#endif
}
if ((err_flag == 0) && (ret>=(1+ulsch->max_ldpc_iterations))) {
// a Code segment is in error so break;
LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1);
err_flag = 1;
}
//////////////////////////////////////////////////////////////////////////////////////////
}
int32_t frame_rx_prev = frame;
int32_t tti_rx_prev = nr_tti_rx - 1;
if (tti_rx_prev < 0) {
frame_rx_prev--;
tti_rx_prev += 10*frame_parms->ttis_per_subframe;
}
frame_rx_prev = frame_rx_prev%1024;
if (err_flag == 1) {
#if gNB_DEBUG_TRACE
LOG_I(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
phy_vars_gNB->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round);
#endif
// harq_process->harq_ack.ack = 0;
// harq_process->harq_ack.harq_id = harq_pid;
// harq_process->harq_ack.send_harq_status = 1;
// harq_process->errors[harq_process->round]++;
harq_process->round++;
if (harq_process->round >= ulsch->Mlimit) {
harq_process->status = SCH_IDLE;
harq_process->round = 0;
harq_process->handled = 0;
ulsch->harq_mask &= ~(1 << harq_pid);
}
if(is_crnti) {
LOG_D(PHY,"[gNB %d] ULSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
phy_vars_gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,ulsch->Mlimit,harq_process->TBS);
}
harq_process->handled = 1;
return((1+ulsch->max_ldpc_iterations));
} else {
#if gNB_DEBUG_TRACE
LOG_I(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n",
phy_vars_gNB->Mod_id,nr_tti_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round);
#endif
harq_process->status = SCH_IDLE;
harq_process->round = 0;
// harq_process->handled = 0;
ulsch->harq_mask &= ~(1 << harq_pid);
// harq_process->harq_ack.ack = 1;
// harq_process->harq_ack.harq_id = harq_pid;
// harq_process->harq_ack.send_harq_status = 1;
if(is_crnti)
{
LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS);
}
}
// Reassembly of Transport block here
offset = 0;
Kr = harq_process->K;
Kr_bytes = Kr>>3;
for (r=0; r<harq_process->C; r++) {
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));
#ifdef DEBUG_ULSCH_DECODING
printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
printf("copied %d bytes to b sequence (harq_pid %d)\n",
(Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
printf("b[0] = %x,c[%d] = %x\n",
harq_process->b[offset],
harq_process->F>>3,
harq_process->c[r]);
#endif
}
ulsch->last_iteration_cnt = ret;
return(ret);
}
\ No newline at end of file
......@@ -76,11 +76,11 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch)
}
for (r=0; r<(MAX_NUM_NR_DLSCH_SEGMENTS); r++) {
if (dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]){
nrLDPC_free_mem(dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]);
dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL;
}
}
if (dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]){
nrLDPC_free_mem(dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]);
dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL;
}
}
free16(dlsch->harq_processes[i],sizeof(NR_DL_UE_HARQ_t));
dlsch->harq_processes[i] = NULL;
......@@ -143,7 +143,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint
if (abstraction_flag == 0) {
for (r=0; r<MAX_NUM_NR_DLSCH_SEGMENTS/bw_scaling; r++) {
dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem();
dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem();
dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(1056);
if (dlsch->harq_processes[i]->c[r])
......@@ -192,7 +192,7 @@ void nr_dlsch_unscrambling(int16_t* llr,
reset = 0;
}
if (((s>>(i&0x1f))&1)==1)
llr[i] = -llr[i];
llr[i] = -llr[i];
}
}
......@@ -203,7 +203,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_process,
uint32_t frame,
uint16_t nb_symb_sch,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
......@@ -247,7 +247,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
//NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0];
if (!dlsch_llr) {
if (!dlsch_llr) {
printf("dlsch_decoding.c: NULL dlsch_llr pointer\n");
return(dlsch->max_ldpc_iterations);
}
......@@ -305,57 +305,59 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
// This is a new packet, so compute quantities regarding segmentation
harq_process->B = A+24;
nr_segmentation(NULL,
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z, // [hna] Z is Zc
&harq_process->F);
p_decParams->Z = harq_process->Z;
#ifdef DEBUG_DLSCH_DECODING
printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z);
if (!frame%100)
printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl);
if (!frame%100)
printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl);
#endif
}
Coderate = (float) A /(float) G;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){
p_decParams->BG = 2;
if (Coderate < 0.3333){
p_decParams->R = 15;
kc = 52;
}
else if (Coderate <0.6667){
p_decParams->R = 13;
kc = 32;
}
else {
p_decParams->R = 23;
kc = 17;
}
}
else{
p_decParams->BG = 1;
if (Coderate < 0.6667){
p_decParams->R = 13;
kc = 68;
}
else if (Coderate <0.8889){
p_decParams->R = 23;
kc = 35;
}
else {
p_decParams->R = 89;
kc = 27;
}
}
//printf("coderate %f kc %d \n", Coderate, kc);
p_decParams->numMaxIter = dlsch->max_ldpc_iterations;
p_decParams->outMode= 0;
Coderate = (float) A /(float) G;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
{
p_decParams->BG = 2;
if (Coderate < 0.3333){
p_decParams->R = 15;
kc = 52;
}
else if (Coderate <0.6667){
p_decParams->R = 13;
kc = 32;
}
else {
p_decParams->R = 23;
kc = 17;
}
}
else{
p_decParams->BG = 1;
if (Coderate < 0.6667){
p_decParams->R = 13;
kc = 68;
}
else if (Coderate <0.8889){
p_decParams->R = 23;
kc = 35;
}
else {
p_decParams->R = 89;
kc = 27;
}
}
//printf("coderate %f kc %d \n", Coderate, kc);
p_decParams->numMaxIter = dlsch->max_ldpc_iterations;
p_decParams->outMode= 0;
err_flag = 0;
r_offset = 0;
......@@ -363,27 +365,27 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
unsigned char bw_scaling =1;
switch (frame_parms->N_RB_DL) {
case 106:
bw_scaling =2;
break;
case 106:
bw_scaling =2;
break;
default:
bw_scaling =1;
break;
default:
bw_scaling =1;
break;
}
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS/bw_scaling) {
LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,MAX_NUM_NR_DLSCH_SEGMENTS/bw_scaling);
return((1+dlsch->max_ldpc_iterations));
}
#ifdef DEBUG_DLSCH_DECODING
printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
#endif
opp_enabled=1;
Kr = harq_process->K;
Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb"
Kr_bytes = Kr>>3;
K_bytes_F = Kr_bytes-(harq_process->F>>3);
......@@ -400,11 +402,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
#endif
nr_deinterleaving_ldpc(E,
harq_process->Qm,
harq_process->w[r],
harq_process->w[r], // [hna] w is e
dlsch_llr+r_offset);
//for (int i =0; i<16; i++)
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
#if UE_TIMING_TRACE
stop_meas(dlsch_deinterleaving_stats);
......@@ -441,31 +443,30 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
#endif
LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n");
return(dlsch->max_ldpc_iterations);
} else
{
} else {
#if UE_TIMING_TRACE
stop_meas(dlsch_rate_unmatching_stats);
#endif
}
//for (int i =0; i<16; i++)
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
r_offset += E;
#ifdef DEBUG_DLSCH_DECODING
if (r==0) {
write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
}
printf("decoder input(segment %d) :",r);
int i; for (i=0;i<(3*8*Kr_bytes)+12;i++)
int i;
for (i=0;i<(3*8*Kr_bytes)+12;i++)
printf("%d : %d\n",i,harq_process->d[r][i]);
printf("\n");
printf("\n");
#endif
// printf("Clearing c, %p\n",harq_process->c[r]);
memset(harq_process->c[r],0,Kr_bytes);
......@@ -482,74 +483,70 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if (err_flag == 0) {
#if UE_TIMING_TRACE
start_meas(dlsch_turbo_decoding_stats);
start_meas(dlsch_turbo_decoding_stats);
#endif
//LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A);
//printf("harq process dr iteration %d\n", p_decParams->numMaxIter);
memset(pv,0,2*harq_process->Z*sizeof(int16_t));
//memset(pl,0,2*p_decParams->Z*sizeof(int8_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
memset(pv,0,2*harq_process->Z*sizeof(int16_t));
//memset(pl,0,2*p_decParams->Z*sizeof(int8_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
}
for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
}
for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
p_nrLDPC_procBuf[r],
p_procTime);
// Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int
if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
printf("Segment %d CRC OK\n",r);
ret = 2;
}
else {
printf("CRC NOK\n");
ret = 1+dlsch->max_ldpc_iterations;
}
nb_total_decod++;
if (no_iteration_ldpc > dlsch->max_ldpc_iterations){
nb_error_decod++;
}
ret=no_iteration_ldpc;
//if (!nb_total_decod%10000){
//printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout);
//}
//else
//printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
// Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int
if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
printf("Segment %d CRC OK\n",r);
ret = 2;
}
else {
printf("CRC NOK\n");
ret = 1+dlsch->max_ldpc_iterations;
}
nb_total_decod++;
if (no_iteration_ldpc > dlsch->max_ldpc_iterations){
nb_error_decod++;
}
ret=no_iteration_ldpc;
//if (!nb_total_decod%10000){
//printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout);
//}
//else
//printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
#ifdef DEBUG_DLSCH_DECODING
//printf("output decoder %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 k=0;k<A>>3;k++)
printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
printf("no_iterations_ldpc %d (ret %d)\n",no_iteration_ldpc,ret);
//write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4);
#endif
......@@ -664,18 +661,18 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
#ifdef UE_DLSCH_PARALLELISATION
uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
UE_nr_rxtx_proc_t *proc,
int eNB_id,
short *dlsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_process,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
uint8_t llr8_flag)
UE_nr_rxtx_proc_t *proc,
int eNB_id,
short *dlsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_process,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
uint8_t llr8_flag)
{
#if UE_TIMING_TRACE
......@@ -786,27 +783,28 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
// This is a new packet, so compute quantities regarding segmentation
harq_process->B = A+24;
nr_segmentation(NULL,
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
}
kb = harq_process->K/harq_process->Z;
if ( kb==22){
p_decParams->BG = 1;
p_decParams->R = 13;
kc = 68;
}
else{
p_decParams->BG = 2;
p_decParams->R = 13;
kc = 52;
}
kb = harq_process->K/harq_process->Z;
if ( kb==22){
p_decParams->BG = 1;
p_decParams->R = 13;
kc = 68;
}
else{
p_decParams->BG = 2;
p_decParams->R = 13;
kc = 52;
}
p_decParams->numMaxIter = 2;
Kr = p_decParams->Z*kb;
......@@ -842,135 +840,133 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
#endif
opp_enabled=1;
if (harq_process->C>1) { // wakeup worker if more than 1 segment
if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
/*Qm= harq_process->Qm;
Nl=harq_process->Nl;
r_thread = harq_process->C/2-1;
C= harq_process->C;
Gp = G/Nl/Qm;
GpmodC = Gp%C;
if (r_thread < (C-(GpmodC)))
Er = Nl*Qm * (Gp/C);
else
Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
printf("mthread Er %d\n", Er);
printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/
proc->instance_cnt_dlsch_td++;
proc->eNB_id = eNB_id;
proc->harq_pid = harq_pid;
proc->llr8_flag = llr8_flag;
//proc->r[0] = 1;
if (proc->instance_cnt_dlsch_td == 0)
{
LOG_D(PHY,"unblock dlsch td processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td );
if (pthread_cond_signal(&proc->cond_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id);
exit_fun("nothing to add");
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
} else
{
LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td);
if (proc->instance_cnt_dlsch_td > 4)
exit_fun("instance_cnt_dlsch_td > 4");
}
//AssertFatal(pthread_cond_signal(&proc->cond_slot1_dl_processing) ==0 ,"");
AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td) ==0,"");
if (harq_process->C>2) {
if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
proc->instance_cnt_dlsch_td1++;
proc->eNB_id = eNB_id;
proc->harq_pid = harq_pid;
proc->llr8_flag = llr8_flag;
// proc->Er = Er;
if (proc->instance_cnt_dlsch_td1 == 0)
{
LOG_D(PHY,"unblock slot1 dl processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td1 );
if (pthread_cond_signal(&proc->cond_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id);
exit_fun("nothing to add");
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
if (harq_process->C>1) { // wakeup worker if more than 1 segment
if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
} else
{
LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread 1 busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td1);
if (proc->instance_cnt_dlsch_td1 > 4)
exit_fun("instance_cnt_dlsch_td1 > 4");
}
/*Qm= harq_process->Qm;
Nl=harq_process->Nl;
r_thread = harq_process->C/2-1;
C= harq_process->C;
AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td1) ==0,"");
Gp = G/Nl/Qm;
GpmodC = Gp%C;
}
/*
if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) {
printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td);
exit_fun( "error locking mutex_fep" );
return -1;
}
if (proc->instance_cnt_td==0) {
printf("[UE] TD thread busy\n");
exit_fun("TD thread busy");
pthread_mutex_unlock( &proc->mutex_td );
return -1;
}
++proc->instance_cnt_td;
if (r_thread < (C-(GpmodC)))
Er = Nl*Qm * (Gp/C);
else
Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
printf("mthread Er %d\n", Er);
proc->tdp.UE = phy_vars_ue;
proc->tdp.eNB_id = eNB_id;
proc->tdp.harq_pid = harq_pid;
proc->tdp.llr8_flag = llr8_flag;
printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/
printf("----- 2thread llr flag %d tdp flag %d\n",llr8_flag, proc->tdp.llr8_flag);
proc->instance_cnt_dlsch_td++;
proc->eNB_id = eNB_id;
proc->harq_pid = harq_pid;
proc->llr8_flag = llr8_flag;
//proc->r[0] = 1;
if (proc->instance_cnt_dlsch_td == 0)
{
LOG_D(PHY,"unblock dlsch td processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td );
if (pthread_cond_signal(&proc->cond_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id);
exit_fun("nothing to add");
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
} else
{
LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td);
if (proc->instance_cnt_dlsch_td > 4)
exit_fun("instance_cnt_dlsch_td > 4");
}
//AssertFatal(pthread_cond_signal(&proc->cond_slot1_dl_processing) ==0 ,"");
AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td) ==0,"");
// wakeup worker to do second half segments
if (pthread_cond_signal(&proc->cond_td) != 0) {
printf("[UE] ERROR pthread_cond_signal for td thread exit\n");
exit_fun( "ERROR pthread_cond_signal" );
return (1+dlsch->last_iteration_cnt);
}
if (harq_process->C>2) {
if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
pthread_mutex_unlock( &proc->mutex_td );*/
proc->instance_cnt_dlsch_td1++;
proc->eNB_id = eNB_id;
proc->harq_pid = harq_pid;
proc->llr8_flag = llr8_flag;
// proc->Er = Er;
if (proc->instance_cnt_dlsch_td1 == 0)
{
LOG_D(PHY,"unblock slot1 dl processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td1 );
if (pthread_cond_signal(&proc->cond_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id);
exit_fun("nothing to add");
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id );
exit_fun("nothing to add");
}
} else
{
LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread 1 busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td1);
if (proc->instance_cnt_dlsch_td1 > 4)
exit_fun("instance_cnt_dlsch_td1 > 4");
}
AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td1) ==0,"");
Cby2 = 1; //harq_process->C/2;
//proc->decoder_main_available = 1;
}
else {
Cby2 = 1;
}
}
/*
if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) {
printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td);
exit_fun( "error locking mutex_fep" );
return -1;
}
if (proc->instance_cnt_td==0) {
printf("[UE] TD thread busy\n");
exit_fun("TD thread busy");
pthread_mutex_unlock( &proc->mutex_td );
return -1;
}
++proc->instance_cnt_td;
proc->tdp.UE = phy_vars_ue;
proc->tdp.eNB_id = eNB_id;
proc->tdp.harq_pid = harq_pid;
proc->tdp.llr8_flag = llr8_flag;
printf("----- 2thread llr flag %d tdp flag %d\n",llr8_flag, proc->tdp.llr8_flag);
// wakeup worker to do second half segments
if (pthread_cond_signal(&proc->cond_td) != 0) {
printf("[UE] ERROR pthread_cond_signal for td thread exit\n");
exit_fun( "ERROR pthread_cond_signal" );
return (1+dlsch->last_iteration_cnt);
}
pthread_mutex_unlock( &proc->mutex_td );*/
//for (r=0; r<Cby2; r++) {
r = 0;
if (r==0) r_offset =0;
Cby2 = 1; //harq_process->C/2;
//proc->decoder_main_available = 1;
}
else {
Cby2 = 1;
}
//for (r=0; r<Cby2; r++) {
r = 0;
if (r==0) r_offset =0;
Kr = harq_process->K;
Kr_bytes = Kr>>3;
......@@ -1041,27 +1037,27 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment
}
//for (int i =0; i<16; i++)
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
//r_offset += E;
//printf("main thread r_offset %d\n",r_offset);
#ifdef DEBUG_DLSCH_DECODING
for (int i =0; i<16; i++)
printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
#endif
#ifdef DEBUG_DLSCH_DECODING
if (r==0) {
write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0);
write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0);
}
printf("decoder input(segment %d) :",r);
for (int i=0;i<(3*8*Kr_bytes);i++)
printf("%d : %d\n",i,harq_process->d[r][i]);
printf("\n");
printf("\n");
#endif
......@@ -1082,98 +1078,94 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment
Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS,
harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations);
*/
if (llr8_flag) {
AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}
if (llr8_flag) {
AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}
#if UE_TIMING_TRACE
start_meas(dlsch_turbo_decoding_stats);
start_meas(dlsch_turbo_decoding_stats);
#endif
LOG_D(PHY,"mthread AbsSubframe %d.%d Start turbo segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1);
for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){
inv_d[cnt] = (1)*harq_process->d[r][cnt];
}
memset(pv,0,2*p_decParams->Z*sizeof(int16_t));
//memset(pl,0,2*p_decParams->Z*sizeof(int8_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
p_nrLDPC_procBuf,
p_procTime);
nb_total_decod++;
if (no_iteration_ldpc > 10){
nb_error_decod++;
ret = 1+dlsch->max_ldpc_iterations;
}
else {
ret=2;
}
if (check_crc(llrProcBuf,harq_process->B,harq_process->F,crc_type)) {
printf("CRC OK\n");
ret = 2;
}
else {
printf("CRC NOK\n");
ret = 1+dlsch->max_ldpc_iterations;
}
//if (!nb_total_decod%10000){
printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout);
//}
//else
//printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
/*for (int u=0; u < Kr>>3; u ++)
{
ullrProcBuf[u]= (uint8_t) llrProcBuf[u];
}
printf("output unsigned ullrProcBuf \n");
for (int j=0; j < Kr>>3; j ++)
{
printf(" %d \n", ullrProcBuf[j]);
}
printf(" \n");*/
//printf("output channel decoder %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]);
//printf("output decoder %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 < (kc-2)*p_decParams->Z; cnt++){
inv_d[cnt] = (1)*harq_process->d[r][cnt];
}
memset(pv,0,2*p_decParams->Z*sizeof(int16_t));
//memset(pl,0,2*p_decParams->Z*sizeof(int8_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
p_nrLDPC_procBuf,
p_procTime);
nb_total_decod++;
if (no_iteration_ldpc > 10){
nb_error_decod++;
ret = 1+dlsch->max_ldpc_iterations;
}
else {
ret=2;
}
if (check_crc(llrProcBuf,harq_process->B,harq_process->F,crc_type)) {
printf("CRC OK\n");
ret = 2;
}
else {
printf("CRC NOK\n");
ret = 1+dlsch->max_ldpc_iterations;
}
//if (!nb_total_decod%10000){
printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout);
//}
//else
//printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
/*for (int u=0; u < Kr>>3; u ++)
{
ullrProcBuf[u]= (uint8_t) llrProcBuf[u];
}
printf("output unsigned ullrProcBuf \n");
for (int j=0; j < Kr>>3; j ++)
{
printf(" %d \n", ullrProcBuf[j]);
}
printf(" \n");*/
//printf("output channel decoder %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]);
//printf("output decoder %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]);
#ifdef DEBUG_DLSCH_DECODING
for (int k=0;k<32;k++)
printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
for (int k=0;k<32;k++)
printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
#endif
#if UE_TIMING_TRACE
......@@ -1252,40 +1244,40 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment
*/
uint32_t wait = 0;
if (harq_process->C==2){
while((proc->decoder_thread_available == 0) )
while((proc->decoder_thread_available == 0) )
{
usleep(1);
wait++;
}
}
else if ((harq_process->C==3) ){
while((proc->decoder_thread_available == 0) || (proc->decoder_thread_available1 == 0))
{
usleep(1);
wait++;
}
while((proc->decoder_thread_available == 0) || (proc->decoder_thread_available1 == 0))
{
usleep(1);
wait++;
}
}
proc->decoder_main_available = 0;
for (r=0; r<harq_process->C; r++) {
Kr = harq_process->K; //to check if same K in all segments
Kr_bytes = Kr>>3;
Kr = harq_process->K; //to check if same K in all segments
Kr_bytes = Kr>>3;
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));
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));
#ifdef DEBUG_DLSCH_DECODING
printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
printf("copied %d bytes to b sequence (harq_pid %d)\n",
(Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
printf("b[0] = %x,c[%d] = %x\n",
harq_process->b[offset],
harq_process->F>>3,
harq_process->c[r]);
printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
printf("copied %d bytes to b sequence (harq_pid %d)\n",
(Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
printf("b[0] = %x,c[%d] = %x\n",
harq_process->b[offset],
harq_process->F>>3,
harq_process->c[r]);
#endif
}
......@@ -1346,14 +1338,14 @@ void *nr_dlsch_decoding_2thread0(void *arg)
char threadname[256];
sprintf(threadname,"UE_thread_dlsch_td_%d", proc->sub_frame_start);
cpu_set_t cpuset;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.dlsch_td_one != -1 )
CPU_SET(threads.dlsch_td_one, &cpuset);
CPU_SET(threads.dlsch_td_one, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.dlsch_td_two != -1 )
CPU_SET(threads.dlsch_td_two, &cpuset);
CPU_SET(threads.dlsch_td_two, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.dlsch_td_three != -1 )
CPU_SET(threads.dlsch_td_three, &cpuset);
CPU_SET(threads.dlsch_td_three, &cpuset);
......@@ -1376,42 +1368,42 @@ void *nr_dlsch_decoding_2thread0(void *arg)
init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname);
while (!oai_exit) {
//proc->decoder_thread_available = 1;
if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" );
exit_fun("nothing to add");
}
while (proc->instance_cnt_dlsch_td < 0) {
// most of the time, the thread is waiting here
pthread_cond_wait( &proc->cond_dlsch_td, &proc->mutex_dlsch_td );
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" );
exit_fun("nothing to add");
}
uint32_t wait = 0;
while(proc->decoder_main_available == 0)
{
usleep(1);
wait++;
}
//proc->decoder_thread_available = 0;
//PHY_VARS_NR_UE *phy_vars_ue = tdp->UE;
int eNB_id = proc->eNB_id;
int harq_pid = proc->harq_pid;
llr8_flag1 = proc->llr8_flag;
//r_offset = proc->Er;
//UE_rxtx_proc_t *proc = tdp->proc;
int frame = proc->frame_rx;
int subframe = proc->nr_tti_rx;
NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0];
NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid];
short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0];
//printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag);
p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[1];
//proc->decoder_thread_available = 1;
if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" );
exit_fun("nothing to add");
}
while (proc->instance_cnt_dlsch_td < 0) {
// most of the time, the thread is waiting here
pthread_cond_wait( &proc->cond_dlsch_td, &proc->mutex_dlsch_td );
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" );
exit_fun("nothing to add");
}
uint32_t wait = 0;
while(proc->decoder_main_available == 0)
{
usleep(1);
wait++;
}
//proc->decoder_thread_available = 0;
//PHY_VARS_NR_UE *phy_vars_ue = tdp->UE;
int eNB_id = proc->eNB_id;
int harq_pid = proc->harq_pid;
llr8_flag1 = proc->llr8_flag;
//r_offset = proc->Er;
//UE_rxtx_proc_t *proc = tdp->proc;
int frame = proc->frame_rx;
int subframe = proc->nr_tti_rx;
NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0];
NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid];
short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0];
//printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag);
p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[1];
/*
if (nb_rb > frame_parms->N_RB_DL) {
......@@ -1444,27 +1436,27 @@ void *nr_dlsch_decoding_2thread0(void *arg)
harq_process->B = A+24;
nr_segmentation(NULL,
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
}
kb = harq_process->K/harq_process->Z;
if ( kb==22){
p_decParams->BG = 1;
p_decParams->R = 13;
kc = 68;
}
else{
p_decParams->BG = 2;
p_decParams->R = 13;
kc = 52;
}
if ( kb==22){
p_decParams->BG = 1;
p_decParams->R = 13;
kc = 68;
}
else{
p_decParams->BG = 2;
p_decParams->R = 13;
kc = 52;
}
p_decParams->numMaxIter = 2;
Kr = p_decParams->Z*kb;
......@@ -1510,14 +1502,14 @@ void *nr_dlsch_decoding_2thread0(void *arg)
Cprime = C; //assume CBGTI not present
if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1)
r_offset = Nl*Qm*(G/(Nl*Qm*Cprime));
r_offset = Nl*Qm*(G/(Nl*Qm*Cprime));
else
r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
// printf("thread0 r_offset %d\n",r_offset);
// printf("thread0 r_offset %d\n",r_offset);
//for (r=(harq_process->C/2); r<harq_process->C; r++) {
r=1; //(harq_process->C/2);
r=1; //(harq_process->C/2);
Kr = harq_process->K;
......@@ -1537,7 +1529,7 @@ void *nr_dlsch_decoding_2thread0(void *arg)
dlsch_llr+r_offset);
//for (int i =0; i<16; i++)
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
#if UE_TIMING_TRACE
stop_meas(dlsch_deinterleaving_stats);
......@@ -1582,7 +1574,7 @@ void *nr_dlsch_decoding_2thread0(void *arg)
}
//for (int i =0; i<16; i++)
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
//r_offset += E;
......@@ -1616,10 +1608,10 @@ void *nr_dlsch_decoding_2thread0(void *arg)
Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS,
harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations);
*/
if (llr8_flag1) {
AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}
if (llr8_flag1) {
AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}
#if UE_TIMING_TRACE
start_meas(dlsch_turbo_decoding_stats);
#endif
......@@ -1634,58 +1626,58 @@ void *nr_dlsch_decoding_2thread0(void *arg)
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
}
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
p_nrLDPC_procBuf,
p_procTime);
p_procTime);
if (no_iteration_ldpc > 10)
printf("Error number of iteration LPDC %d\n", no_iteration_ldpc);
//else
//printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
if (no_iteration_ldpc > 10)
printf("Error number of iteration LPDC %d\n", no_iteration_ldpc);
//else
//printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
/*for (int u=0; u < Kr>>3; u ++)
{
ullrProcBuf[u]= (uint8_t) llrProcBuf[u];
}
/*for (int u=0; u < Kr>>3; u ++)
{
ullrProcBuf[u]= (uint8_t) llrProcBuf[u];
}
printf("output unsigned ullrProcBuf \n");
printf("output unsigned ullrProcBuf \n");
for (int j=0; j < Kr>>3; j ++)
{
for (int j=0; j < Kr>>3; j ++)
{
printf(" %d \n", ullrProcBuf[j]);
printf(" %d \n", ullrProcBuf[j]);
}
printf(" \n");*/
#ifdef DEBUG_DLSCH_DECODING
for (int k=0;k<2;k++)
printf("segment 1 output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
}
printf(" \n");*/
#ifdef DEBUG_DLSCH_DECODING
for (int k=0;k<2;k++)
printf("segment 1 output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]);
#endif
#if UE_TIMING_TRACE
stop_meas(dlsch_turbo_decoding_stats);
#endif
......@@ -1818,7 +1810,7 @@ void *nr_dlsch_decoding_2thread0(void *arg)
#define FIFO_PRIORITY 39
void *nr_dlsch_decoding_2thread1(void *arg)
{
static __thread int UE_dlsch_td_retval1;
static __thread int UE_dlsch_td_retval1;
struct nr_rxtx_thread_data *rtd = arg;
UE_nr_rxtx_proc_t *proc = rtd->proc;
PHY_VARS_NR_UE *phy_vars_ue = rtd->UE;
......@@ -1860,14 +1852,14 @@ void *nr_dlsch_decoding_2thread1(void *arg)
char threadname[256];
sprintf(threadname,"UE_thread_dlsch_td1_%d", proc->sub_frame_start);
cpu_set_t cpuset;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.dlsch_td_one != -1 )
CPU_SET(threads.dlsch_td_one, &cpuset);
CPU_SET(threads.dlsch_td_one, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.dlsch_td_two != -1 )
CPU_SET(threads.dlsch_td_two, &cpuset);
CPU_SET(threads.dlsch_td_two, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.dlsch_td_three != -1 )
CPU_SET(threads.dlsch_td_three, &cpuset);
CPU_SET(threads.dlsch_td_three, &cpuset);
......@@ -1881,51 +1873,51 @@ void *nr_dlsch_decoding_2thread1(void *arg)
uint32_t ret,offset;
uint32_t r,r_offset=0,Kr,Kr_bytes,err_flag=0,K_bytes_F;
uint8_t crc_type;
uint8_t C,Cprime;
uint8_t C,Cprime;
uint8_t Qm;
uint8_t Nl;
uint8_t Nl;
//uint32_t Er;
init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname);
printf("2thread1 oai_exit %d\n", oai_exit);
while (!oai_exit) {
if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" );
exit_fun("nothing to add");
}
while (proc->instance_cnt_dlsch_td1 < 0) {
// most of the time, the thread is waiting here
pthread_cond_wait( &proc->cond_dlsch_td1, &proc->mutex_dlsch_td1 );
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" );
exit_fun("nothing to add");
}
//printf("2thread1 main available %d\n", proc->decoder_main_available);
uint32_t wait = 0;
while(proc->decoder_main_available == 0)
{
usleep(1);
wait++;
}
//proc->decoder_thread_available1 = 0;
//PHY_VARS_NR_UE *phy_vars_ue = tdp->UE;
int eNB_id = proc->eNB_id;
int harq_pid = proc->harq_pid;
llr8_flag1 = proc->llr8_flag;
//r_offset = proc->Er;
//UE_rxtx_proc_t *proc = tdp->proc;
int frame = proc->frame_rx;
int subframe = proc->nr_tti_rx;
NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0];
NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid];
short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0];
//printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag);
//printf("2thread1 nr_tti_tx %d subframe %d SF thread id %d r_offset %d\n", proc->nr_tti_rx, subframe, phy_vars_ue->current_thread_id[subframe], r_offset);
p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[2];
init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname);
printf("2thread1 oai_exit %d\n", oai_exit);
while (!oai_exit) {
if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" );
exit_fun("nothing to add");
}
while (proc->instance_cnt_dlsch_td1 < 0) {
// most of the time, the thread is waiting here
pthread_cond_wait( &proc->cond_dlsch_td1, &proc->mutex_dlsch_td1 );
}
if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" );
exit_fun("nothing to add");
}
//printf("2thread1 main available %d\n", proc->decoder_main_available);
uint32_t wait = 0;
while(proc->decoder_main_available == 0)
{
usleep(1);
wait++;
}
//proc->decoder_thread_available1 = 0;
//PHY_VARS_NR_UE *phy_vars_ue = tdp->UE;
int eNB_id = proc->eNB_id;
int harq_pid = proc->harq_pid;
llr8_flag1 = proc->llr8_flag;
//r_offset = proc->Er;
//UE_rxtx_proc_t *proc = tdp->proc;
int frame = proc->frame_rx;
int subframe = proc->nr_tti_rx;
NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0];
NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid];
short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0];
//printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag);
//printf("2thread1 nr_tti_tx %d subframe %d SF thread id %d r_offset %d\n", proc->nr_tti_rx, subframe, phy_vars_ue->current_thread_id[subframe], r_offset);
p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[2];
/*
if (nb_rb > frame_parms->N_RB_DL) {
......@@ -1960,27 +1952,27 @@ void *nr_dlsch_decoding_2thread1(void *arg)
// This is a new packet, so compute quantities regarding segmentation
harq_process->B = A+24;
nr_segmentation(NULL,
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z,
&harq_process->F);
p_decParams->Z = harq_process->Z;
}
kb = harq_process->K/harq_process->Z;
if ( kb==22){
p_decParams->BG = 1;
p_decParams->R = 89;
kc = 68;
}
else{
p_decParams->BG = 2;
p_decParams->R = 13;
kc = 52;
}
if ( kb==22){
p_decParams->BG = 1;
p_decParams->R = 89;
kc = 68;
}
else{
p_decParams->BG = 2;
p_decParams->R = 13;
kc = 52;
}
p_decParams->numMaxIter = 2;
Kr = p_decParams->Z*kb;
......@@ -2025,23 +2017,23 @@ void *nr_dlsch_decoding_2thread1(void *arg)
Cprime = C; //assume CBGTI not present
if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1)
r_offset = Nl*Qm*(G/(Nl*Qm*Cprime));
r_offset = Nl*Qm*(G/(Nl*Qm*Cprime));
else
r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
//printf("sub thread r_offset %d\n", r_offset);
//printf("sub thread r_offset %d\n", r_offset);
//for (r=(harq_process->C/2); r<harq_process->C; r++) {
r=2; //(harq_process->C/2);
r_offset = r*r_offset;
//printf("thread1 r=%d r_offset %d \n",r, r_offset);
r=2; //(harq_process->C/2);
r_offset = r*r_offset;
//printf("thread1 r=%d r_offset %d \n",r, r_offset);
Kr = harq_process->K;
Kr_bytes = Kr>>3;
K_bytes_F = Kr_bytes-(harq_process->F>>3);
Kr = harq_process->K;
Kr_bytes = Kr>>3;
K_bytes_F = Kr_bytes-(harq_process->F>>3);
Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r);
......@@ -2059,7 +2051,7 @@ void *nr_dlsch_decoding_2thread1(void *arg)
dlsch_llr+r_offset);
//for (int i =0; i<16; i++)
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
#if UE_TIMING_TRACE
stop_meas(dlsch_deinterleaving_stats);
......@@ -2082,15 +2074,15 @@ void *nr_dlsch_decoding_2thread1(void *arg)
#endif
if (nr_rate_matching_ldpc_rx(Ilbrm,
Tbslbrm,
p_decParams->BG,
p_decParams->Z,
harq_process->d[r],
harq_process->w[r],
harq_process->C,
harq_process->rvidx,
(harq_process->round==0)?1:0,
E)==-1) {
Tbslbrm,
p_decParams->BG,
p_decParams->Z,
harq_process->d[r],
harq_process->w[r],
harq_process->C,
harq_process->rvidx,
(harq_process->round==0)?1:0,
E)==-1) {
#if UE_TIMING_TRACE
stop_meas(dlsch_rate_unmatching_stats);
#endif
......@@ -2104,7 +2096,7 @@ void *nr_dlsch_decoding_2thread1(void *arg)
}
//for (int i =0; i<16; i++)
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
//r_offset += E;
......@@ -2136,71 +2128,71 @@ void *nr_dlsch_decoding_2thread1(void *arg)
Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS,
harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations);
*/
if (llr8_flag1) {
AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}
if (llr8_flag1) {
AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}
#if UE_TIMING_TRACE
start_meas(dlsch_turbo_decoding_stats);
#endif
// LOG_D(PHY,"AbsSubframe %d.%d Start turbo segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1);
memset(pv,0,2*p_decParams->Z*sizeof(int16_t));
memset(pv,0,2*p_decParams->Z*sizeof(int16_t));
//memset(pl,0,2*p_decParams->Z*sizeof(int8_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++)
{
pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j]));
}
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++)
{
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
}
}
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
no_iteration_ldpc = nrLDPC_decoder(p_decParams,
(int8_t*)&pl[0],
llrProcBuf,
p_nrLDPC_procBuf,
p_procTime);
p_procTime);
if (no_iteration_ldpc > 10)
printf("Error number of iteration LPDC %d\n", no_iteration_ldpc);
//else
// printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
if (no_iteration_ldpc > 10)
printf("Error number of iteration LPDC %d\n", no_iteration_ldpc);
//else
// printf("OK number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
for (int m=0; m < Kr>>3; m ++)
{
harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
}
/*for (int u=0; u < Kr>>3; u ++)
{
ullrProcBuf[u]= (uint8_t) llrProcBuf[u];
}
/*for (int u=0; u < Kr>>3; u ++)
{
ullrProcBuf[u]= (uint8_t) llrProcBuf[u];
}
printf("output unsigned ullrProcBuf \n");
printf("output unsigned ullrProcBuf \n");
for (int j=0; j < Kr>>3; j ++)
{
for (int j=0; j < Kr>>3; j ++)
{
printf(" %d \n", ullrProcBuf[j]);
printf(" %d \n", ullrProcBuf[j]);
}
printf(" \n");*/
}
printf(" \n");*/
#endif
//printf("output channel decoder %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]);
//printf("output channel decoder %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]);
//printf("output decoder %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]);
//printf("output decoder %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]);
#if UE_TIMING_TRACE
stop_meas(dlsch_turbo_decoding_stats);
......@@ -2239,7 +2231,7 @@ void *nr_dlsch_decoding_2thread1(void *arg)
//printf("end 2thread1 proc->instance_cnt_dlsch_td1 %d\n", proc->instance_cnt_dlsch_td1);
}
//printf("after 2thread1 after oai exit proc->instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td1);
//printf("after 2thread1 after oai exit proc->instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td1);
// thread finished
free(arg);
return &UE_dlsch_td_retval1;
......
......@@ -61,10 +61,10 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch);
NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag);
void free_ue_ulsch(NR_UE_ULSCH_t *ulsch);
void free_nr_ue_ulsch(NR_UE_ULSCH_t *ulsch);
NR_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag);
NR_UE_ULSCH_t *new_nr_ue_ulsch(unsigned char N_RB_UL, int number_of_harq_pids, uint8_t abstraction_flag);
void fill_UE_dlsch_MCH(PHY_VARS_NR_UE *ue,int mcs,int ndi,int rvidx,int eNB_id);
......@@ -1006,6 +1006,25 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
uint8_t is_crnti,
uint8_t llr8_flag);
int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
NR_DL_FRAME_PARMS* frame_parms,
uint8_t harq_pid);
/*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param[in] in Pointer to input bits
@param[in] size of input bits
@param[in] Nid cell id
@param[in] n_RNTI CRNTI
@param[out] out the scrambled bits
*/
void nr_pusch_codeword_scrambling(uint8_t *in,
uint16_t size,
uint32_t Nid,
uint32_t n_RNTI,
uint32_t* out);
uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
UE_nr_rxtx_proc_t *proc,
int eNB_id,
......
......@@ -102,6 +102,8 @@ typedef struct {
uint16_t first_rb;
/// Current Number of RBs
uint16_t nb_rb;
/// number of layers
uint8_t Nl;
/// Last TPC command
uint8_t TPC;
/// Transport block size
......@@ -110,20 +112,24 @@ typedef struct {
uint32_t B;
/// Length of ACK information (bits)
uint8_t O_ACK;
/// Pointer to the payload
uint8_t *b;
/// Pointers to transport block segments
uint8_t *c[MAX_NUM_ULSCH_SEGMENTS];
/// Index of current HARQ round for this ULSCH
uint8_t round;
/// MCS format of this ULSCH
uint8_t mcs;
/// Redundancy-version of the current sub-frame
uint8_t rvidx;
/// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8)
unsigned char *a;
/// Pointer to the payload + CRC
uint8_t *b;
/// Pointers to transport block segments
uint8_t *c[MAX_NUM_NR_ULSCH_SEGMENTS];
/// LDPC-code outputs
uint8_t d[MAX_NUM_ULSCH_SEGMENTS][3*8448];
/// Interleaver outputs
uint8_t w[MAX_NUM_ULSCH_SEGMENTS][3*8448];
uint8_t *d[MAX_NUM_NR_ULSCH_SEGMENTS];
/// LDPC-code outputs (TS 36.212 V15.4.0, Sec 5.3.2 p. 17)
uint8_t e[MAX_NUM_NR_CHANNEL_BITS] __attribute__((aligned(32)));
/// Rate matching (Interleaving) outputs (TS 36.212 V15.4.0, Sec 5.4.2.2 p. 30)
uint8_t f[MAX_NUM_NR_CHANNEL_BITS] __attribute__((aligned(32)));
/// Number of code segments
uint32_t C;
/// Number of bits in code segments
......@@ -158,6 +164,8 @@ typedef struct {
typedef struct {
/// Current Number of Symbols
uint8_t Nsymb_pusch;
/// number of DMRS resource elements
uint8_t nb_re_dmrs;
/// SRS active flag
uint8_t srs_active;
//#if defined(UPGRADE_RAT_NR)
......@@ -168,6 +176,7 @@ typedef struct {
// UL number of harq processes
uint8_t number_harq_processes_for_pusch;
#endif
/*
/// Pointer to CQI data (+1 for 8 bits crc)
uint8_t o[1+MAX_CQI_BYTES];
/// Length of CQI data (bits)
......@@ -180,22 +189,25 @@ typedef struct {
uint8_t O_RI;
/// Pointer to ACK
uint8_t o_ACK[4];
*/
/// Minimum number of CQI bits for PUSCH (36-212 r8.6, Sec 5.2.4.1 p. 37)
uint8_t O_CQI_MIN;
/// ACK/NAK Bundling flag
uint8_t bundling;
/// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
uint8_t e[MAX_NUM_CHANNEL_BITS];
/// Concatenated "g"-sequences (for definition see 36-212 V15.4.0 2018-12, p.31)
uint8_t g[MAX_NUM_NR_CHANNEL_BITS];
/// Interleaved "h"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
uint8_t h[MAX_NUM_CHANNEL_BITS];
uint8_t h[MAX_NUM_NR_CHANNEL_BITS];
/// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
uint8_t b_tilde[MAX_NUM_CHANNEL_BITS];
uint8_t b_tilde[MAX_NUM_NR_CHANNEL_BITS];
/// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
int32_t d[MAX_NUM_RE];
int32_t d[MAX_NUM_NR_RE];
/// Transform-coded "z"-sequences (for definition see 36-211 V8.6 2009-03, p.14-15)
int32_t z[MAX_NUM_RE];
int32_t z[MAX_NUM_NR_RE];
/*
/// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
uint8_t q[MAX_CQI_PAYLOAD];
/// coded and interleaved CQI bits
uint8_t o_w[(MAX_CQI_BITS+8)*3];
/// coded CQI bits
......@@ -204,6 +216,7 @@ typedef struct {
uint8_t q_ACK[MAX_ACK_PAYLOAD];
/// coded RI bits
uint8_t q_RI[MAX_RI_PAYLOAD];
*/
/// beta_offset_cqi times 8
uint16_t beta_offset_cqi_times8;
/// beta_offset_ri times 8
......@@ -229,9 +242,9 @@ typedef struct {
/// num active cba group
uint8_t num_active_cba_groups;
/// num dci found for cba
uint8_t num_cba_dci[10];
//uint8_t num_cba_dci[10];
/// allocated CBA RNTI
uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
//uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
/// UL max-harq-retransmission
uint8_t Mlimit;
} NR_UE_ULSCH_t;
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
* \brief Top-level routines for coding the ULSCH transport channel as described in 38.212 V15.4 2018-12
* \author Khalid Ahmed
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: khalid.ahmed@iis.fraunhofer.de
* \note
* \warning
*/
#include "PHY/defs_UE.h"
#include "PHY/phy_extern_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/CODING/nrLDPC_encoder/defs.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
void free_nr_ue_ulsch(NR_UE_ULSCH_t *ulsch)
{
int i;
int r;
if (ulsch) {
#ifdef DEBUG_ULSCH_FREE
printf("Freeing ulsch %p\n",ulsch);
#endif
for (i=0; i<NR_MAX_ULSCH_HARQ_PROCESSES; i++) {
if (ulsch->harq_processes[i]) {
if (ulsch->harq_processes[i]->a) {
free16(ulsch->harq_processes[i]->a,MAX_NR_ULSCH_PAYLOAD_BYTES);
ulsch->harq_processes[i]->a = NULL;
}
if (ulsch->harq_processes[i]->b) {
free16(ulsch->harq_processes[i]->b,MAX_NR_ULSCH_PAYLOAD_BYTES);
ulsch->harq_processes[i]->b = NULL;
}
for (r=0; r<MAX_NUM_NR_ULSCH_SEGMENTS; r++) {
if (ulsch->harq_processes[i]->c[r]) {
free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768);
ulsch->harq_processes[i]->c[r] = NULL;
}
if (ulsch->harq_processes[i]->d[r]) {
free16(ulsch->harq_processes[i]->d[r],68*384);
ulsch->harq_processes[i]->d[r] = NULL;
}
}
free16(ulsch->harq_processes[i],sizeof(NR_UL_UE_HARQ_t));
ulsch->harq_processes[i] = NULL;
}
}
free16(ulsch,sizeof(NR_UE_ULSCH_t));
ulsch = NULL;
}
}
NR_UE_ULSCH_t *new_nr_ue_ulsch(unsigned char N_RB_UL, int number_of_harq_pids, uint8_t abstraction_flag)
{
NR_UE_ULSCH_t *ulsch;
unsigned char exit_flag = 0,i,j,r;
unsigned char bw_scaling =1;
switch (N_RB_UL) {
case 106:
bw_scaling =2;
break;
default:
bw_scaling =1;
break;
}
ulsch = (NR_UE_ULSCH_t *)malloc16(sizeof(NR_UE_ULSCH_t));
if (ulsch) {
memset(ulsch,0,sizeof(NR_UE_ULSCH_t));
ulsch->number_harq_processes_for_pusch = NR_MAX_ULSCH_HARQ_PROCESSES;
ulsch->Mlimit = 4; // maximum harq retransmissions
//for (i=0; i<10; i++)
//ulsch->harq_ids[i] = 0;
for (i=0; i<number_of_harq_pids; i++) {
ulsch->harq_processes[i] = (NR_UL_UE_HARQ_t *)malloc16(sizeof(NR_UL_UE_HARQ_t));
// printf("ulsch->harq_processes[%d] %p\n",i,ulsch->harq_processes[i]);
if (ulsch->harq_processes[i]) {
memset(ulsch->harq_processes[i], 0, sizeof(NR_UL_UE_HARQ_t));
ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling);
ulsch->harq_processes[i]->a = (unsigned char*)malloc16(MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling);
if (ulsch->harq_processes[i]->a) {
bzero(ulsch->harq_processes[i]->a,MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling);
} else {
printf("Can't allocate PDU\n");
exit_flag=1;
}
if (ulsch->harq_processes[i]->b)
bzero(ulsch->harq_processes[i]->b,MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling);
else {
LOG_E(PHY,"Can't get b\n");
exit_flag=1;
}
if (abstraction_flag==0) {
for (r=0; r<MAX_NUM_NR_ULSCH_SEGMENTS/bw_scaling; r++) {
// account for filler in first segment and CRCs for multiple segment case
ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(8448);
ulsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output
if (ulsch->harq_processes[i]->c[r]) {
bzero(ulsch->harq_processes[i]->c[r],8448);
} else {
printf("Can't get c\n");
exit_flag=2;
}
if (ulsch->harq_processes[i]->d[r]) {
bzero(ulsch->harq_processes[i]->d[r],(68*384));
} else {
printf("Can't get d\n");
exit_flag=2;
}
}
}
ulsch->harq_processes[i]->subframe_scheduling_flag = 0;
ulsch->harq_processes[i]->first_tx = 1;
} else {
LOG_E(PHY,"Can't get harq_p %d\n",i);
exit_flag=3;
}
}
if (exit_flag==0) {
for (i=0; i<number_of_harq_pids; i++) {
ulsch->harq_processes[i]->round=0;
}
return(ulsch);
}
}
LOG_E(PHY,"new_ue_ulsch exit flag, size of %d , %zu\n",exit_flag, sizeof(LTE_UE_ULSCH_t));
free_nr_ue_ulsch(ulsch);
return(NULL);
}
int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
NR_DL_FRAME_PARMS* frame_parms,
uint8_t harq_pid)
{
/////////////////////////parameters and variables declaration/////////////////////////
///////////
unsigned int G,crc;
NR_UL_UE_HARQ_t *harq_process;
uint16_t nb_rb ;
uint8_t nb_symb_sch ;
uint32_t A, Z, F;
uint32_t *pz;
uint8_t mod_order;
uint16_t Kr,r,r_offset,Kr_bytes;
uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS];
uint8_t BG;
uint32_t E;
uint8_t Ilbrm;
uint32_t Tbslbrm;
uint8_t nb_re_dmrs;
uint16_t length_dmrs;
int i;
float Coderate;
///////////
///////////////////////////////////////////////////////////////////////////////////////
/////////////////////////parameters and variables initialization/////////////////////////
///////////
crc = 1;
harq_process = ulsch->harq_processes[harq_pid];
nb_rb = harq_process->nb_rb;
nb_symb_sch = harq_process->nb_symbols;
A = harq_process->TBS;
pz = &Z;
mod_order = nr_get_Qm(harq_process->mcs,1);
Kr=0;
r_offset=0;
BG = 1;
F=0;
Ilbrm = 0;
Tbslbrm = 950984; //max tbs
nb_re_dmrs = ulsch->nb_re_dmrs;
length_dmrs = 1;
Coderate = 0.0;
///////////
/////////////////////////////////////////////////////////////////////////////////////////
/*
uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; //unsigned char
for(j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
channel_input[j] = (unsigned char *)malloc16(sizeof(unsigned char) * 68*384);
}
*/
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
printf("ulsch coding nb_rb %d nb_symb_sch %d nb_re_dmrs %d, length_dmrs %d\n", nb_rb,nb_symb_sch, nb_re_dmrs,length_dmrs);
G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,harq_process->Nl);
LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order);
printf("ulsch coding A %d G %d mod_order %d\n", A,G, mod_order);
Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
// if (harq_process->Ndi == 1) { // this is a new packet
if (harq_process->round == 0) { // this is a new packet
#ifdef DEBUG_DLSCH_CODING
printf("encoding thinks this is a new packet \n");
#endif
///////////////////////// a---->| add CRC |---->b /////////////////////////
///////////
/*
int i;
printf("ulsch (tx): \n");
for (i=0;i<(A>>3);i++)
printf("%02x.",a[i]);
printf("\n");
*/
// Add 24-bit crc (polynomial A) to payload
crc = crc24a(harq_process->a,A)>>8;
harq_process->a[A>>3] = ((uint8_t*)&crc)[2];
harq_process->a[1+(A>>3)] = ((uint8_t*)&crc)[1];
harq_process->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_process->B = A+24;
memcpy(harq_process->b,harq_process->a,(A/8)+4);
///////////
///////////////////////////////////////////////////////////////////////////
///////////////////////// b---->| block segmentation |---->c /////////////////////////
///////////
nr_segmentation(harq_process->b,
harq_process->c,
harq_process->B,
&harq_process->C,
&harq_process->K,
pz,
&harq_process->F);
F = harq_process->F;
Coderate = (float) A /(float) G;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){
BG = 2;
}
else{
BG = 1;
}
Kr = harq_process->K;
Kr_bytes = Kr>>3;
///////////
/////////////////////////////////////////////////////////////////////////////////////
///////////////////////// c---->| LDCP coding |---->d /////////////////////////
///////////
//printf("segment Z %d k %d Kr %d BG %d\n", *pz,harq_process->K,Kr,BG);
//start_meas(te_stats);
for (r=0; r<harq_process->C; r++) {
d_tmp[r] = &harq_process->d[r][0];
//channel_input[r] = &harq_process->d[r][0];
#ifdef DEBUG_DLSCH_CODING
printf("Encoder: B %d F %d \n",harq_process->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 ++){
printf("%d ", harq_process->c[r][cnt]);
}
printf("\n");
#endif
//ldpc_encoder_orig((unsigned char*)harq_process->c[r],harq_process->d[r],Kr,BG,0);
//ldpc_encoder_optim((unsigned char*)harq_process->c[r],(unsigned char*)&harq_process->d[r][0],Kr,BG,NULL,NULL,NULL,NULL);
}
//for (int i=0;i<68*384;i++)
// printf("channel_input[%d]=%d\n",i,channel_input[i]);
/*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], harq_process->d[0][4]);
for (int cnt =0 ; cnt < 66*(*pz); cnt ++){
printf("%d \n", harq_process->d[0][cnt]);
}
printf("\n");*/
//ldpc_encoder_optim_8seg(harq_process->c,d_tmp,Kr,BG,harq_process->C,NULL,NULL,NULL,NULL);
ldpc_encoder_optim_8seg(harq_process->c,harq_process->d,Kr,BG,harq_process->C,NULL,NULL,NULL,NULL);
//stop_meas(te_stats);
//printf("end ldpc encoder -- output\n");
//write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4);
#ifdef DEBUG_DLSCH_CODING
write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4);
write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4);
#endif
///////////
///////////////////////////////////////////////////////////////////////////////
}
for (r=0; r<harq_process->C; r++) { // looping over C segments
if (harq_process->F>0) {
for (int k=(Kr-F-2*(*pz)); k<Kr-2*(*pz); k++) {
harq_process->d[r][k] = NR_NULL;
//if (k<(Kr-F+8))
//printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]);
}
}
#ifdef DEBUG_DLSCH_CODING
printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n",
r,
G,
Kr*3,
mod_order,nb_rb);
#endif
//start_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING
printf("rvidx in encoding = %d\n", harq_process->rvidx);
#endif
///////////////////////// d---->| Rate matching bit selection |---->e /////////////////////////
///////////
E = nr_get_E(G, harq_process->C, mod_order, harq_process->Nl, r);
nr_rate_matching_ldpc(Ilbrm,
Tbslbrm,
BG,
*pz,
harq_process->d[r],
harq_process->e+r_offset,
harq_process->C,
harq_process->rvidx,
E);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output ratematching e[%d]= %d r_offset %d\n", i,harq_process->e[i+r_offset], r_offset);
#endif
///////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// e---->| Rate matching bit interleaving |---->f /////////////////////////
///////////
//stop_meas(rm_stats);
//start_meas(i_stats);
nr_interleaving_ldpc(E,
mod_order,
harq_process->e+r_offset,
harq_process->f+r_offset);
//stop_meas(i_stats);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output interleaving f[%d]= %d r_offset %d\n", i,harq_process->f[i+r_offset], r_offset);
if (r==harq_process->C-1)
write_output("enc_output.m","enc",harq_process->f,G,1,4);
#endif
r_offset += E;
///////////
///////////////////////////////////////////////////////////////////////////////////////////////
}
memcpy(ulsch->g,harq_process->f,G>>3); // g is the concatenated code block
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return(0);
}
......@@ -38,6 +38,10 @@
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/impl_defs_top.h"
#include "PHY/defs_common.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#define MAX_NUM_RU_PER_gNB MAX_NUM_RU_PER_eNB
......@@ -72,6 +76,7 @@ typedef struct {
uint64_t dci_pdu[2];
} NR_gNB_DCI_ALLOC_t;
typedef struct {
uint8_t num_dci;
uint8_t num_pdsch_rnti;
......@@ -79,6 +84,14 @@ typedef struct {
} NR_gNB_PDCCH;
typedef enum {
NR_SCH_IDLE,
NR_ACTIVE,
NR_CBA_ACTIVE,
NR_DISABLED
} NR_SCH_status_t;
typedef struct {
/// Nfapi DLSCH PDU
nfapi_nr_dl_config_dlsch_pdu dlsch_pdu;
......@@ -114,7 +127,6 @@ typedef struct {
typedef struct {
/// Pointers to 16 HARQ processes for the DLSCH
NR_DL_gNB_HARQ_t *harq_processes[NR_MAX_NB_HARQ_PROCESSES];
/// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
......@@ -160,6 +172,170 @@ typedef struct {
} NR_gNB_DLSCH_t;
typedef struct {
/// Nfapi ULSCH PDU
nfapi_nr_ul_config_ulsch_pdu ulsch_pdu;
/// Frame where current HARQ round was sent
uint32_t frame;
/// Subframe where current HARQ round was sent
uint32_t subframe;
/// Index of current HARQ round for this DLSCH
uint8_t round;
/// Last TPC command
uint8_t TPC;
/// MIMO mode for this DLSCH
MIMO_mode_t mimo_mode;
/// Flag indicating that this ULSCH has been allocated by a DCI (otherwise it is a retransmission based on PHICH NAK)
uint8_t dci_alloc;
/// Flag indicating that this ULSCH has been allocated by a RAR (otherwise it is a retransmission based on PHICH NAK or DCI)
uint8_t rar_alloc;
/// Status Flag indicating for this ULSCH (idle,active,disabled)
NR_SCH_status_t status;
/// Subframe scheduling indicator (i.e. Transmission opportunity indicator)
uint8_t subframe_scheduling_flag;
/// Subframe cba scheduling indicator (i.e. CBA Transmission opportunity indicator)
uint8_t subframe_cba_scheduling_flag;
/// PHICH active flag
uint8_t phich_active;
/// PHICH ACK
uint8_t phich_ACK;
/// First Allocated RB - previous scheduling. This is needed for PHICH generation which is done after a new scheduling
uint16_t previous_first_rb;
/// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
uint8_t handled;
/// Flag to indicate that this ULSCH is for calibration information sent from UE (i.e. no MAC SDU to pass up)
// int calibration_flag;
/// delta_TF for power control
int32_t delta_TF;
/////////////////////// ulsch decoding ///////////////////////
/// Transport block size (This is A from 38.212 V15.4.0 section 5.1)
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[MAX_NUM_NR_ULSCH_SEGMENTS];
/// Number of bits in each code block (38.212 V15.4.0 section 5.2.2)
uint32_t K;
/// Number of "Filler" bits added in the code block segmentation (38.212 V15.4.0 section 5.2.2)
uint32_t F;
/// Number of code blocks after code block segmentation (38.212 V15.4.0 section 5.2.2)
uint32_t C;
/// Pointers to code blocks after LDPC coding (38.212 V15.4.0 section 5.3.2)
int16_t *d[MAX_NUM_NR_ULSCH_SEGMENTS];
/// LDPC processing buffer
t_nrLDPC_procBuf* p_nrLDPC_procBuf[MAX_NUM_NR_ULSCH_SEGMENTS];
/// LDPC lifting size (38.212 V15.4.0 table 5.3.2-1)
uint32_t Z;
/// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
int16_t e[MAX_NUM_NR_DLSCH_SEGMENTS][3*8448];
/// Number of bits in each code block after rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
uint32_t E;
/// Number of soft channel bits after code block concatenation (38.212 V15.4.0 section 5.5)
uint32_t G;
//////////////////////////////////////////////////////////////
/////////////////////////// DMRS /////////////////////////////
/// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2)
uint8_t n_DMRS;
/// n_DMRS 2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1)
uint8_t n_DMRS2;
/// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2) - previous scheduling
/// This is needed for PHICH generation which
/// is done after a new scheduling
uint8_t previous_n_DMRS;
//////////////////////////////////////////////////////////////
///////////////////// UCI multiplexing ///////////////////////
/// CQI CRC status
uint8_t cqi_crc_status;
/// Pointer to CQI data
uint8_t o[MAX_CQI_BYTES];
/// Format of CQI data
UCI_format_t uci_format;
/// Length of CQI data under RI=1 assumption(bits)
uint8_t Or1;
/// Length of CQI data under RI=2 assumption(bits)
uint8_t Or2;
/// Rank information
uint8_t o_RI[2];
/// Length of rank information (bits)
uint8_t O_RI;
/// Pointer to ACK
uint8_t o_ACK[4];
/// Length of ACK information (bits)
uint8_t O_ACK;
/// The value of DAI in DCI format 0
uint8_t V_UL_DAI;
/// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
int8_t q[MAX_CQI_PAYLOAD];
/// number of coded CQI bits after interleaving
uint8_t o_RCC;
/// coded and interleaved CQI bits
int8_t o_w[(MAX_CQI_BITS+8)*3];
/// coded CQI bits
int8_t o_d[96+((MAX_CQI_BITS+8)*3)];
/// coded ACK bits
int16_t q_ACK[MAX_ACK_PAYLOAD];
/// coded RI bits
int16_t q_RI[MAX_RI_PAYLOAD];
/// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled
uint8_t h[MAX_NUM_CHANNEL_BITS];
/// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
//////////////////////////////////////////////////////////////
} NR_UL_gNB_HARQ_t;
typedef struct {
/// Pointers to 16 HARQ processes for the ULSCH
NR_UL_gNB_HARQ_t *harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES];
/// Current HARQ process id
int harq_process_id[NR_MAX_SLOTS_PER_FRAME];
/// HARQ process mask, indicates which processes are currently active
uint16_t harq_mask;
/// ACK/NAK Bundling flag
uint8_t bundling;
/// beta_offset_cqi times 8
uint16_t beta_offset_cqi_times8;
/// beta_offset_ri times 8
uint16_t beta_offset_ri_times8;
/// beta_offset_harqack times 8
uint16_t beta_offset_harqack_times8;
/// Flag to indicate that gNB awaits UE Msg3
uint8_t Msg3_active;
/// Flag to indicate that gNB should decode UE Msg3
uint8_t Msg3_flag;
/// Subframe for Msg3
uint8_t Msg3_subframe;
/// Frame for Msg3
uint32_t Msg3_frame;
/// Allocated RNTI for this ULSCH
uint16_t rnti;
/// RNTI type
uint8_t rnti_type;
/// cyclic shift for DM RS
uint8_t cyclicShift;
/// for cooperative communication
uint8_t cooperation_flag;
/// Maximum number of HARQ rounds
uint8_t Mlimit;
/// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations;
/// number of iterations used in last LDPC decoding
uint8_t last_iteration_cnt;
/// num active cba group
uint8_t num_active_cba_groups;
/// num active cba group
uint16_t cba_rnti[NUM_MAX_CBA_GROUP];
} NR_gNB_ULSCH_t;
typedef struct {
/// \brief Pointers (dynamic) to the received data in the time domain.
/// - first index: rx antenna [0..nb_antennas_rx[
......@@ -394,17 +570,18 @@ typedef struct PHY_VARS_gNB_s {
LTE_eNB_PHICH phich_vars[2];
NR_gNB_COMMON common_vars;
LTE_eNB_UCI uci_vars[NUMBER_OF_UE_MAX];
LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PRACH prach_vars;
NR_gNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams
LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA
LTE_eNB_UCI uci_vars[NUMBER_OF_UE_MAX];
LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PRACH prach_vars;
NR_gNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams
NR_gNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1][2]; // [Nusers times + number of RA][2 codewords], index 0 in [NUMBER_OF_UE_MAX+1] is for RA
// LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA
NR_gNB_DLSCH_t *dlsch_SI,*dlsch_ra,*dlsch_p;
NR_gNB_DLSCH_t *dlsch_MCH;
NR_gNB_DLSCH_t *dlsch_PCH;
LTE_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX];
LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX];
LTE_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX];
LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX];
uint8_t pbch_configured;
uint8_t pbch_pdu[4]; //PBCH_PDU_SIZE
......
......@@ -1054,8 +1054,8 @@ typedef struct {
NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX];
NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX];
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX];
NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][2]; // two RxTx Threads
NR_UE_ULSCH_t *ulsch[NUMBER_OF_CONNECTED_eNB_MAX];
NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads
NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words
NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX];
NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX];
NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX];
......
......@@ -87,10 +87,10 @@
#define NR_MAX_CSET_DURATION 3
#define NR_MAX_NB_RBG 18
#define NR_MAX_NB_LAYERS 8
#define NR_MAX_NB_LAYERS 8 // SU-MIMO (3GPP TS 38.211 V15.4.0 section 7.3.1.3)
#define NR_MAX_NB_CODEWORDS 2
#define NR_MAX_NB_HARQ_PROCESSES 16
#define NR_MAX_PDSCH_ENCODED_LENGTH 950984
#define NR_MAX_PDSCH_ENCODED_LENGTH NR_MAX_NB_RB*NR_SYMBOLS_PER_SLOT*NR_NB_SC_PER_RB*8*NR_MAX_NB_LAYERS // 8 is the maximum modulation order (it was 950984 before !!)
#define NR_MAX_PDSCH_TBS 3824
typedef enum {
......
......@@ -150,7 +150,7 @@ void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_i
*
*********************************************************************/
void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_harq_processes_pusch)
void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx, uint8_t number_harq_processes_pusch)
{
NR_UE_ULSCH_t *ulsch;
......@@ -160,7 +160,7 @@ void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_h
memset(ulsch,0,sizeof(NR_UE_ULSCH_t));
ue->ulsch[gNB_id] = ulsch;
ue->ulsch[thread_id][gNB_id][code_word_idx] = ulsch;
}
else {
LOG_E(PHY, "Fatal memory allocation problem at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__);
......@@ -185,7 +185,7 @@ void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_h
}
for (int slot_tx = 0; slot_tx < NR_MAX_SLOTS_PER_FRAME; slot_tx++) {
ue->ulsch[gNB_id]->harq_process_id[slot_tx] = NR_MAX_HARQ_PROCESSES;
ue->ulsch[thread_id][gNB_id][code_word_idx]->harq_process_id[slot_tx] = NR_MAX_HARQ_PROCESSES;
}
}
......@@ -202,9 +202,9 @@ void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_h
*
*********************************************************************/
void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id)
void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx)
{
NR_UE_ULSCH_t *ulsch = ue->ulsch[gNB_id];
NR_UE_ULSCH_t *ulsch = ue->ulsch[thread_id][gNB_id][code_word_idx];
for (int process_id = 0; process_id < ulsch->number_harq_processes_for_pusch; process_id++) {
......@@ -215,7 +215,7 @@ void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id)
free16(ulsch, sizeof(NR_UE_ULSCH_t));
ue->ulsch[gNB_id] = NULL;
ue->ulsch[thread_id][gNB_id][code_word_idx] = NULL;
}
/*******************************************************************
......
......@@ -83,17 +83,21 @@ void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_i
/** \brief This function configures uplink HARQ context
@param PHY_VARS_NR_UE ue context
@param gNB_id gNodeB identifier
@param thread_id RXTX thread index
@param code_word_idx code word index
@param number_harq_processes_pusch maximum number of uplink HARQ processes
@returns none */
void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_harq_processes_pusch);
void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx, uint8_t number_harq_processes_pusch);
/** \brief This function releases uplink HARQ context
@param PHY_VARS_NR_UE ue context
@param gNB_id gNodeB identifier
@param thread_id RXTX thread index
@param code_word_idx code word index
@returns none */
void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id);
void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx);
/** \brief This function stores slot for transmission in HARQ context
@param ulsch uplink context
......
......@@ -409,7 +409,7 @@ int main(int argc, char **argv) {
r_im[i] = malloc(frame_length_complex_samples * sizeof(double));
bzero(r_im[i], frame_length_complex_samples * sizeof(double));
txdata[i] = malloc(frame_length_complex_samples * sizeof(int));
bzero(r_re[i], frame_length_complex_samples * sizeof(int));
bzero(r_re[i], frame_length_complex_samples * sizeof(int)); // [hna] r_re should be txdata
}
if (pbch_file_fd != NULL) {
......@@ -485,7 +485,7 @@ int main(int argc, char **argv) {
rel15->nb_layers = Nl;
rel15->nb_re_dmrs = nb_re_dmrs;
rel15->transport_block_size = TBS;
double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384);
double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc
short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384);
short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384);
double errors_bit_uncoded = 0;
......
/*
* 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 <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
#include "common/ran_context.h"
#include "SIMULATION/TOOLS/sim.h"
#include "SIMULATION/RF/rf.h"
#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/defs_gNB.h"
#include "PHY/INIT/phy_init.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
#include "PHY/NR_REFSIG/nr_mod_table.h"
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/NR_TRANSPORT/nr_transport.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "SCHED_NR/sched_nr.h"
//#include "PHY/MODULATION/modulation_common.h"
//#include "common/config/config_load_configmodule.h"
//#include "UTIL/LISTS/list.h"
//#include "common/ran_context.h"
//#define DEBUG_ULSCHSIM
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
double cpuf;
// dummy functions
int nfapi_mode = 0;
int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) {
return (0);
}
int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) {
return (0);
}
int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) {
return (0);
}
int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) {
return (0);
}
int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) {
return (0);
}
uint32_t from_nrarfcn(int nr_bandP, uint32_t dl_earfcn) {
return (0);
}
int32_t get_uldl_offset(int eutra_bandP) {
return (0);
}
NR_IF_Module_t *
NR_IF_Module_init(int Mod_id) {
return (NULL);
}
void exit_function(const char *file, const char *function, const int line, const char *s) {
const char *msg = s == NULL ? "no comment" : s;
printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
exit(-1);
}
// needed for some functions
PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } };
uint16_t n_rnti = 0x1234;
char quantize(double D, double x, unsigned char B) {
double qxd;
short maxlev;
qxd = floor(x / D);
maxlev = 1 << (B - 1); //(char)(pow(2,B-1));
//printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev);
if (qxd <= -maxlev)
qxd = -maxlev;
else if (qxd >= maxlev)
qxd = maxlev - 1;
return ((char) qxd);
}
int main(int argc, char **argv) {
char c;
int i,sf; //,j,l,aa;
double SNR, SNR_lin, snr0 = -2.0, snr1 = 2.0;
double snr_step = 0.1;
uint8_t snr1set = 0;
int **txdata;
double **s_re, **s_im, **r_re, **r_im;
// int sync_pos, sync_pos_slot;
// FILE *rx_frame_file;
FILE *output_fd = NULL;
uint8_t write_output_file = 0;
// int subframe_offset;
// char fname[40], vname[40];
int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
uint8_t transmission_mode = 1, n_tx = 1, n_rx = 1;
uint16_t Nid_cell = 0;
channel_desc_t *gNB2UE;
uint8_t extended_prefix_flag = 0;
int8_t interf1 = -21, interf2 = -21;
FILE *input_fd = NULL, *pbch_file_fd = NULL;
//char input_val_str[50],input_val_str2[50];
//uint16_t NB_RB=25;
SCM_t channel_model = AWGN; //Rayleigh1_anticorr;
uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1;
unsigned char frame_type = 0;
unsigned char pbch_phase = 0;
int frame = 0, subframe = 0;
int frame_length_complex_samples;
//int frame_length_complex_samples_no_prefix;
NR_DL_FRAME_PARMS *frame_parms;
//nfapi_nr_config_request_t *gNB_config;
// uint8_t Kmimo = 0;
uint32_t Nsoft = 0;
double sigma;
unsigned char qbits = 8;
int ret;
//int run_initial_sync=0;
int loglvl = OAILOG_WARNING;
float target_error_rate = 0.01;
uint64_t SSB_positions=0x01;
uint16_t nb_symb_sch = 12;
uint16_t nb_rb = 50;
uint8_t Imcs = 9;
cpuf = get_cpu_freq_GHz();
if (load_configmodule(argc, argv) == 0) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
//logInit();
randominit(0);
while ((c = getopt(argc, argv, "df:hpg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:")) != -1) {
switch (c) {
case 'f':
write_output_file = 1;
output_fd = fopen(optarg, "w");
if (output_fd == NULL) {
printf("Error opening %s\n", optarg);
exit(-1);
}
break;
case 'd':
frame_type = 1;
break;
case 'g':
switch ((char) *optarg) {
case 'A':
channel_model = SCM_A;
break;
case 'B':
channel_model = SCM_B;
break;
case 'C':
channel_model = SCM_C;
break;
case 'D':
channel_model = SCM_D;
break;
case 'E':
channel_model = EPA;
break;
case 'F':
channel_model = EVA;
break;
case 'G':
channel_model = ETU;
break;
default:
msg("Unsupported channel model!\n");
exit(-1);
}
break;
case 'i':
interf1 = atoi(optarg);
break;
case 'j':
interf2 = atoi(optarg);
break;
case 'n':
n_trials = atoi(optarg);
break;
case 's':
snr0 = atof(optarg);
msg("Setting SNR0 to %f\n", snr0);
break;
case 'S':
snr1 = atof(optarg);
snr1set = 1;
msg("Setting SNR1 to %f\n", snr1);
break;
case 'p':
extended_prefix_flag = 1;
break;
/*
case 'r':
ricean_factor = pow(10,-.1*atof(optarg));
if (ricean_factor>1) {
printf("Ricean factor must be between 0 and 1\n");
exit(-1);
}
break;
*/
case 'y':
n_tx = atoi(optarg);
if ((n_tx == 0) || (n_tx > 2)) {
msg("Unsupported number of tx antennas %d\n", n_tx);
exit(-1);
}
break;
case 'z':
n_rx = atoi(optarg);
if ((n_rx == 0) || (n_rx > 2)) {
msg("Unsupported number of rx antennas %d\n", n_rx);
exit(-1);
}
break;
case 'M':
SSB_positions = atoi(optarg);
break;
case 'N':
Nid_cell = atoi(optarg);
break;
case 'R':
N_RB_DL = atoi(optarg);
N_RB_UL = N_RB_DL;
break;
case 'F':
input_fd = fopen(optarg, "r");
if (input_fd == NULL) {
printf("Problem with filename %s\n", optarg);
exit(-1);
}
break;
case 'P':
pbch_phase = atoi(optarg);
if (pbch_phase > 3)
printf("Illegal PBCH phase (0-3) got %d\n", pbch_phase);
break;
case 'm':
Imcs = atoi(optarg);
break;
case 'l':
nb_symb_sch = atoi(optarg);
break;
case 'r':
nb_rb = atoi(optarg);
break;
case 'x':
transmission_mode = atoi(optarg);
break;
default:
case 'h':
printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]);
printf("-h This message\n");
printf("-p Use extended prefix mode\n");
printf("-d Use TDD\n");
printf("-n Number of frames to simulate\n");
printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n");
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
printf("-t Delay spread for multipath channel\n");
printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n");
printf("-x Transmission mode (1,2,6 for the moment)\n");
printf("-y Number of TX antennas used in eNB\n");
printf("-z Number of RX antennas used in UE\n");
printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n");
printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n");
printf("-M Multiple SSB positions in burst\n");
printf("-N Nid_cell\n");
printf("-R N_RB_DL\n");
printf("-O oversampling factor (1,2,4,8,16)\n");
printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
// printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
printf("-f Output filename (.txt format) for Pe/SNR results\n");
printf("-F Input filename (.txt format) for RX conformance testing\n");
exit(-1);
break;
}
}
logInit();
set_glog(loglvl);
T_stdout = 1;
if (snr1set == 0)
snr1 = snr0 + 10;
gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model,
61.44e6, //N_RB2sampling_rate(N_RB_DL),
40e6, //N_RB2channel_bandwidth(N_RB_DL),
0, 0, 0);
if (gNB2UE == NULL) {
msg("Problem generating channel model. Exiting.\n");
exit(-1);
}
RC.gNB = (PHY_VARS_gNB ** *) malloc(sizeof(PHY_VARS_gNB **));
RC.gNB[0] = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *));
RC.gNB[0][0] = malloc(sizeof(PHY_VARS_gNB));
gNB = RC.gNB[0][0];
//gNB_config = &gNB->gNB_config;
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
frame_parms->nb_antennas_tx = n_tx;
frame_parms->nb_antennas_rx = n_rx;
frame_parms->N_RB_DL = N_RB_DL;
frame_parms->N_RB_UL = N_RB_UL;
frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL;
crcTableInit();
nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions);
phy_init_nr_gNB(gNB, 0, 0);
//init_eNB_afterRU();
frame_length_complex_samples = frame_parms->samples_per_subframe;
//frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
s_re = malloc(2 * sizeof(double *));
s_im = malloc(2 * sizeof(double *));
r_re = malloc(2 * sizeof(double *));
r_im = malloc(2 * sizeof(double *));
txdata = malloc(2 * sizeof(int * ));
for (i = 0; i < 2; i++) {
s_re[i] = malloc(frame_length_complex_samples * sizeof(double));
bzero(s_re[i], frame_length_complex_samples * sizeof(double));
s_im[i] = malloc(frame_length_complex_samples * sizeof(double));
bzero(s_im[i], frame_length_complex_samples * sizeof(double));
r_re[i] = malloc(frame_length_complex_samples * sizeof(double));
bzero(r_re[i], frame_length_complex_samples * sizeof(double));
r_im[i] = malloc(frame_length_complex_samples * sizeof(double));
bzero(r_im[i], frame_length_complex_samples * sizeof(double));
txdata[i] = malloc(frame_length_complex_samples * sizeof(int));
bzero(r_re[i], frame_length_complex_samples * sizeof(int)); // [hna] r_re should be txdata
}
if (pbch_file_fd != NULL) {
load_pbch_desc(pbch_file_fd);
}
/* for (int k=0; k<2; k++) {
// Create transport channel structures for 2 transport blocks (MIMO)
for (i=0; i<2; i++) {
gNB->dlsch[k][i] = new_gNB_dlsch(Kmimo,8,Nsoft,0,frame_parms,gNB_config);
if (!gNB->dlsch[k][i]) {
printf("Can't get eNB dlsch structures\n");
exit(-1);
}
gNB->dlsch[k][i]->Nsoft = 10;
gNB->dlsch[k][i]->rnti = n_rnti+k;
}
}*/
//configure UE
UE = malloc(sizeof(PHY_VARS_NR_UE));
memcpy(&UE->frame_parms, frame_parms, sizeof(NR_DL_FRAME_PARMS));
//phy_init_nr_top(frame_parms);
if (init_nr_ue_signal(UE, 1, 0) != 0) {
printf("Error at UE NR initialisation\n");
exit(-1);
}
//nr_init_frame_parms_ue(&UE->frame_parms);
//init_nr_ue_transport(UE, 0);
for (sf = 0; sf < 2; sf++) {
for (i = 0; i < 2; i++) {
UE->ulsch[sf][0][i] = new_nr_ue_ulsch(N_RB_UL, 8, 0);
if (!UE->ulsch[sf][0][i]) {
printf("Can't get ue ulsch structures\n");
exit(-1);
}
}
}
UE->dlsch_SI[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0);
UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0);
unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
//time_stats_t *rm_stats, *te_stats, *i_stats;
uint8_t is_crnti = 0, llr8_flag = 0;
unsigned int TBS = 8424;
unsigned int available_bits;
uint8_t nb_re_dmrs = 6;
uint16_t length_dmrs = 1;
unsigned char mod_order;
uint8_t Nl = 1;
uint8_t rvidx = 0;
uint8_t UE_id = 1;
NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id][0];
nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15;
NR_UE_ULSCH_t *ulsch_ue = UE->ulsch[0][0][0];
ulsch_ue->nb_re_dmrs = nb_re_dmrs; //[adk] A HOT FIX until cearting nfapi_nr_ul_config_ulsch_pdu_rel15_t
mod_order = nr_get_Qm(Imcs, 1);
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1);
TBS = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, Nl);
printf("available bits %d TBS %d mod_order %d\n", available_bits, TBS, mod_order);
/////////// setting rel15_ul parameters ///////////
rel15_ul->number_rbs = nb_rb;
rel15_ul->number_symbols = nb_symb_sch;
rel15_ul->Qm = mod_order;
rel15_ul->mcs = Imcs;
rel15_ul->rv = rvidx;
rel15_ul->n_layers = Nl;
///////////////////////////////////////////////////
double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc
short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384);
short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384);
unsigned int errors_bit_uncoded = 0;
// unsigned char *estimated_output;
unsigned char *estimated_output_bit;
unsigned char *test_input_bit;
unsigned int errors_bit = 0;
test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
// estimated_output = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
unsigned char *test_input;
test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8);
for (i = 0; i < TBS / 8; i++)
test_input[i] = (unsigned char) rand();
// estimated_output = ulsch_gNB->harq_processes[harq_pid]->b;
/////////////////////////[adk] preparing UL harq_process parameters/////////////////////////
///////////
NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid];
if (harq_process_ul_ue) {
harq_process_ul_ue->mcs = Imcs;
harq_process_ul_ue->Nl = Nl;
harq_process_ul_ue->nb_rb = nb_rb;
harq_process_ul_ue->nb_symbols = nb_symb_sch;
harq_process_ul_ue->rvidx = rvidx;
harq_process_ul_ue->TBS = TBS;
harq_process_ul_ue->a = &test_input[0];
}
///////////
////////////////////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG_ULSCHSIM
for (i = 0; i < TBS / 8; i++) printf("test_input[i]=%d \n",test_input[i]);
#endif
/*for (int i=0; i<TBS/8; i++)
printf("test input[%d]=%d \n",i,test_input[i]);*/
//printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32));
// generate signal
/////////////////////////[adk] ULSCH coding/////////////////////////
///////////
if (input_fd == NULL) {
nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid);
}
///////////
////////////////////////////////////////////////////////////////////
for (SNR = snr0; SNR < snr1; SNR += snr_step) {
n_errors = 0;
n_false_positive = 0;
for (trial = 0; trial < n_trials; trial++) {
errors_bit_uncoded = 0;
for (i = 0; i < available_bits; i++) {
#ifdef DEBUG_CODER
if ((i&0xf)==0)
printf("\ne %d..%d: ",i,i+15);
#endif
/*
if (i<16){
printf("dlsch_encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]);
printf("ulsch_encoder output f[%d] = %d\n",i,ulsch_ue->harq_processes[0]->f[i]);
}
*/
if (ulsch_ue->harq_processes[0]->f[i] == 0)
modulated_input[i] = 1.0; ///sqrt(2); //QPSK
else
modulated_input[i] = -1.0; ///sqrt(2);
//if (i<16) printf("modulated_input[%d] = %d\n",i,modulated_input[i]);
//SNR =10;
SNR_lin = pow(10, SNR / 10.0);
sigma = 1.0 / sqrt(2 * SNR_lin);
#if 1
channel_output_fixed[i] = (short) quantize(sigma / 4.0 / 4.0,
modulated_input[i] + sigma * gaussdouble(0.0, 1.0),
qbits);
#else
channel_output_fixed[i] = (short) quantize(0.01, modulated_input[i], qbits);
#endif
//channel_output_fixed[i] = (char)quantize8bit(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0));
//printf("llr[%d]=%d\n",i,channel_output_fixed[i]);
//printf("channel_output_fixed[%d]: %d\n",i,channel_output_fixed[i]);
//channel_output_fixed[i] = (char)quantize(1,channel_output_fixed[i],qbits);
//if (i<16) printf("channel_output_fixed[%d] = %d\n",i,channel_output_fixed[i]);
//Uncoded BER
if (channel_output_fixed[i] < 0)
channel_output_uncoded[i] = 1; //QPSK demod
else
channel_output_uncoded[i] = 0;
if (channel_output_uncoded[i] != ulsch_ue->harq_processes[harq_pid]->f[i])
errors_bit_uncoded = errors_bit_uncoded + 1;
}
//if (errors_bit_uncoded>10)
printf("errors bits uncoded %u\n", errors_bit_uncoded);
#ifdef DEBUG_CODER
printf("\n");
exit(-1);
#endif
ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms,
frame, nb_symb_sch, subframe, harq_pid, is_crnti, llr8_flag);
if (ret > ulsch_gNB->max_ldpc_iterations)
n_errors++;
//count errors
errors_bit = 0;
for (i = 0; i < TBS; i++) {
estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7);
test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
if (estimated_output_bit[i] != test_input_bit[i]) {
errors_bit++;
//printf("estimated bits error occurs @%d ",i);
}
}
if (errors_bit > 0) {
n_false_positive++;
if (n_trials == 1)
printf("errors_bit %d (trial %d)\n", errors_bit, trial);
}
}
printf("*****************************************\n");
printf("SNR %f, BLER %f (false positive %f)\n", SNR,
(float) n_errors / (float) n_trials,
(float) n_false_positive / (float) n_trials);
printf("*****************************************\n");
if ((float) n_errors / (float) n_trials < target_error_rate) {
printf("PUSCH test OK\n");
break;
}
}
/*LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1);
if (gNB->frame_parms.nb_antennas_tx>1)
LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1);*/
//TODO: loop over slots
/*for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
if (gNB_config->subframe_config.dl_cyclic_prefix_type.value == 1) {
PHY_ofdm_mod(gNB->common_vars.txdataF[aa],
txdata[aa],
frame_parms->ofdm_symbol_size,
12,
frame_parms->nb_prefix_samples,
CYCLIC_PREFIX);
} else {
nr_normal_prefix_mod(gNB->common_vars.txdataF[aa],
txdata[aa],
14,
frame_parms);
}
}
LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1);
if (gNB->frame_parms.nb_antennas_tx>1)
LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1);
for (i=0; i<frame_length_complex_samples; i++) {
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
}
}*/
for (i = 0; i < 2; i++) {
printf("----------------------\n");
printf("freeing codeword %d\n", i);
printf("----------------------\n");
printf("gNB ulsch[0][%d]\n", i); // [hna] ulsch[0] is for RA
free_gNB_ulsch(gNB->ulsch[0][i]);
printf("gNB ulsch[%d][%d]\n",UE_id, i);
free_gNB_ulsch(gNB->ulsch[UE_id][i]);
for (sf = 0; sf < 2; sf++) {
printf("UE ulsch[%d][0][%d]\n", sf, i);
if (UE->ulsch[sf][0][i])
free_nr_ue_ulsch(UE->ulsch[sf][0][i]);
}
printf("\n");
}
for (i = 0; i < 2; i++) {
free(s_re[i]);
free(s_im[i]);
free(r_re[i]);
free(r_im[i]);
free(txdata[i]);
}
free(s_re);
free(s_im);
free(r_re);
free(r_im);
free(txdata);
if (output_fd)
fclose(output_fd);
if (input_fd)
fclose(input_fd);
return (n_errors);
}
......@@ -54,6 +54,8 @@
int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue)
{
int gNB_id = 0;
int thread_number = 0;
int code_word_idx = 0;
int harq_pid = 0;
int ndi = 1;
uint8_t rnti_type = _C_RNTI_;
......@@ -61,7 +63,7 @@ int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue)
printf("\nHARQ Uplink \n");
config_uplink_harq_process(phy_vars_ue , gNB_id, NR_DEFAULT_DLSCH_HARQ_PROCESSES);
config_uplink_harq_process(phy_vars_ue , gNB_id, thread_number, code_word_idx, NR_DEFAULT_DLSCH_HARQ_PROCESSES);
NR_UE_ULSCH_t *ulsch_harq = phy_vars_ue->ulsch[gNB_id];
......@@ -91,7 +93,7 @@ int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue)
}
}
release_uplink_harq_process(phy_vars_ue , gNB_id);
release_uplink_harq_process(phy_vars_ue , gNB_id, thread_number, code_word_idx);
return 0;
}
......
......@@ -58,11 +58,7 @@ extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][MAX_MOBILES
#ifndef PHYSIM
#define NB_INST 1
#else
extern unsigned char NB_INST;
#endif
extern unsigned char NB_eNB_INST;
extern unsigned char NB_UE_INST;
extern unsigned char NB_RN_INST;
......
......@@ -44,17 +44,11 @@ extern LogicalChannelConfig_t SRB1_logicalChannelConfig_defaultValue;
extern LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue;
#ifndef PHY_EMUL
#ifndef PHYSIM
//#define NB_INST 1
#else
extern unsigned char NB_INST;
#endif
extern unsigned char NB_eNB_INST;
extern unsigned char NB_UE_INST;
extern unsigned short NODE_ID[1];
extern void* bigphys_malloc(int);
#endif
//CONSTANTS
......
......@@ -43,17 +43,11 @@ extern LogicalChannelConfig_t SRB1_logicalChannelConfig_defaultValue;
extern LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue;
#ifndef PHY_EMUL
#ifndef PHYSIM
//#define NB_INST 1
#else
extern unsigned char NB_INST;
#endif
extern unsigned char NB_eNB_INST;
extern unsigned char NB_UE_INST;
extern unsigned short NODE_ID[1];
extern void* bigphys_malloc(int);
#endif
//CONSTANTS
......
#ifndef OPENAIRINTERFACE5G_LIMITS_H_
#define OPENAIRINTERFACE5G_LIMITS_H_
#if defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
#if 1 /*defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)*/
# define NUMBER_OF_eNB_MAX 1
# define NUMBER_OF_gNB_MAX 1
# define NUMBER_OF_RU_MAX 2
# define NUMBER_OF_NR_RU_MAX 2
# ifndef PHYSIM
# ifndef UE_EXPANSION
# define NUMBER_OF_UE_MAX 16
# define NUMBER_OF_NR_UE_MAX 16
......@@ -17,6 +18,12 @@
# define NUMBER_OF_CONNECTED_eNB_MAX 1
# define NUMBER_OF_CONNECTED_gNB_MAX 1
# endif
# else
# define NUMBER_OF_UE_MAX 1
# define NUMBER_OF_NR_UE_MAX 1
# define NUMBER_OF_CONNECTED_eNB_MAX 1
# define NUMBER_OF_CONNECTED_gNB_MAX 1
# endif
#else
# define NUMBER_OF_eNB_MAX 7
# define NUMBER_OF_gNB_MAX 7
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment