Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Michael Black
OpenXG-RAN
Commits
66442aa4
Commit
66442aa4
authored
Apr 02, 2019
by
Ahmed Hussein
Committed by
Thomas Schlichter
Jun 04, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implementation of LLR computation for 4, 16, and 64 QAM (tested)
parent
54ebd39b
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
581 additions
and
51 deletions
+581
-51
cmake_targets/CMakeLists.txt
cmake_targets/CMakeLists.txt
+1
-0
openair1/PHY/INIT/nr_init.c
openair1/PHY/INIT/nr_init.c
+22
-23
openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
+91
-0
openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
+365
-0
openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+1
-1
openair1/PHY/defs_gNB.h
openair1/PHY/defs_gNB.h
+39
-2
openair1/SIMULATION/NR_PHY/ulsim.c
openair1/SIMULATION/NR_PHY/ulsim.c
+62
-25
No files found.
cmake_targets/CMakeLists.txt
View file @
66442aa4
...
...
@@ -1285,6 +1285,7 @@ set(PHY_SRC_UE
${
OPENAIR1_DIR
}
/PHY/NR_TRANSPORT/nr_ulsch.c
${
OPENAIR1_DIR
}
/PHY/NR_TRANSPORT/nr_tbs_tools.c
${
OPENAIR1_DIR
}
/PHY/NR_TRANSPORT/nr_sch_dmrs.c
${
OPENAIR1_DIR
}
/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
${
OPENAIR1_DIR
}
/PHY/NR_REFSIG/nr_gold.c
${
OPENAIR1_DIR
}
/PHY/TOOLS/file_output.c
${
OPENAIR1_DIR
}
/PHY/TOOLS/cadd_vv.c
...
...
openair1/PHY/INIT/nr_init.c
View file @
66442aa4
...
...
@@ -80,8 +80,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS
*
const
fp
=
&
gNB
->
frame_parms
;
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;
NR_gNB_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
;
...
...
@@ -200,39 +200,38 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
for (i=0; i<64; i++) prach_vars->prach_ifft[0][i] = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t));
prach_vars->rxsigF[0] = (int16_t **)malloc16_clear(64*sizeof(int16_t *));
*/
for (int
ulsch_id=0; ulsch_id<NUMBER_OF_NR_ULSCH_MAX; ulsch
_id++) {
for
(
int
UE_id
=
0
;
UE_id
<
NUMBER_OF_UE_MAX
;
UE
_id
++
)
{
//FIXME
pusch_vars[UE_id] = (LTE_eNB_PUSCH *)malloc16_clear( NUMBER_OF_UE_MAX*sizeof(LTE_eNB_PUSCH) );
pusch_vars[UE_id]->rxdataF_ext = (int32_t **)malloc16( 2*sizeof(int32_t *) );
pusch_vars[UE_id]->rxdataF_ext2 = (int32_t **)malloc16( 2*sizeof(int32_t *) );
pusch_vars[UE_id]->drs_ch_estimates = (int32_t **)malloc16( 2*sizeof(int32_t *) );
pusch_vars
[
UE_id
]
=
(
NR_gNB_PUSCH
*
)
malloc16_clear
(
sizeof
(
NR_gNB_PUSCH
)
);
pusch_vars
[
UE_id
]
->
rxdataF_ext
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
pusch_vars
[
UE_id
]
->
rxdataF_ext2
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
pusch_vars
[
UE_id
]
->
drs_ch_estimates
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
pusch_vars
[
UE_id
]
->
drs_ch_estimates_time
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
pusch_vars[UE_id]->rxdataF_comp = (int32_t **)malloc16( 2*sizeof(int32_t *) );
pusch_vars[UE_id]->ul_ch_mag = (int32_t **)malloc16( 2*sizeof(int32_t *) );
pusch_vars[UE_id]->ul_ch_magb = (int32_t **)malloc16( 2*sizeof(int32_t *) );
pusch_vars
[
UE_id
]
->
rxdataF_comp
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
pusch_vars
[
UE_id
]
->
ul_ch_mag
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
pusch_vars
[
UE_id
]
->
ul_ch_magb
=
(
int32_t
**
)
malloc16
(
2
*
sizeof
(
int32_t
*
)
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
// RK 2 times because of output format of FFT!
// FIXME We should get rid of this
pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot );
pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot );
pusch_vars[UE_id]->drs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot );
pusch_vars
[
UE_id
]
->
rxdataF_ext
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
sizeof
(
int32_t
)
*
cfg
->
rf_config
.
ul_carrier_bandwidth
.
value
*
12
*
fp
->
symbols_per_slot
);
pusch_vars
[
UE_id
]
->
rxdataF_ext2
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
sizeof
(
int32_t
)
*
cfg
->
rf_config
.
ul_carrier_bandwidth
.
value
*
12
*
fp
->
symbols_per_slot
);
pusch_vars
[
UE_id
]
->
drs_ch_estimates
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
sizeof
(
int32_t
)
*
cfg
->
rf_config
.
ul_carrier_bandwidth
.
value
*
12
*
fp
->
symbols_per_slot
);
pusch_vars
[
UE_id
]
->
drs_ch_estimates_time
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
2
*
sizeof
(
int32_t
)
*
fp
->
ofdm_symbol_size
);
pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot );
pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 );
pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 );
pusch_vars
[
UE_id
]
->
rxdataF_comp
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
sizeof
(
int32_t
)
*
cfg
->
rf_config
.
ul_carrier_bandwidth
.
value
*
12
*
fp
->
symbols_per_slot
);
pusch_vars
[
UE_id
]
->
ul_ch_mag
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
fp
->
symbols_per_slot
*
sizeof
(
int32_t
)
*
cfg
->
rf_config
.
ul_carrier_bandwidth
.
value
*
12
);
pusch_vars
[
UE_id
]
->
ul_ch_magb
[
i
]
=
(
int32_t
*
)
malloc16_clear
(
fp
->
symbols_per_slot
*
sizeof
(
int32_t
)
*
cfg
->
rf_config
.
ul_carrier_bandwidth
.
value
*
12
);
}
pusch_vars[UE_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
pusch_vars
[
UE_id
]
->
llr
=
(
int16_t
*
)
malloc16_clear
(
(
8
*
((
3
*
8
*
6144
)
+
12
))
*
sizeof
(
int16_t
)
);
// [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
}
//UE_id
/*
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
gNB->UE_stats_ptr[UE_id] = &gNB->UE_stats[UE_id];
gNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration
*/
gNB
->
pdsch_config_dedicated
->
p_a
=
dB0
;
//defaul value until overwritten by RRCConnectionReconfiguration
return
(
0
);
}
/*
...
...
@@ -283,8 +282,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) {
//NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms;
//nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
NR_gNB_COMMON
*
const
common_vars
=
&
gNB
->
common_vars
;
/*LTE_e
NB_PUSCH **const pusch_vars = gNB->pusch_vars;
LTE_eNB_SRS *const srs_vars = gNB->srs_vars;
NR_g
NB_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;*/
uint32_t
***
pdcch_dmrs
=
gNB
->
nr_gold_pdcch_dmrs
;
...
...
openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
0 → 100644
View file @
66442aa4
/*
* 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_TRANSPORT/nr_transport_proto.h.c
* \brief Function prototypes for PHY physical/transport channel processing and generation
* \author Ahmed Hussein
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: ahmed.hussein@iis.fraunhofer.de
* \note
* \warning
*/
#include "PHY/defs_nr_common.h"
/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms.
@param rxdataF_comp Compensated channel output
@param ulsch_llr llr output
@param nb_re number of REs for this allocation
@param symbol OFDM symbol index in sub-frame
*/
void
nr_ulsch_qpsk_llr
(
int32_t
*
rxdataF_comp
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
);
/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16 QAM received waveforms.
@param rxdataF_comp Compensated channel output
@param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 16
@param ulsch_llr llr output
@param nb_re number of RBs for this allocation
@param symbol OFDM symbol index in sub-frame
*/
void
nr_ulsch_16qam_llr
(
int32_t
*
rxdataF_comp
,
int32_t
**
ul_ch_mag
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
);
/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 64 QAM received waveforms.
@param rxdataF_comp Compensated channel output
@param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64
@param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64
@param ulsch_llr llr output
@param nb_re number of REs for this allocation
@param symbol OFDM symbol index in sub-frame
*/
void
nr_ulsch_64qam_llr
(
int32_t
*
rxdataF_comp
,
int32_t
**
ul_ch_mag
,
int32_t
**
ul_ch_magb
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
);
/** \brief This function computes the log-likelihood ratios for 4, 16, and 64 QAM
@param rxdataF_comp Compensated channel output
@param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64
@param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64
@param ulsch_llr llr output
@param nb_re number of REs for this allocation
@param symbol OFDM symbol index in sub-frame
@param mod_order modulation order
*/
void
nr_ulsch_compute_llr
(
int32_t
*
rxdataF_comp
,
int32_t
**
ul_ch_mag
,
int32_t
**
ul_ch_magb
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
,
uint8_t
mod_order
);
\ No newline at end of file
openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
0 → 100644
View file @
66442aa4
/*
* 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_TRANSPORT/nr_ulsch_llr_computation.c
* \brief Top-level routines for LLR computation of the PDSCH physical channel
* \author Ahmed Hussein
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: ahmed.hussein@iis.fraunhofer.de
* \note
* \warning
*/
#include "PHY/defs_nr_common.h"
#include "PHY/sse_intrin.h"
#include "PHY/impl_defs_top.h"
__m128i
xmm0
__attribute__
((
aligned
(
16
)));
__m128i
xmm1
__attribute__
((
aligned
(
16
)));
__m128i
xmm2
__attribute__
((
aligned
(
16
)));
//----------------------------------------------------------------------------------------------
// QPSK
//----------------------------------------------------------------------------------------------
void
nr_ulsch_qpsk_llr
(
int32_t
*
rxdataF_comp
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
)
{
int
i
;
uint32_t
*
rxF
=
(
uint32_t
*
)
rxdataF_comp
;
uint32_t
*
llr32
=
(
uint32_t
*
)
ulsch_llr
;
if
(
!
llr32
)
{
LOG_E
(
PHY
,
"nr_ulsch_qpsk_llr: llr is null, symbol %d, llr32 = %p
\n
"
,
symbol
,
llr32
);
}
for
(
i
=
0
;
i
<
nb_re
;
i
++
)
{
*
llr32
=
*
rxF
;
rxF
++
;
llr32
++
;
}
}
//----------------------------------------------------------------------------------------------
// 16-QAM
//----------------------------------------------------------------------------------------------
void
nr_ulsch_16qam_llr
(
int32_t
*
rxdataF_comp
,
int32_t
**
ul_ch_mag
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
rxF
=
(
__m128i
*
)
rxdataF_comp
;
// __m128i *ch_mag; // [hna] This should be uncommented once channel estimation is implemented
__m128i
llr128
[
2
];
uint32_t
*
llr32
;
// [hna] temp_channel and one_over_sqrt_2 are for temporary use until channel estimation is implemented
// else ul_ch_mag and ul_ch_magb should be used after channel estimation has benn implemented
__m128i
temp_channel
;
int16_t
one_over_sqrt_2
=
23170
;
#elif defined(__arm__)
int16x8_t
*
rxF
=
(
int16x8_t
*
)
&
rxdataF_comp
;
// int16x8_t *ch_mag; // [hna] This should be uncommented once channel estimation is implemented
int16x8_t
xmm0
;
int16_t
*
llr16
;
#endif
int
i
;
unsigned
char
len_mod4
=
0
;
#if defined(__x86_64__) || defined(__i386__)
llr32
=
(
uint32_t
*
)
ulsch_llr
;
#elif defined(__arm__)
llr16
=
(
int16_t
*
)
ulsch_llr
;
#endif
// [hna] This should be uncommented once channel estimation is implemented
// ------------------------------------------------------------
// #if defined(__x86_64__) || defined(__i386__)
// ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*nb_rb*12)];
// #elif defined(__arm__)
// ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*nb_rb*12)];
// #endif
// ------------------------------------------------------------
len_mod4
=
nb_re
&
3
;
nb_re
>>=
2
;
// length in quad words (4 REs)
nb_re
+=
(
len_mod4
==
0
?
0
:
1
);
temp_channel
=
_mm_set1_epi16
((
int16_t
)((
QAM64_n1
*
one_over_sqrt_2
)
>>
15
));
for
(
i
=
0
;
i
<
nb_re
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386)
xmm0
=
_mm_abs_epi16
(
rxF
[
i
]);
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
xmm0
=
_mm_subs_epi16
(
temp_channel
,
xmm0
);
// registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
llr128
[
0
]
=
_mm_unpacklo_epi32
(
rxF
[
i
],
xmm0
);
// llr128[0] contains the llrs of the 1st and 2nd REs
llr128
[
1
]
=
_mm_unpackhi_epi32
(
rxF
[
i
],
xmm0
);
// llr128[1] contains the llrs of the 3rd and 4th REs
// 1st RE
llr32
[
0
]
=
_mm_extract_epi32
(
llr128
[
0
],
0
);
// llr32[0] low 16 bits-> y_R , high 16 bits-> y_I
llr32
[
1
]
=
_mm_extract_epi32
(
llr128
[
0
],
1
);
// llr32[1] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2
// 2nd RE
llr32
[
2
]
=
_mm_extract_epi32
(
llr128
[
0
],
2
);
// llr32[2] low 16 bits-> y_R , high 16 bits-> y_I
llr32
[
3
]
=
_mm_extract_epi32
(
llr128
[
0
],
3
);
// llr32[3] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2
// 3rd RE
llr32
[
4
]
=
_mm_extract_epi32
(
llr128
[
1
],
0
);
// llr32[4] low 16 bits-> y_R , high 16 bits-> y_I
llr32
[
5
]
=
_mm_extract_epi32
(
llr128
[
1
],
1
);
// llr32[5] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2
// 4th RE
llr32
[
6
]
=
_mm_extract_epi32
(
llr128
[
1
],
2
);
// llr32[6] low 16 bits-> y_R , high 16 bits-> y_I
llr32
[
7
]
=
_mm_extract_epi32
(
llr128
[
1
],
3
);
// llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2
llr32
+=
8
;
#elif defined(__arm__)
xmm0
=
vabsq_s16
(
rxF
[
i
]);
xmm0
=
vqsubq_s16
((
*
(
__m128i
*
)
&
ones
[
0
]),
xmm0
);
llr16
[
0
]
=
vgetq_lane_s16
(
rxF
[
i
],
0
);
llr16
[
1
]
=
vgetq_lane_s16
(
rxF
[
i
],
1
);
llr16
[
2
]
=
vgetq_lane_s16
(
xmm0
,
0
);
llr16
[
3
]
=
vgetq_lane_s16
(
xmm0
,
1
);
llr16
[
4
]
=
vgetq_lane_s16
(
rxF
[
i
],
2
);
llr16
[
5
]
=
vgetq_lane_s16
(
rxF
[
i
],
3
);
llr16
[
6
]
=
vgetq_lane_s16
(
xmm0
,
2
);
llr16
[
7
]
=
vgetq_lane_s16
(
xmm0
,
3
);
llr16
[
8
]
=
vgetq_lane_s16
(
rxF
[
i
],
4
);
llr16
[
9
]
=
vgetq_lane_s16
(
rxF
[
i
],
5
);
llr16
[
10
]
=
vgetq_lane_s16
(
xmm0
,
4
);
llr16
[
11
]
=
vgetq_lane_s16
(
xmm0
,
5
);
llr16
[
12
]
=
vgetq_lane_s16
(
rxF
[
i
],
6
);
llr16
[
13
]
=
vgetq_lane_s16
(
rxF
[
i
],
6
);
llr16
[
14
]
=
vgetq_lane_s16
(
xmm0
,
7
);
llr16
[
15
]
=
vgetq_lane_s16
(
xmm0
,
7
);
llr16
+=
16
;
#endif
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
//----------------------------------------------------------------------------------------------
// 64-QAM
//----------------------------------------------------------------------------------------------
void
nr_ulsch_64qam_llr
(
int32_t
*
rxdataF_comp
,
int32_t
**
ul_ch_mag
,
int32_t
**
ul_ch_magb
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
rxF
=
(
__m128i
*
)
rxdataF_comp
;
// __m128i *ch_mag,*ch_magb; // [hna] This should be uncommented once channel estimation is implemented
// [hna] temp_channel and one_over_sqrt_2 are for temporary use until channel estimation is implemented
// else ul_ch_mag and ul_ch_magb should be used after channel estimation has been implemented
__m128i
temp_channel
[
2
];
int16_t
one_over_sqrt_2
=
23170
;
#elif defined(__arm__)
int16x8_t
*
rxF
=
(
int16x8_t
*
)
&
rxdataF_comp
;
// int16x8_t *ch_mag,*ch_magb; // [hna] This should be uncommented once channel estimation is implemented
int16x8_t
xmm1
,
xmm2
;
#endif
int
i
;
unsigned
char
len_mod4
;
// [hna] This should be uncommented once channel estimation is implemented
// -------------------------------------------------------------------------
// #if defined(__x86_64__) || defined(__i386__)
// ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*frame_parms->N_RB_UL*12)];
// ch_magb = (__m128i*)&ul_ch_magb[0][(symbol*frame_parms->N_RB_UL*12)];
// #elif defined(__arm__)
// ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*frame_parms->N_RB_UL*12)];
// ch_magb = (int16x8_t*)&ul_ch_magb[0][(symbol*frame_parms->N_RB_UL*12)];
// #endif
// -------------------------------------------------------------------------
len_mod4
=
nb_re
&
3
;
nb_re
=
nb_re
>>
2
;
// length in quad words (4 REs)
nb_re
+=
((
len_mod4
==
0
)
?
0
:
1
);
temp_channel
[
0
]
=
_mm_set1_epi16
((
int16_t
)((
QAM64_n1
*
one_over_sqrt_2
)
>>
15
));
temp_channel
[
1
]
=
_mm_set1_epi16
((
int16_t
)((
QAM64_n2
*
one_over_sqrt_2
)
>>
15
));
for
(
i
=
0
;
i
<
nb_re
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
xmm1
=
_mm_abs_epi16
(
rxF
[
i
]);
xmm1
=
_mm_subs_epi16
(
temp_channel
[
0
],
xmm1
);
xmm2
=
_mm_abs_epi16
(
xmm1
);
xmm2
=
_mm_subs_epi16
(
temp_channel
[
1
],
xmm2
);
#elif defined(__arm__)
xmm1
=
vabsq_s16
(
rxF
[
i
]);
xmm1
=
vsubq_s16
(
ch_mag
[
i
],
xmm1
);
xmm2
=
vabsq_s16
(
xmm1
);
xmm2
=
vsubq_s16
(
ch_magb
[
i
],
xmm2
);
#endif
// ---------------------------------------s
// 1st RE
// ---------------------------------------
ulsch_llr
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
0
];
ulsch_llr
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
1
];
#if defined(__x86_64__) || defined(__i386__)
ulsch_llr
[
2
]
=
_mm_extract_epi16
(
xmm1
,
0
);
ulsch_llr
[
3
]
=
_mm_extract_epi16
(
xmm1
,
1
);
ulsch_llr
[
4
]
=
_mm_extract_epi16
(
xmm2
,
0
);
ulsch_llr
[
5
]
=
_mm_extract_epi16
(
xmm2
,
1
);
#elif defined(__arm__)
ulsch_llr
[
2
]
=
vgetq_lane_s16
(
xmm1
,
0
);
ulsch_llr
[
3
]
=
vgetq_lane_s16
(
xmm1
,
1
);
ulsch_llr
[
4
]
=
vgetq_lane_s16
(
xmm2
,
0
);
ulsch_llr
[
5
]
=
vgetq_lane_s16
(
xmm2
,
1
);
#endif
// ---------------------------------------
ulsch_llr
+=
6
;
// ---------------------------------------
// 2nd RE
// ---------------------------------------
ulsch_llr
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
2
];
ulsch_llr
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
3
];
#if defined(__x86_64__) || defined(__i386__)
ulsch_llr
[
2
]
=
_mm_extract_epi16
(
xmm1
,
2
);
ulsch_llr
[
3
]
=
_mm_extract_epi16
(
xmm1
,
3
);
ulsch_llr
[
4
]
=
_mm_extract_epi16
(
xmm2
,
2
);
ulsch_llr
[
5
]
=
_mm_extract_epi16
(
xmm2
,
3
);
#elif defined(__arm__)
ulsch_llr
[
2
]
=
vgetq_lane_s16
(
xmm1
,
2
);
ulsch_llr
[
3
]
=
vgetq_lane_s16
(
xmm1
,
3
);
ulsch_llr
[
4
]
=
vgetq_lane_s16
(
xmm2
,
2
);
ulsch_llr
[
5
]
=
vgetq_lane_s16
(
xmm2
,
3
);
#endif
// ---------------------------------------
ulsch_llr
+=
6
;
// ---------------------------------------
// 3rd RE
// ---------------------------------------
ulsch_llr
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
4
];
ulsch_llr
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
5
];
#if defined(__x86_64__) || defined(__i386__)
ulsch_llr
[
2
]
=
_mm_extract_epi16
(
xmm1
,
4
);
ulsch_llr
[
3
]
=
_mm_extract_epi16
(
xmm1
,
5
);
ulsch_llr
[
4
]
=
_mm_extract_epi16
(
xmm2
,
4
);
ulsch_llr
[
5
]
=
_mm_extract_epi16
(
xmm2
,
5
);
#elif defined(__arm__)
ulsch_llr
[
2
]
=
vgetq_lane_s16
(
xmm1
,
4
);
ulsch_llr
[
3
]
=
vgetq_lane_s16
(
xmm1
,
5
);
ulsch_llr
[
4
]
=
vgetq_lane_s16
(
xmm2
,
4
);
ulsch_llr
[
5
]
=
vgetq_lane_s16
(
xmm2
,
5
);
#endif
// ---------------------------------------
ulsch_llr
+=
6
;
// ---------------------------------------
// 4th RE
// ---------------------------------------
ulsch_llr
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
6
];
ulsch_llr
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
7
];
#if defined(__x86_64__) || defined(__i386__)
ulsch_llr
[
2
]
=
_mm_extract_epi16
(
xmm1
,
6
);
ulsch_llr
[
3
]
=
_mm_extract_epi16
(
xmm1
,
7
);
ulsch_llr
[
4
]
=
_mm_extract_epi16
(
xmm2
,
6
);
ulsch_llr
[
5
]
=
_mm_extract_epi16
(
xmm2
,
7
);
#elif defined(__arm__)
ulsch_llr
[
2
]
=
vgetq_lane_s16
(
xmm1
,
6
);
ulsch_llr
[
3
]
=
vgetq_lane_s16
(
xmm1
,
7
);
ulsch_llr
[
4
]
=
vgetq_lane_s16
(
xmm2
,
6
);
ulsch_llr
[
5
]
=
vgetq_lane_s16
(
xmm2
,
7
);
#endif
// ---------------------------------------
ulsch_llr
+=
6
;
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
nr_ulsch_compute_llr
(
int32_t
*
rxdataF_comp
,
int32_t
**
ul_ch_mag
,
int32_t
**
ul_ch_magb
,
int16_t
*
ulsch_llr
,
uint32_t
nb_re
,
uint8_t
symbol
,
uint8_t
mod_order
)
{
switch
(
mod_order
){
case
2
:
nr_ulsch_qpsk_llr
(
rxdataF_comp
,
ulsch_llr
,
nb_re
,
symbol
);
break
;
case
4
:
nr_ulsch_16qam_llr
(
rxdataF_comp
,
ul_ch_mag
,
ulsch_llr
,
nb_re
,
symbol
);
break
;
case
6
:
nr_ulsch_64qam_llr
(
rxdataF_comp
,
ul_ch_mag
,
ul_ch_magb
,
ulsch_llr
,
nb_re
,
symbol
);
break
;
default:
LOG_E
(
PHY
,
"nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d
\n
"
,
symbol
,
mod_order
);
break
;
}
}
\ No newline at end of file
openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
View file @
66442aa4
...
...
@@ -204,7 +204,7 @@ typedef struct {
/// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
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_mod
[
MAX_NUM_NR_RE
];
int32_t
d_mod
[
MAX_NUM_NR_RE
]
__attribute__
((
aligned
(
16
)))
;
/// Transform-coded "z"-sequences (for definition see 36-211 V8.6 2009-03, p.14-15)
int32_t
z
[
MAX_NUM_NR_RE
];
/*
...
...
openair1/PHY/defs_gNB.h
View file @
66442aa4
...
...
@@ -354,6 +354,43 @@ typedef struct {
}
NR_gNB_COMMON
;
typedef
struct
{
/// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..2*ofdm_symbol_size[
int32_t
**
rxdataF_ext
;
/// \brief Holds the received data in the frequency domain for the allocated RBs in normal format.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t
**
rxdataF_ext2
;
/// \brief Hold the channel estimates in time domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..4*ofdm_symbol_size[
int32_t
**
drs_ch_estimates_time
;
/// \brief Hold the channel estimates in frequency domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t
**
drs_ch_estimates
;
/// \brief Holds the compensated signal.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t
**
rxdataF_comp
;
/// \brief Magnitude of the UL channel estimates. Used for 2nd-bit level thresholds in LLR computation
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t
**
ul_ch_mag
;
/// \brief Magnitude of the UL channel estimates scaled for 3rd bit level thresholds in LLR computation
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t
**
ul_ch_magb
;
/// measured RX power based on DRS
int
ulsch_power
[
2
];
/// \brief llr values.
/// - first index: ? [0..1179743] (hard coded)
int16_t
*
llr
;
}
NR_gNB_PUSCH
;
/// Context data structure for RX/TX portion of slot processing
typedef
struct
{
/// Component Carrier index
...
...
@@ -569,13 +606,13 @@ typedef struct PHY_VARS_gNB_s {
Sched_Rsp_t
Sched_INFO
;
NR_gNB_PDCCH
pdcch_vars
;
NR_gNB_PBCH
pbch
;
LTE_eNB_PHICH
phich_vars
[
2
];
//
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_PUSCH
*
pusch_vars
[
NUMBER_OF_UE_MAX
];
NR_gNB_DLSCH_t
*
dlsch
[
NUMBER_OF_NR_DLSCH_MAX
][
2
];
// Nusers times two spatial streams
NR_gNB_ULSCH_t
*
ulsch
[
NUMBER_OF_NR_ULSCH_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
...
...
openair1/SIMULATION/NR_PHY/ulsim.c
View file @
66442aa4
...
...
@@ -48,16 +48,14 @@
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.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
;
...
...
@@ -487,6 +485,7 @@ int main(int argc, char **argv) {
uint8_t
bit_index
;
uint32_t
errors_scrambling
;
uint32_t
scrambling_index
;
uint8_t
symbol
;
int16_t
**
tx_layers
;
int32_t
*
mod_symbols
[
MAX_NUM_NR_RE
];
uint16_t
n_dmrs
;
...
...
@@ -573,7 +572,7 @@ int main(int argc, char **argv) {
nr_modulation
(
scrambled_output
[
cwd
],
// assume one codeword for the moment
available_bits
,
mod_order
,
ulsch_ue
[
cwd
]
->
d_mod
);
(
int16_t
*
)
ulsch_ue
[
cwd
]
->
d_mod
);
///////////
////////////////////////////////////////////////////////////////////////
...
...
@@ -718,12 +717,12 @@ m, l, k, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1],
n_errors
=
0
;
n_false_positive
=
0
;
SNR_lin
=
pow
(
10
,
SNR
/
10
.
0
);
sigma
=
1
.
0
/
sqrt
(
2
*
SNR_lin
);
SNR_lin
=
pow
(
10
,
SNR
/
10
.
0
);
sigma
=
1
.
0
/
sqrt
(
2
*
SNR_lin
);
//AWGN
sigma2_dB
=
10
*
log10
((
double
)
txlev
)
-
SNR
;
sigma2
=
pow
(
10
,
sigma2_dB
/
10
);
//AWGN
sigma2_dB
=
10
*
log10
((
double
)
txlev
)
-
SNR
;
sigma2
=
pow
(
10
,
sigma2_dB
/
10
);
for
(
trial
=
0
;
trial
<
n_trials
;
trial
++
)
{
...
...
@@ -795,37 +794,70 @@ m, l, k, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1],
#endif
//
//////////////////////////////////////////////////////////
//
////////////////// ULSCH unscrambling ////////////////////
//
//////////////////////////////////////////////////////////
//
----------------------------------------------------------
//
-------------------- LLRs computation --------------------
//
----------------------------------------------------------
nr_ulsch_unscrambling
(
channel_output_fixed
,
available_bits
,
0
,
Nid_cell
,
n_rnti
);
int
sch_sym_start
=
NR_SYMBOLS_PER_SLOT
-
nb_symb_sch
;
uint32_t
nb_re
;
uint32_t
d_mod_offset
=
0
;
uint32_t
llr_offset
=
0
;
for
(
symbol
=
sch_sym_start
;
symbol
<
14
;
symbol
++
)
{
if
(
symbol
==
2
)
// [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1)
nb_re
=
nb_rb
*
6
;
else
nb_re
=
nb_rb
*
12
;
nr_ulsch_compute_llr
(
&
ulsch_ue
[
0
]
->
d_mod
[
d_mod_offset
],
gNB
->
pusch_vars
[
UE_id
]
->
ul_ch_mag
,
gNB
->
pusch_vars
[
UE_id
]
->
ul_ch_magb
,
&
gNB
->
pusch_vars
[
UE_id
]
->
llr
[
llr_offset
],
nb_re
,
symbol
,
rel15_ul
->
Qm
);
d_mod_offset
=
d_mod_offset
+
nb_re
;
// [hna] d_mod is incremented by nb_re
llr_offset
=
llr_offset
+
(
nb_re
*
rel15_ul
->
Qm
);
// [hna] llr is incremented by (nb_re*mod_order) because each RE has (mod_order) coded bit (i.e LLRs)
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
//----------------------------------------------------------
//------------------- ULSCH unscrambling -------------------
//----------------------------------------------------------
nr_ulsch_unscrambling
(
gNB
->
pusch_vars
[
UE_id
]
->
llr
,
available_bits
,
0
,
Nid_cell
,
n_rnti
);
////////////////////////////////////////////////////////////
////////////////////// ULSCH decoding //////////////////////
////////////////////////////////////////////////////////////
//----------------------------------------------------------
//--------------------- ULSCH decoding ---------------------
//----------------------------------------------------------
ret
=
nr_ulsch_decoding
(
gNB
,
UE_id
,
channel_output_fixed
,
frame_parms
,
frame
,
ret
=
nr_ulsch_decoding
(
gNB
,
UE_id
,
gNB
->
pusch_vars
[
UE_id
]
->
llr
,
frame_parms
,
frame
,
nb_symb_sch
,
subframe
,
harq_pid
,
is_crnti
,
llr8_flag
);
if
(
ret
>
ulsch_gNB
->
max_ldpc_iterations
)
n_errors
++
;
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////
//
///////////////////// count errors ///////////////////////
//
//////////////////////////////////////////////////////////
//
----------------------------------------------------------
//
---------------------- count errors ----------------------
//
----------------------------------------------------------
for
(
i
=
0
;
i
<
TBS
;
i
++
)
{
if
(((
ulsch_ue
[
0
]
->
g
[
i
]
==
0
)
&&
(
channel_output_fixed
[
i
]
<
0
))
||
((
ulsch_ue
[
0
]
->
g
[
i
]
==
1
)
&&
(
channel_output_fixed
[
i
]
>=
0
)))
{
if
(((
ulsch_ue
[
0
]
->
g
[
i
]
==
0
)
&&
(
gNB
->
pusch_vars
[
UE_id
]
->
llr
[
i
]
<=
0
))
||
((
ulsch_ue
[
0
]
->
g
[
i
]
==
1
)
&&
(
gNB
->
pusch_vars
[
UE_id
]
->
llr
[
i
]
>=
0
)))
{
if
(
errors_scrambling
==
0
)
printf
(
"First bit in error = %d
\n
"
,
i
);
errors_scrambling
++
;
}
...
...
@@ -838,15 +870,19 @@ m, l, k, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1],
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
if
(
errors_scrambling
>
0
)
{
if
(
n_trials
==
1
)
printf
(
"errors_scrambling %d (trial %d)
\n
"
,
errors_scrambling
,
trial
);
}
if
(
errors_bit
>
0
)
{
n_false_positive
++
;
if
(
n_trials
==
1
)
printf
(
"errors_bit %d (trial %d)
\n
"
,
errors_bit
,
trial
);
}
}
}
// [hna] for (trial = 0; trial < n_trials; trial++)
printf
(
"*****************************************
\n
"
);
printf
(
"SNR %f, BLER %f (false positive %f)
\n
"
,
SNR
,
...
...
@@ -858,7 +894,8 @@ m, l, k, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1],
printf
(
"PUSCH test OK
\n
"
);
break
;
}
}
}
// [hna] for (SNR = snr0; SNR < snr1; SNR += snr_step)
for
(
i
=
0
;
i
<
2
;
i
++
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment