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
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
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
OpenXG
OpenXG-RAN
Commits
810e62e1
Commit
810e62e1
authored
Apr 06, 2022
by
Robert Schmidt
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/ldpc-decoder-memory' into integration_2022_wk14
parents
276c7be5
2c23b28b
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
306 additions
and
586 deletions
+306
-586
openair1/PHY/CODING/TESTBENCH/ldpctest.c
openair1/PHY/CODING/TESTBENCH/ldpctest.c
+99
-143
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h
+2
-11
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h
+4
-16
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
+47
-154
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h
+0
-83
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h
+8
-24
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/nrLDPC_debug.h
...ir1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/nrLDPC_debug.h
+7
-7
openair1/PHY/CODING/nrLDPC_defs.h
openair1/PHY/CODING/nrLDPC_defs.h
+1
-1
openair1/PHY/CODING/nrLDPC_extern.h
openair1/PHY/CODING/nrLDPC_extern.h
+0
-1
openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+4
-8
openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c
openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c
+2
-1
openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
+12
-10
openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+106
-114
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+8
-5
openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+0
-2
openair1/PHY/defs_gNB.h
openair1/PHY/defs_gNB.h
+0
-2
openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+6
-4
No files found.
openair1/PHY/CODING/TESTBENCH/ldpctest.c
View file @
810e62e1
This diff is collapsed.
Click to expand it.
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h
View file @
810e62e1
...
...
@@ -37,17 +37,12 @@
\param p_lut Pointer to decoder LUTs
\param Z Lifting size
*/
static
inline
void
nrLDPC_bnProcPc
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_bnProcPc
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
bnProcBuf
,
int8_t
*
bnProcBufRes
,
int8_t
*
llrProcBuf
,
int8_t
*
llrRes
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numBnInBnGroups
=
p_lut
->
numBnInBnGroups
;
const
uint32_t
*
lut_startAddrBnGroups
=
p_lut
->
startAddrBnGroups
;
const
uint16_t
*
lut_startAddrBnGroupsLlr
=
p_lut
->
startAddrBnGroupsLlr
;
int8_t
*
bnProcBuf
=
p_procBuf
->
bnProcBuf
;
int8_t
*
bnProcBufRes
=
p_procBuf
->
bnProcBufRes
;
int8_t
*
llrRes
=
p_procBuf
->
llrRes
;
int8_t
*
llrProcBuf
=
p_procBuf
->
llrProcBuf
;
__m128i
*
p_bnProcBuf
;
__m256i
*
p_bnProcBufRes
;
__m128i
*
p_llrProcBuf
;
...
...
@@ -1681,7 +1676,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc
\param p_lut Pointer to decoder LUTs
\param Z Lifting size
*/
static
inline
void
nrLDPC_bnProc
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_bnProc
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
bnProcBuf
,
int8_t
*
bnProcBufRes
,
int8_t
*
llrRes
,
uint16_t
Z
)
{
// BN Processing calculating the values to send back to the CNs for next iteration
// bnProcBufRes contains the sum of all edges to each BN at the start of each group
...
...
@@ -1690,10 +1685,6 @@ static inline void nrLDPC_bnProc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_procBu
const
uint32_t
*
lut_startAddrBnGroups
=
p_lut
->
startAddrBnGroups
;
const
uint16_t
*
lut_startAddrBnGroupsLlr
=
p_lut
->
startAddrBnGroupsLlr
;
int8_t
*
bnProcBuf
=
p_procBuf
->
bnProcBuf
;
int8_t
*
bnProcBufRes
=
p_procBuf
->
bnProcBufRes
;
int8_t
*
llrRes
=
p_procBuf
->
llrRes
;
__m256i
*
p_bnProcBuf
;
__m256i
*
p_bnProcBufRes
;
__m256i
*
p_llrRes
;
...
...
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h
View file @
810e62e1
...
...
@@ -37,14 +37,11 @@
\param p_procBuf Pointer to processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_cnProc_BG2
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_cnProc_BG2
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
cnProcBuf
,
int8_t
*
cnProcBufRes
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
int8_t
*
cnProcBufRes
=
p_procBuf
->
cnProcBufRes
;
__m256i
*
p_cnProcBuf
;
__m256i
*
p_cnProcBufRes
;
...
...
@@ -372,14 +369,11 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr
\param p_lut Pointer to decoder LUTs
\param Z Lifting size
*/
static
inline
void
nrLDPC_cnProc_BG1
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_cnProc_BG1
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
cnProcBuf
,
int8_t
*
cnProcBufRes
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
int8_t
*
cnProcBufRes
=
p_procBuf
->
cnProcBufRes
;
__m256i
*
p_cnProcBuf
;
__m256i
*
p_cnProcBufRes
;
...
...
@@ -871,14 +865,11 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr
\param Z Lifting size
\return 32-bit parity check indicator
*/
static
inline
uint32_t
nrLDPC_cnProcPc_BG1
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
)
static
inline
uint32_t
nrLDPC_cnProcPc_BG1
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
cnProcBuf
,
int8_t
*
cnProcBufRes
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
int8_t
*
cnProcBufRes
=
p_procBuf
->
cnProcBufRes
;
__m256i
*
p_cnProcBuf
;
__m256i
*
p_cnProcBufRes
;
...
...
@@ -1506,14 +1497,11 @@ static inline uint32_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
\param Z Lifting size
\return 32-bit parity check indicator
*/
static
inline
uint32_t
nrLDPC_cnProcPc_BG2
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
)
static
inline
uint32_t
nrLDPC_cnProcPc_BG2
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
cnProcBuf
,
int8_t
*
cnProcBufRes
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
int8_t
*
cnProcBufRes
=
p_procBuf
->
cnProcBufRes
;
__m256i
*
p_cnProcBuf
;
__m256i
*
p_cnProcBufRes
;
...
...
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
View file @
810e62e1
This diff is collapsed.
Click to expand it.
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h
deleted
100644 → 0
View file @
276c7be5
/*
* 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 nrLDPC_init_mem.h
* \brief Defines the function to initialize the LDPC decoder and sets correct LUTs.
* \author Sebastian Wagner (TCL Communications) Email: <mailto:sebastian.wagner@tcl.com>
* \date 07-12-2018
* \version 1.0
* \note
* \warning
*/
#ifndef __NR_LDPC_INIT_MEM__H__
#define __NR_LDPC_INIT_MEM__H__
#include <stdlib.h>
#include "nrLDPC_types.h"
/**
\brief Allocates 32 byte aligned memory and initializes to zero
\param size Input size in bytes
\return Pointer to memory
*/
static
inline
void
*
malloc32_clear
(
size_t
size
)
{
void
*
ptr
=
(
void
*
)
memalign
(
32
,
size
+
32
);
memset
(
ptr
,
0
,
size
);
return
ptr
;
}
/**
\brief Allocates and initializes the internal decoder processing buffers
\param p_decParams Pointer to decoder parameters
\param p_lut Pointer to decoder LUTs
\return Number of LLR values
*/
static
inline
t_nrLDPC_procBuf
*
nrLDPC_init_mem
(
void
)
{
t_nrLDPC_procBuf
*
p_procBuf
=
(
t_nrLDPC_procBuf
*
)
malloc32_clear
(
sizeof
(
t_nrLDPC_procBuf
));
if
(
p_procBuf
)
{
p_procBuf
->
cnProcBuf
=
(
int8_t
*
)
malloc32_clear
(
NR_LDPC_SIZE_CN_PROC_BUF
*
sizeof
(
int8_t
));
p_procBuf
->
cnProcBufRes
=
(
int8_t
*
)
malloc32_clear
(
NR_LDPC_SIZE_CN_PROC_BUF
*
sizeof
(
int8_t
));
p_procBuf
->
bnProcBuf
=
(
int8_t
*
)
malloc32_clear
(
NR_LDPC_SIZE_BN_PROC_BUF
*
sizeof
(
int8_t
));
p_procBuf
->
bnProcBufRes
=
(
int8_t
*
)
malloc32_clear
(
NR_LDPC_SIZE_BN_PROC_BUF
*
sizeof
(
int8_t
));
p_procBuf
->
llrRes
=
(
int8_t
*
)
malloc32_clear
(
NR_LDPC_MAX_NUM_LLR
*
sizeof
(
int8_t
));
p_procBuf
->
llrProcBuf
=
(
int8_t
*
)
malloc32_clear
(
NR_LDPC_MAX_NUM_LLR
*
sizeof
(
int8_t
));
}
return
(
p_procBuf
);
}
static
inline
void
nrLDPC_free_mem
(
t_nrLDPC_procBuf
*
p_procBuf
)
{
free
(
p_procBuf
->
cnProcBuf
);
free
(
p_procBuf
->
cnProcBufRes
);
free
(
p_procBuf
->
bnProcBuf
);
free
(
p_procBuf
->
bnProcBufRes
);
free
(
p_procBuf
->
llrRes
);
free
(
p_procBuf
->
llrProcBuf
);
free
(
p_procBuf
);
}
#endif
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h
View file @
810e62e1
...
...
@@ -97,7 +97,7 @@ static inline void *nrLDPC_circ_memcpy(int8_t *str1, const int8_t *str2, uint16_
\param Z Lifting size
\param BG Base graph
*/
static
inline
void
nrLDPC_llr2llrProcBuf
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llr
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
,
uint8_t
BG
)
static
inline
void
nrLDPC_llr2llrProcBuf
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llr
,
int8_t
*
llrP
rocBuf
,
uint16_t
Z
,
uint8_t
BG
)
{
uint32_t
i
;
const
uint8_t
numBn2CnG1
=
p_lut
->
numBnInBnGroups
[
0
];
...
...
@@ -109,7 +109,6 @@ static inline void nrLDPC_llr2llrProcBuf(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrL
const
uint8_t
*
lut_llr2llrProcBufBnPos
=
p_lut
->
llr2llrProcBufBnPos
;
uint32_t
idxBn
;
int8_t
*
llrProcBuf
=
p_procBuf
->
llrProcBuf
;
// Copy LLRs connected to 1 CN
if
(
numBn2CnG1
>
0
)
...
...
@@ -133,7 +132,7 @@ static inline void nrLDPC_llr2llrProcBuf(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrL
\param p_procBuf Pointer to the processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_llr2CnProcBuf_BG1
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llr
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_llr2CnProcBuf_BG1
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llr
,
int8_t
*
cnP
rocBuf
,
uint16_t
Z
)
{
const
uint16_t
(
*
lut_circShift_CNG3
)
[
lut_numCnInCnGroups_BG1_R13
[
0
]]
=
(
const
uint16_t
(
*
)[
lut_numCnInCnGroups_BG1_R13
[
0
]])
p_lut
->
circShift
[
0
];
const
uint16_t
(
*
lut_circShift_CNG4
)
[
lut_numCnInCnGroups_BG1_R13
[
1
]]
=
(
const
uint16_t
(
*
)[
lut_numCnInCnGroups_BG1_R13
[
1
]])
p_lut
->
circShift
[
1
];
...
...
@@ -158,7 +157,6 @@ static inline void nrLDPC_llr2CnProcBuf_BG1(t_nrLDPC_lut* p_lut, int8_t* llr, t_
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
uint32_t
i
;
uint32_t
j
;
...
...
@@ -342,7 +340,7 @@ static inline void nrLDPC_llr2CnProcBuf_BG1(t_nrLDPC_lut* p_lut, int8_t* llr, t_
\param p_procBuf Pointer to the processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_llr2CnProcBuf_BG2
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llr
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_llr2CnProcBuf_BG2
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llr
,
int8_t
*
cnP
rocBuf
,
uint16_t
Z
)
{
const
uint16_t
(
*
lut_circShift_CNG3
)
[
lut_numCnInCnGroups_BG2_R15
[
0
]]
=
(
const
uint16_t
(
*
)[
lut_numCnInCnGroups_BG2_R15
[
0
]])
p_lut
->
circShift
[
0
];
const
uint16_t
(
*
lut_circShift_CNG4
)
[
lut_numCnInCnGroups_BG2_R15
[
1
]]
=
(
const
uint16_t
(
*
)[
lut_numCnInCnGroups_BG2_R15
[
1
]])
p_lut
->
circShift
[
1
];
...
...
@@ -361,7 +359,6 @@ static inline void nrLDPC_llr2CnProcBuf_BG2(t_nrLDPC_lut* p_lut, int8_t* llr, t_
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
uint32_t
i
;
uint32_t
j
;
...
...
@@ -478,7 +475,7 @@ static inline void nrLDPC_llr2CnProcBuf_BG2(t_nrLDPC_lut* p_lut, int8_t* llr, t_
\param p_procBuf Pointer to the processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_cn2bnProcBuf_BG2
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_cn2bnProcBuf_BG2
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
cnProcBufRes
,
int8_t
*
bnP
rocBuf
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
...
...
@@ -504,9 +501,6 @@ static inline void nrLDPC_cn2bnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG8
)
[
lut_numCnInCnGroups
[
4
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
4
]])
p_lut
->
bnPosBnProcBuf
[
4
];
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG10
)
[
lut_numCnInCnGroups
[
5
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
5
]])
p_lut
->
bnPosBnProcBuf
[
5
];
int8_t
*
cnProcBufRes
=
p_procBuf
->
cnProcBufRes
;
int8_t
*
bnProcBuf
=
p_procBuf
->
bnProcBuf
;
int8_t
*
p_cnProcBufRes
;
uint32_t
bitOffsetInGroup
;
uint32_t
i
;
...
...
@@ -621,7 +615,7 @@ static inline void nrLDPC_cn2bnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
\param p_procBuf Pointer to the processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_cn2bnProcBuf_BG1
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_cn2bnProcBuf_BG1
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
cnProcBufRes
,
int8_t
*
bnP
rocBuf
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
...
...
@@ -655,9 +649,6 @@ static inline void nrLDPC_cn2bnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG10
)[
lut_numCnInCnGroups
[
7
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
7
]])
p_lut
->
bnPosBnProcBuf
[
7
];
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG19
)[
lut_numCnInCnGroups
[
8
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
8
]])
p_lut
->
bnPosBnProcBuf
[
8
];
int8_t
*
cnProcBufRes
=
p_procBuf
->
cnProcBufRes
;
int8_t
*
bnProcBuf
=
p_procBuf
->
bnProcBuf
;
int8_t
*
p_cnProcBufRes
;
uint32_t
bitOffsetInGroup
;
uint32_t
i
;
...
...
@@ -819,7 +810,7 @@ static inline void nrLDPC_cn2bnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
\param p_procBuf Pointer to the processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_bn2cnProcBuf_BG2
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_bn2cnProcBuf_BG2
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
bnProcBufRes
,
int8_t
*
cnP
rocBuf
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
...
...
@@ -845,9 +836,6 @@ static inline void nrLDPC_bn2cnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG8
)
[
lut_numCnInCnGroups
[
4
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
4
]])
p_lut
->
bnPosBnProcBuf
[
4
];
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG10
)
[
lut_numCnInCnGroups
[
5
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
5
]])
p_lut
->
bnPosBnProcBuf
[
5
];
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
int8_t
*
bnProcBufRes
=
p_procBuf
->
bnProcBufRes
;
int8_t
*
p_cnProcBuf
;
uint32_t
bitOffsetInGroup
;
uint32_t
i
;
...
...
@@ -961,7 +949,7 @@ static inline void nrLDPC_bn2cnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
\param p_procBuf Pointer to the processing buffers
\param Z Lifting size
*/
static
inline
void
nrLDPC_bn2cnProcBuf_BG1
(
t_nrLDPC_lut
*
p_lut
,
t_nrLDPC_procBuf
*
p_p
rocBuf
,
uint16_t
Z
)
static
inline
void
nrLDPC_bn2cnProcBuf_BG1
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
bnProcBufRes
,
int8_t
*
cnP
rocBuf
,
uint16_t
Z
)
{
const
uint8_t
*
lut_numCnInCnGroups
=
p_lut
->
numCnInCnGroups
;
const
uint32_t
*
lut_startAddrCnGroups
=
p_lut
->
startAddrCnGroups
;
...
...
@@ -995,9 +983,6 @@ static inline void nrLDPC_bn2cnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG10
)[
lut_numCnInCnGroups
[
7
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
7
]])
p_lut
->
bnPosBnProcBuf
[
7
];
const
uint8_t
(
*
lut_bnPosBnProcBuf_CNG19
)[
lut_numCnInCnGroups
[
8
]]
=
(
const
uint8_t
(
*
)[
lut_numCnInCnGroups
[
8
]])
p_lut
->
bnPosBnProcBuf
[
8
];
int8_t
*
cnProcBuf
=
p_procBuf
->
cnProcBuf
;
int8_t
*
bnProcBufRes
=
p_procBuf
->
bnProcBufRes
;
int8_t
*
p_cnProcBuf
;
uint32_t
bitOffsetInGroup
;
uint32_t
i
;
...
...
@@ -1157,7 +1142,7 @@ static inline void nrLDPC_bn2cnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf
\param Z Lifting size
\param BG Base graph
*/
static
inline
void
nrLDPC_llrRes2llrOut
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llrOut
,
t_nrLDPC_procBuf
*
p_procBuf
,
uint16_t
Z
,
uint8_t
BG
)
static
inline
void
nrLDPC_llrRes2llrOut
(
t_nrLDPC_lut
*
p_lut
,
int8_t
*
llrOut
,
int8_t
*
llrRes
,
uint16_t
Z
,
uint8_t
BG
)
{
uint32_t
i
;
const
uint8_t
numBn2CnG1
=
p_lut
->
numBnInBnGroups
[
0
];
...
...
@@ -1168,7 +1153,6 @@ static inline void nrLDPC_llrRes2llrOut(t_nrLDPC_lut* p_lut, int8_t* llrOut, t_n
const
uint16_t
*
lut_llr2llrProcBufAddr
=
p_lut
->
llr2llrProcBufAddr
;
const
uint8_t
*
lut_llr2llrProcBufBnPos
=
p_lut
->
llr2llrProcBufBnPos
;
int8_t
*
llrRes
=
p_procBuf
->
llrRes
;
int8_t
*
p_llrOut
=
&
llrOut
[
0
];
uint32_t
idxBn
;
...
...
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/nrLDPC_debug.h
View file @
810e62e1
...
...
@@ -87,38 +87,38 @@ static inline void nrLDPC_initFile(const char* fileName)
\brief Writes data of predefined buffers to file
\param buffer Enum of buffer name to write
*/
static
inline
void
nrLDPC_debug_writeBuffer2File
(
e_nrLDPC_buffers
buffer
,
t_nrLDPC_procBuf
*
p_procBuf
)
static
inline
void
nrLDPC_debug_writeBuffer2File
(
e_nrLDPC_buffers
buffer
,
int8_t
*
p_buffer
)
{
switch
(
buffer
)
{
case
nrLDPC_buffers_LLR_PROC
:
{
nrLDPC_writeFile
(
"llrProcBuf.txt"
,
p_
procBuf
->
llrProcBuf
,
NR_LDPC_MAX_NUM_LLR
);
nrLDPC_writeFile
(
"llrProcBuf.txt"
,
p_
buffer
,
NR_LDPC_MAX_NUM_LLR
);
break
;
}
case
nrLDPC_buffers_CN_PROC
:
{
nrLDPC_writeFile
(
"cnProcBuf.txt"
,
p_
procBuf
->
cnProcBuf
,
NR_LDPC_SIZE_CN_PROC_BUF
);
nrLDPC_writeFile
(
"cnProcBuf.txt"
,
p_
buffer
,
NR_LDPC_SIZE_CN_PROC_BUF
);
break
;
}
case
nrLDPC_buffers_CN_PROC_RES
:
{
nrLDPC_writeFile
(
"cnProcBufRes.txt"
,
p_
procBuf
->
cnProcBufRes
,
NR_LDPC_SIZE_CN_PROC_BUF
);
nrLDPC_writeFile
(
"cnProcBufRes.txt"
,
p_
buffer
,
NR_LDPC_SIZE_CN_PROC_BUF
);
break
;
}
case
nrLDPC_buffers_BN_PROC
:
{
nrLDPC_writeFile
(
"bnProcBuf.txt"
,
p_
procBuf
->
bnProcBuf
,
NR_LDPC_SIZE_BN_PROC_BUF
);
nrLDPC_writeFile
(
"bnProcBuf.txt"
,
p_
buffer
,
NR_LDPC_SIZE_BN_PROC_BUF
);
break
;
}
case
nrLDPC_buffers_BN_PROC_RES
:
{
nrLDPC_writeFile
(
"bnProcBufRes.txt"
,
p_
procBuf
->
bnProcBufRes
,
NR_LDPC_SIZE_BN_PROC_BUF
);
nrLDPC_writeFile
(
"bnProcBufRes.txt"
,
p_
buffer
,
NR_LDPC_SIZE_BN_PROC_BUF
);
break
;
}
case
nrLDPC_buffers_LLR_RES
:
{
nrLDPC_writeFile
(
"llrRes.txt"
,
p_
procBuf
->
llrRes
,
NR_LDPC_MAX_NUM_LLR
);
nrLDPC_writeFile
(
"llrRes.txt"
,
p_
buffer
,
NR_LDPC_MAX_NUM_LLR
);
break
;
}
}
...
...
openair1/PHY/CODING/nrLDPC_defs.h
View file @
810e62e1
...
...
@@ -71,5 +71,5 @@ typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,sho
\param p_llrOut Output vector
\param p_profiler LDPC profiler statistics
*/
typedef
int32_t
(
*
nrLDPC_decoderfunc_t
)(
t_nrLDPC_dec_params
*
,
int8_t
*
,
int8_t
*
,
t_nrLDPC_procBuf
*
,
t_nrLDPC_time_stats
*
);
typedef
int32_t
(
*
nrLDPC_decoderfunc_t
)(
t_nrLDPC_dec_params
*
,
int8_t
*
,
int8_t
*
,
t_nrLDPC_time_stats
*
);
#endif
openair1/PHY/CODING/nrLDPC_extern.h
View file @
810e62e1
...
...
@@ -34,5 +34,4 @@ extern nrLDPC_initcallfunc_t nrLDPC_initcall;
extern
nrLDPC_decoderfunc_t
nrLDPC_decoder
;
extern
nrLDPC_encoderfunc_t
nrLDPC_encoder
;
// inline functions:
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h"
#endif
openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
View file @
810e62e1
...
...
@@ -76,8 +76,6 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr, uint16_t N_RB_UL)
free_and_zero
(
ulsch
->
harq_processes
[
i
]
->
c
[
r
]);
free_and_zero
(
ulsch
->
harq_processes
[
i
]
->
d
[
r
]);
free_and_zero
(
ulsch
->
harq_processes
[
i
]
->
w
[
r
]);
nrLDPC_free_mem
(
ulsch
->
harq_processes
[
i
]
->
p_nrLDPC_procBuf
[
r
]);
ulsch
->
harq_processes
[
i
]
->
p_nrLDPC_procBuf
[
r
]
=
NULL
;
}
free_and_zero
(
ulsch
->
harq_processes
[
i
]);
ulsch
->
harq_processes
[
i
]
=
NULL
;
...
...
@@ -101,22 +99,21 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
uint32_t
ulsch_bytes
=
a_segments
*
1056
;
// allocated bytes per segment
ulsch
=
(
NR_gNB_ULSCH_t
*
)
malloc16_clear
(
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_clear
(
sizeof
(
NR_UL_gNB_HARQ_t
));
ulsch
->
harq_processes
[
i
]
->
b
=
(
uint8_t
*
)
malloc16_clear
(
ulsch_bytes
);
for
(
r
=
0
;
r
<
a_segments
;
r
++
)
{
ulsch
->
harq_processes
[
i
]
->
p_nrLDPC_procBuf
[
r
]
=
nrLDPC_init_mem
();
ulsch
->
harq_processes
[
i
]
->
c
[
r
]
=
(
uint8_t
*
)
malloc16_clear
(
8448
*
sizeof
(
uint8_t
));
ulsch
->
harq_processes
[
i
]
->
d
[
r
]
=
(
int16_t
*
)
malloc16_clear
((
68
*
384
)
*
sizeof
(
int16_t
));
ulsch
->
harq_processes
[
i
]
->
w
[
r
]
=
(
int16_t
*
)
malloc16_clear
((
3
*
(
6144
+
64
))
*
sizeof
(
int16_t
));
}
}
return
(
ulsch
);
}
...
...
@@ -360,7 +357,6 @@ void nr_processULSegment(void* arg) {
no_iteration_ldpc
=
nrLDPC_decoder
(
p_decoderParms
,
(
int8_t
*
)
&
pl
[
0
],
llrProcBuf
,
ulsch_harq
->
p_nrLDPC_procBuf
[
r
],
p_procTime
);
if
(
check_crc
((
uint8_t
*
)
llrProcBuf
,
length_dec
,
ulsch_harq
->
F
,
crc_type
))
{
...
...
openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c
View file @
810e62e1
...
...
@@ -36,7 +36,8 @@
void
nr_adjust_synch_ue
(
NR_DL_FRAME_PARMS
*
frame_parms
,
PHY_VARS_NR_UE
*
ue
,
module_id_t
gNB_id
,
const
int
estimateSz
,
struct
complex16
dl_ch_estimates_time
[][
estimateSz
],
const
int
estimateSz
,
struct
complex16
dl_ch_estimates_time
[][
estimateSz
],
uint8_t
frame
,
uint8_t
subframe
,
unsigned
char
clear
,
...
...
openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
View file @
810e62e1
...
...
@@ -197,9 +197,9 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
int
nr_pbch_channel_estimation
(
PHY_VARS_NR_UE
*
ue
,
int
estimateSz
,
struct
complex16
dl_ch_estimates
[][
estimateSz
],
struct
complex16
dl_ch_estimates_time
[][
estimateSz
],
int
estimateSz
,
struct
complex16
dl_ch_estimates
[][
estimateSz
],
struct
complex16
dl_ch_estimates_time
[][
ue
->
frame_parms
.
ofdm_symbol_size
],
UE_nr_rxtx_proc_t
*
proc
,
uint8_t
gNB_id
,
unsigned
char
Ns
,
...
...
@@ -320,7 +320,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
rxF
=
(
int16_t
*
)
&
rxdataF
[
aarx
][(
symbol_offset
+
k
+
re_offset
)];
dl_ch
=
(
int16_t
*
)
&
dl_ch_estimates
[
aarx
][
ch_offset
];
memset
(
dl_ch
,
0
,
sizeof
(
*
dl_ch
)
*
(
ue
->
frame_parms
.
ofdm_symbol_size
));
memset
(
dl_ch
,
0
,
sizeof
(
struct
complex16
)
*
(
ue
->
frame_parms
.
ofdm_symbol_size
));
#ifdef DEBUG_CH
printf
(
"pbch ch est pilot addr %p RB_DL %d
\n
"
,
&
pilot
[
0
],
ue
->
frame_parms
.
N_RB_DL
);
...
...
@@ -387,10 +387,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
if
(
dmrss
==
1
&&
pilot_cnt
==
12
)
{
pilot_cnt
=
48
;
re_offset
=
(
re_offset
+
144
)
%
ue
->
frame_parms
.
ofdm_symbol_size
;
rxF
=
(
int16_t
*
)
&
rxdataF
[
aarx
][(
symbol_offset
+
k
+
re_offset
)];
dl_ch
+=
288
;
pilot_cnt
=
48
;
re_offset
=
(
re_offset
+
144
)
%
ue
->
frame_parms
.
ofdm_symbol_size
;
rxF
=
(
int16_t
*
)
&
rxdataF
[
aarx
][(
symbol_offset
+
k
+
re_offset
)];
dl_ch
+=
288
;
}
ch
[
0
]
=
(
int16_t
)(((
int32_t
)
pil
[
0
]
*
rxF
[
0
]
-
(
int32_t
)
pil
[
1
]
*
rxF
[
1
])
>>
15
);
ch
[
1
]
=
(
int16_t
)(((
int32_t
)
pil
[
0
]
*
rxF
[
1
]
+
(
int32_t
)
pil
[
1
]
*
rxF
[
0
])
>>
15
);
...
...
@@ -452,10 +452,12 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
(
int16_t
*
)
&
dl_ch_estimates
[
aarx
][
ch_offset
],
(
int16_t
*
)
dl_ch_estimates_time
[
aarx
],
1
);
}
}
}
}
if
(
dmrss
==
2
)
UEscopeCopy
(
ue
,
pbchDlChEstimateTime
,
(
void
*
)
dl_ch_estimates_time
,
sizeof
(
struct
complex16
),
ue
->
frame_parms
.
nb_antennas_rx
,
idftsizeidx
);
return
(
0
);
}
...
...
openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
View file @
810e62e1
This diff is collapsed.
Click to expand it.
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
View file @
810e62e1
...
...
@@ -146,23 +146,26 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
start_meas
(
&
ue
->
dlsch_channel_estimation_stats
);
// computing channel estimation for selected best ssb
const
int
estimateSz
=
7
*
2
*
frame_parms
->
ofdm_symbol_size
;
const
int
estimateSz
=
frame_parms
->
symbols_per_slot
*
frame_parms
->
ofdm_symbol_size
;
__attribute__
((
aligned
(
32
)))
struct
complex16
dl_ch_estimates
[
frame_parms
->
nb_antennas_rx
][
estimateSz
];
__attribute__
((
aligned
(
32
)))
struct
complex16
dl_ch_estimates_time
[
frame_parms
->
nb_antennas_rx
][
estimateSz
];
__attribute__
((
aligned
(
32
)))
struct
complex16
dl_ch_estimates_time
[
frame_parms
->
nb_antennas_rx
][
frame_parms
->
ofdm_symbol_size
];
for
(
int
i
=
pbch_initial_symbol
;
i
<
pbch_initial_symbol
+
3
;
i
++
)
nr_pbch_channel_estimation
(
ue
,
estimateSz
,
dl_ch_estimates
,
dl_ch_estimates_time
,
proc
,
0
,
0
,
i
,
i
-
pbch_initial_symbol
,
temp_ptr
->
i_ssb
,
temp_ptr
->
n_hf
);
stop_meas
(
&
ue
->
dlsch_channel_estimation_stats
);
fapiPbch_t
result
;
ret
=
nr_rx_pbch
(
ue
,
proc
,
estimateSz
,
dl_ch_estimates
,
ue
->
pbch_vars
[
0
],
estimateSz
,
dl_ch_estimates
,
ue
->
pbch_vars
[
0
],
frame_parms
,
0
,
temp_ptr
->
i_ssb
,
SISO
,
&
result
);
&
result
);
temp_ptr
=
temp_ptr
->
next_ssb
;
}
...
...
openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
View file @
810e62e1
...
...
@@ -196,8 +196,6 @@ typedef struct {
uint8_t
rvidx
;
/// MIMO mode for this DLSCH
MIMO_nrmode_t
mimo_mode
;
/// LDPC processing buffers
t_nrLDPC_procBuf
**
p_nrLDPC_procBuf
;
/// Number of code segments
uint32_t
C
;
/// Number of bits in code segments
...
...
openair1/PHY/defs_gNB.h
View file @
810e62e1
...
...
@@ -280,8 +280,6 @@ typedef struct {
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)
...
...
openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
View file @
810e62e1
...
...
@@ -1405,9 +1405,11 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
if
(
slot_ssb
)
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH
,
VCD_FUNCTION_IN
);
LOG_D
(
PHY
,
" ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------
\n
"
,
frame_rx
%
1024
,
nr_slot_rx
);
const
int
estimateSz
=
7
*
2
*
sizeof
(
int
)
*
fp
->
ofdm_symbol_size
;
const
int
estimateSz
=
fp
->
symbols_per_slot
*
fp
->
ofdm_symbol_size
;
__attribute__
((
aligned
(
32
)))
struct
complex16
dl_ch_estimates
[
fp
->
nb_antennas_rx
][
estimateSz
];
__attribute__
((
aligned
(
32
)))
struct
complex16
dl_ch_estimates_time
[
fp
->
nb_antennas_rx
][
estimateSz
];
__attribute__
((
aligned
(
32
)))
struct
complex16
dl_ch_estimates_time
[
fp
->
nb_antennas_rx
][
fp
->
ofdm_symbol_size
];
for
(
int
i
=
1
;
i
<
4
;
i
++
)
{
nr_slot_fep
(
ue
,
...
...
@@ -1415,7 +1417,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
(
ue
->
symbol_offset
+
i
)
%
(
fp
->
symbols_per_slot
),
nr_slot_rx
);
start_meas
(
&
ue
->
dlsch_channel_estimation_stats
);
nr_pbch_channel_estimation
(
ue
,
estimateSz
,
dl_ch_estimates
,
dl_ch_estimates_time
,
proc
,
gNB_id
,
nr_slot_rx
,(
ue
->
symbol_offset
+
i
)
%
(
fp
->
symbols_per_slot
),
i
-
1
,(
fp
->
ssb_index
)
&
7
,
fp
->
half_frame_bit
);
stop_meas
(
&
ue
->
dlsch_channel_estimation_stats
);
...
...
@@ -1433,7 +1434,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
nr_adjust_synch_ue
(
fp
,
ue
,
gNB_id
,
estimateSz
,
dl_ch_estimates_time
,
fp
->
ofdm_symbol_size
,
dl_ch_estimates_time
,
frame_rx
,
nr_slot_rx
,
0
,
...
...
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