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
ao gleen
OpenXG-RAN
Commits
8756afdb
Commit
8756afdb
authored
Oct 09, 2024
by
Yi-Hung Chang
Committed by
Romain Beurdouche
Dec 16, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(nrLDPC_coding_interface): Add ldpc_xdma coding library
parent
73770da5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1450 additions
and
2 deletions
+1450
-2
CMakeLists.txt
CMakeLists.txt
+25
-1
cmake_targets/build_oai
cmake_targets/build_oai
+1
-1
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
...ING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
+455
-0
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.c
...PC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.c
+783
-0
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.h
...PC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.h
+67
-0
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/xdma_diag.h
...1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/xdma_diag.h
+119
-0
No files found.
CMakeLists.txt
View file @
8756afdb
...
...
@@ -508,6 +508,19 @@ endif()
##########################################################
# LDPC offload library - XDMA
##########################################################
add_boolean_option
(
ENABLE_LDPC_XDMA OFF
"Build support for LDPC Offload to XDMA library"
OFF
)
if
(
ENABLE_LDPC_XDMA
)
set
(
PHY_NRLDPC_CODING_XDMA_SRC
${
OPENAIR1_DIR
}
/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.c
${
OPENAIR1_DIR
}
/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
${
OPENAIR1_DIR
}
/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c
${
OPENAIR1_DIR
}
/PHY/CODING/nrLDPC_load.c
)
add_library
(
ldpc_xdma MODULE
${
PHY_NRLDPC_CODING_XDMA_SRC
}
)
endif
()
include_directories
(
"
${
OPENAIR_DIR
}
/radio/COMMON"
)
##############################################################
...
...
@@ -2065,6 +2078,10 @@ if (ENABLE_LDPC_T2)
add_dependencies
(
nr-softmodem ldpc_t2
)
endif
()
if
(
ENABLE_LDPC_XDMA
)
add_dependencies
(
nr-softmodem ldpc_xdma
)
endif
()
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries
(
nr-softmodem PRIVATE
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp
)
...
...
@@ -2126,6 +2143,10 @@ if (ENABLE_LDPC_T2)
add_dependencies
(
nr-uesoftmodem ldpc_t2
)
endif
()
if
(
ENABLE_LDPC_XDMA
)
add_dependencies
(
nr-uesoftmodem ldpc_xdma
)
endif
()
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries
(
nr-uesoftmodem PRIVATE
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp
)
...
...
@@ -2283,6 +2304,9 @@ add_executable(nr_ulsim
if
(
ENABLE_LDPC_T2
)
add_dependencies
(
nr_ulsim ldpc_t2
)
endif
()
if
(
ENABLE_LDPC_XDMA
)
add_dependencies
(
nr_ulsim ldpc_xdma
)
endif
()
add_dependencies
(
nr_ulsim ldpc_slot_segment
)
target_link_libraries
(
nr_ulsim PRIVATE
...
...
@@ -2350,7 +2374,7 @@ if (${T_TRACER})
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU OPENAIR0_LIB
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_cl ldpc_cuda ldpc ldpc_slot_segment ldpc_t2
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_cl ldpc_cuda ldpc ldpc_slot_segment ldpc_t2
ldpc_xdma
dfts config_internals nr_common
)
if
(
TARGET
${
i
}
)
add_dependencies
(
${
i
}
generate_T
)
...
...
cmake_targets/build_oai
View file @
8756afdb
...
...
@@ -46,7 +46,7 @@ BUILD_DOXYGEN=0
DISABLE_HARDWARE_DEPENDENCY
=
"False"
CMAKE_BUILD_TYPE
=
"RelWithDebInfo"
CMAKE_CMD
=
"
$CMAKE
"
OPTIONAL_LIBRARIES
=
"telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer imscope"
OPTIONAL_LIBRARIES
=
"telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2
ldpc_xdma
websrv oai_iqplayer imscope"
TARGET_LIST
=
""
BUILD_TOOL_OPT
=
"-j
$(
nproc
)
"
...
...
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
0 → 100644
View file @
8756afdb
/*
* 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/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c
* \brief Top-level routines for decoding LDPC (ULSCH) transport channels
* decoding implemented using a FEC IP core on FPGA through XDMA driver
*/
// [from gNB coding]
#include <syscall.h>
#include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/defs_gNB.h"
#include "SCHED_NR/fapi_nr_l1.h"
#include "SCHED_NR/sched_nr.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "defs.h"
// #define DEBUG_ULSCH_DECODING
// #define gNB_DEBUG_TRACE
#define OAI_UL_LDPC_MAX_NUM_LLR 27000 // 26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
// #define DEBUG_CRC
#ifdef DEBUG_CRC
#define PRINT_CRC_CHECK(a) a
#else
#define PRINT_CRC_CHECK(a)
#endif
// extern double cpuf;
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
// Global var to limit the rework of the dirty legacy code
ldpc_interface_t
ldpc_interface_segment
;
int
num_threads_prepare_max
=
0
;
char
*
user_device
=
NULL
;
char
*
enc_read_device
=
NULL
;
char
*
enc_write_device
=
NULL
;
char
*
dec_read_device
=
NULL
;
char
*
dec_write_device
=
NULL
;
/*!
* \typedef args_fpga_decode_prepare_t
* \struct args_fpga_decode_prepare_s
* \brief arguments structure for passing arguments to the nr_ulsch_FPGA_decoding_prepare_blocks function
*/
typedef
struct
args_fpga_decode_prepare_s
{
nrLDPC_TB_decoding_parameters_t
*
TB_params
;
/*!< transport blocks parameters */
uint8_t
*
multi_indata
;
/*!< pointer to the head of the block destination array that is then passed to the FPGA decoding */
int
no_iteration_ldpc
;
/*!< pointer to the number of iteration set by this function */
uint32_t
r_first
;
/*!< index of the first block to be prepared within this function */
uint32_t
r_span
;
/*!< number of blocks to be prepared within this function */
int
r_offset
;
/*!< r index expressed in bits */
int
input_CBoffset
;
/*!< */
int
kc
;
/*!< */
int
K_bits_F
;
/*!< */
task_ans_t
*
ans
;
/*!< pointer to the answer that is used by thread pool to detect job completion */
}
args_fpga_decode_prepare_t
;
int32_t
nrLDPC_coding_init
(
void
);
int32_t
nrLDPC_coding_shutdown
(
void
);
int32_t
nrLDPC_coding_decoder
(
nrLDPC_slot_decoding_parameters_t
*
slot_params
,
int
frame_rx
,
int
slot_rx
);
// int32_t nrLDPC_coding_encoder(void);
int
decoder_xdma
(
nrLDPC_TB_decoding_parameters_t
*
TB_params
,
int
frame_rx
,
int
slot_rx
,
tpool_t
*
ldpc_threadPool
);
void
nr_ulsch_FPGA_decoding_prepare_blocks
(
void
*
args
);
int32_t
nrLDPC_coding_init
(
void
)
{
char
*
encoder_shlibversion
=
NULL
;
paramdef_t
LoaderParams
[]
=
{
{
"num_threads_prepare"
,
NULL
,
0
,
.
iptr
=
&
num_threads_prepare_max
,
.
defintval
=
0
,
TYPE_INT
,
0
,
NULL
},
{
"encoder_shlibversion"
,
NULL
,
0
,
.
strptr
=
&
encoder_shlibversion
,
.
defstrval
=
""
,
TYPE_STRING
,
0
,
NULL
},
{
"user_device"
,
NULL
,
0
,
.
strptr
=
&
user_device
,
.
defstrval
=
DEVICE_NAME_DEFAULT_USER
,
TYPE_STRING
,
0
,
NULL
},
{
"enc_read_device"
,
NULL
,
0
,
.
strptr
=
&
enc_read_device
,
.
defstrval
=
DEVICE_NAME_DEFAULT_ENC_READ
,
TYPE_STRING
,
0
,
NULL
},
{
"enc_write_device"
,
NULL
,
0
,
.
strptr
=
&
enc_write_device
,
.
defstrval
=
DEVICE_NAME_DEFAULT_ENC_WRITE
,
TYPE_STRING
,
0
,
NULL
},
{
"dec_read_device"
,
NULL
,
0
,
.
strptr
=
&
dec_read_device
,
.
defstrval
=
DEVICE_NAME_DEFAULT_DEC_READ
,
TYPE_STRING
,
0
,
NULL
},
{
"dec_write_device"
,
NULL
,
0
,
.
strptr
=
&
dec_write_device
,
.
defstrval
=
DEVICE_NAME_DEFAULT_DEC_WRITE
,
TYPE_STRING
,
0
,
NULL
}
};
config_get
(
config_get_if
(),
LoaderParams
,
sizeofArray
(
LoaderParams
),
"nrLDPC_coding_xdma"
);
AssertFatal
(
num_threads_prepare_max
!=
0
,
"nrLDPC_coding_xdma.num_threads_prepare was not provided"
);
load_LDPClib
(
encoder_shlibversion
,
&
ldpc_interface_segment
);
return
0
;
}
int32_t
nrLDPC_coding_shutdown
(
void
)
{
free_LDPClib
(
&
ldpc_interface_segment
);
return
0
;
}
int32_t
nrLDPC_coding_decoder
(
nrLDPC_slot_decoding_parameters_t
*
slot_params
,
int
frame_rx
,
int
slot_rx
)
{
int
nbDecode
=
0
;
for
(
int
ULSCH_id
=
0
;
ULSCH_id
<
slot_params
->
nb_TBs
;
ULSCH_id
++
)
nbDecode
+=
decoder_xdma
(
&
slot_params
->
TBs
[
ULSCH_id
],
frame_rx
,
slot_rx
,
slot_params
->
threadPool
);
return
nbDecode
;
}
/*
int32_t nrLDPC_coding_encoder(void)
{
return 0;
}
*/
int
decoder_xdma
(
nrLDPC_TB_decoding_parameters_t
*
TB_params
,
int
frame_rx
,
int
slot_rx
,
tpool_t
*
ldpc_threadPool
)
{
const
uint32_t
Kr
=
TB_params
->
K
;
const
uint32_t
Kr_bytes
=
Kr
>>
3
;
const
int
kc
=
TB_params
->
BG
==
2
?
52
:
68
;
int
r_offset
=
0
,
offset
=
0
;
int
K_bits_F
=
Kr
-
TB_params
->
F
;
// FPGA parameter preprocessing
static
uint8_t
multi_indata
[
27000
*
25
];
// FPGA input data
static
uint8_t
multi_outdata
[
1100
*
25
];
// FPGA output data
int
bg_len
=
TB_params
->
BG
==
1
?
22
:
10
;
// Calc input CB offset
int
input_CBoffset
=
TB_params
->
Z
*
kc
*
8
;
if
((
input_CBoffset
&
0x7F
)
==
0
)
input_CBoffset
=
input_CBoffset
/
8
;
else
input_CBoffset
=
16
*
((
input_CBoffset
/
128
)
+
1
);
DecIFConf
dec_conf
=
{
0
};
dec_conf
.
Zc
=
TB_params
->
Z
;
dec_conf
.
BG
=
TB_params
->
BG
;
dec_conf
.
max_iter
=
TB_params
->
max_ldpc_iterations
;
dec_conf
.
numCB
=
TB_params
->
C
;
// input soft bits length, Zc x 66 - length of filler bits
dec_conf
.
numChannelLls
=
(
K_bits_F
-
2
*
TB_params
->
Z
)
+
(
kc
*
TB_params
->
Z
-
Kr
);
// filler bits length
dec_conf
.
numFillerBits
=
TB_params
->
F
;
dec_conf
.
max_schedule
=
0
;
dec_conf
.
SetIdx
=
12
;
dec_conf
.
nRows
=
(
dec_conf
.
BG
==
1
)
?
46
:
42
;
dec_conf
.
user_device
=
user_device
;
dec_conf
.
enc_read_device
=
enc_read_device
;
dec_conf
.
enc_write_device
=
enc_write_device
;
dec_conf
.
dec_read_device
=
dec_read_device
;
dec_conf
.
dec_write_device
=
dec_write_device
;
int
out_CBoffset
=
dec_conf
.
Zc
*
bg_len
;
if
((
out_CBoffset
&
0x7F
)
==
0
)
out_CBoffset
=
out_CBoffset
/
8
;
else
out_CBoffset
=
16
*
((
out_CBoffset
/
128
)
+
1
);
#ifdef LDPC_DATA
printf
(
"
\n
------------------------
\n
"
);
printf
(
"BG:
\t\t
%d
\n
"
,
dec_conf
.
BG
);
printf
(
"TB_params->C: %d
\n
"
,
TB_params
->
C
);
printf
(
"TB_params->K: %d
\n
"
,
TB_params
->
K
);
printf
(
"TB_params->Z: %d
\n
"
,
TB_params
->
Z
);
printf
(
"TB_params->F: %d
\n
"
,
TB_params
->
F
);
printf
(
"numChannelLls:
\t
%d = (%d - 2 * %d) + (%d * %d - %d)
\n
"
,
dec_conf
.
numChannelLls
,
K_bits_F
,
TB_params
->
Z
,
kc
,
TB_params
->
Z
,
Kr
);
printf
(
"numFillerBits:
\t
%d
\n
"
,
TB_params
->
F
);
printf
(
"------------------------
\n
"
);
// ===================================
// debug mode
// ===================================
FILE
*
fptr_llr
,
*
fptr_ldpc
;
fptr_llr
=
fopen
(
"../../../cmake_targets/log/ulsim_ldpc_llr.txt"
,
"w"
);
fptr_ldpc
=
fopen
(
"../../../cmake_targets/log/ulsim_ldpc_output.txt"
,
"w"
);
// ===================================
#endif
int
length_dec
=
lenWithCrc
(
TB_params
->
C
,
TB_params
->
A
);
uint8_t
crc_type
=
crcType
(
TB_params
->
C
,
TB_params
->
A
);
int
no_iteration_ldpc
=
2
;
uint32_t
num_threads_prepare
=
0
;
// calculate required number of jobs
uint32_t
r_while
=
0
;
while
(
r_while
<
TB_params
->
C
)
{
// calculate number of segments processed in the new job
uint32_t
modulus
=
(
TB_params
->
C
-
r_while
)
%
(
num_threads_prepare_max
-
num_threads_prepare
);
uint32_t
quotient
=
(
TB_params
->
C
-
r_while
)
/
(
num_threads_prepare_max
-
num_threads_prepare
);
uint32_t
r_span_max
=
modulus
==
0
?
quotient
:
quotient
+
1
;
// saturate to be sure to not go above C
uint32_t
r_span
=
TB_params
->
C
-
r_while
<
r_span_max
?
TB_params
->
C
-
r_while
:
r_span_max
;
// increment
num_threads_prepare
++
;
r_while
+=
r_span
;
}
args_fpga_decode_prepare_t
arr
[
num_threads_prepare
];
task_ans_t
ans
[
num_threads_prepare
];
memset
(
ans
,
0
,
num_threads_prepare
*
sizeof
(
task_ans_t
));
thread_info_tm_t
t_info
=
{.
buf
=
(
uint8_t
*
)
arr
,
.
len
=
0
,
.
cap
=
num_threads_prepare
,
.
ans
=
ans
};
// start the prepare jobs
uint32_t
r_remaining
=
0
;
for
(
uint32_t
r
=
0
;
r
<
TB_params
->
C
;
r
++
)
{
nrLDPC_segment_decoding_parameters_t
*
segment_params
=
&
TB_params
->
segments
[
r
];
if
(
r_remaining
==
0
)
{
// TODO: int nr_tti_rx = 0;
args_fpga_decode_prepare_t
*
args
=
&
((
args_fpga_decode_prepare_t
*
)
t_info
.
buf
)[
t_info
.
len
];
DevAssert
(
t_info
.
len
<
t_info
.
cap
);
args
->
ans
=
&
t_info
.
ans
[
t_info
.
len
];
t_info
.
len
+=
1
;
args
->
TB_params
=
TB_params
;
args
->
multi_indata
=
multi_indata
;
args
->
no_iteration_ldpc
=
no_iteration_ldpc
;
args
->
r_first
=
r
;
uint32_t
modulus
=
(
TB_params
->
C
-
r
)
%
(
num_threads_prepare_max
-
num_threads_prepare
);
uint32_t
quotient
=
(
TB_params
->
C
-
r
)
/
(
num_threads_prepare_max
-
num_threads_prepare
);
uint32_t
r_span_max
=
modulus
==
0
?
quotient
:
quotient
+
1
;
uint32_t
r_span
=
TB_params
->
C
-
r
<
r_span_max
?
TB_params
->
C
-
r
:
r_span_max
;
args
->
r_span
=
r_span
;
args
->
r_offset
=
r_offset
;
args
->
input_CBoffset
=
input_CBoffset
;
args
->
kc
=
kc
;
args
->
K_bits_F
=
K_bits_F
;
r_remaining
=
r_span
;
task_t
t
=
{.
func
=
&
nr_ulsch_FPGA_decoding_prepare_blocks
,
.
args
=
args
};
pushTpool
(
ldpc_threadPool
,
t
);
LOG_D
(
PHY
,
"Added %d block(s) to prepare for decoding, in pipe: %d to %d
\n
"
,
r_span
,
r
,
r
+
r_span
-
1
);
}
r_offset
+=
segment_params
->
E
;
offset
+=
(
Kr_bytes
-
(
TB_params
->
F
>>
3
)
-
((
TB_params
->
C
>
1
)
?
3
:
0
));
r_remaining
-=
1
;
}
// reset offset in order to properly fill the output array later
offset
=
0
;
DevAssert
(
num_threads_prepare
==
t_info
.
len
);
// wait for the prepare jobs to complete
join_task_ans
(
t_info
.
ans
,
t_info
.
len
);
for
(
uint32_t
job
=
0
;
job
<
num_threads_prepare
;
job
++
)
{
args_fpga_decode_prepare_t
*
args
=
&
arr
[
job
];
if
(
args
->
no_iteration_ldpc
>
TB_params
->
max_ldpc_iterations
)
no_iteration_ldpc
=
TB_params
->
max_ldpc_iterations
+
1
;
}
// launch decode with FPGA
LOG_I
(
PHY
,
"Run the LDPC ------[FPGA version]------
\n
"
);
//==================================================================
// Xilinx FPGA LDPC decoding function -> nrLDPC_decoder_FPGA_PYM()
//==================================================================
start_meas
(
&
TB_params
->
segments
[
0
].
ts_ldpc_decode
);
nrLDPC_decoder_FPGA_PYM
(
&
multi_indata
[
0
],
&
multi_outdata
[
0
],
dec_conf
);
// printf("Xilinx FPGA -> CB = %d\n", harq_process->C);
stop_meas
(
&
TB_params
->
segments
[
0
].
ts_ldpc_decode
);
*
TB_params
->
processedSegments
=
0
;
for
(
uint32_t
r
=
0
;
r
<
TB_params
->
C
;
r
++
)
{
// ------------------------------------------------------------
// --------------------- copy FPGA output ---------------------
// ------------------------------------------------------------
nrLDPC_segment_decoding_parameters_t
*
segment_params
=
&
TB_params
->
segments
[
r
];
if
(
check_crc
(
multi_outdata
,
length_dec
,
crc_type
))
{
#ifdef DEBUG_CRC
LOG_I
(
PHY
,
"Segment %d CRC OK
\n
"
,
r
);
#endif
no_iteration_ldpc
=
2
;
}
else
{
#ifdef DEBUG_CRC
LOG_I
(
PHY
,
"segment %d CRC NOK
\n
"
,
r
);
#endif
no_iteration_ldpc
=
TB_params
->
max_ldpc_iterations
+
1
;
}
for
(
int
i
=
0
;
i
<
out_CBoffset
;
i
++
)
{
segment_params
->
c
[
i
]
=
multi_outdata
[
i
+
r
*
out_CBoffset
];
}
segment_params
->
decodeSuccess
=
(
no_iteration_ldpc
<=
TB_params
->
max_ldpc_iterations
);
if
(
segment_params
->
decodeSuccess
)
{
*
TB_params
->
processedSegments
=
*
TB_params
->
processedSegments
+
1
;
}
}
return
0
;
}
/*!
* \fn nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
* \brief prepare blocks for LDPC decoding on FPGA
*
* \param args pointer to the arguments of the function in a structure of type args_fpga_decode_prepare_t
*/
void
nr_ulsch_FPGA_decoding_prepare_blocks
(
void
*
args
)
{
// extract the arguments
args_fpga_decode_prepare_t
*
arguments
=
(
args_fpga_decode_prepare_t
*
)
args
;
nrLDPC_TB_decoding_parameters_t
*
TB_params
=
arguments
->
TB_params
;
uint8_t
Qm
=
TB_params
->
Qm
;
uint8_t
BG
=
TB_params
->
BG
;
uint8_t
rv_index
=
TB_params
->
rv_index
;
uint8_t
max_ldpc_iterations
=
TB_params
->
max_ldpc_iterations
;
uint32_t
tbslbrm
=
TB_params
->
tbslbrm
;
uint32_t
Kr
=
TB_params
->
K
;
uint32_t
Z
=
TB_params
->
Z
;
uint32_t
F
=
TB_params
->
F
;
uint32_t
C
=
TB_params
->
C
;
nrLDPC_segment_decoding_parameters_t
*
segment_params
=
&
TB_params
->
segments
[
0
];
short
*
ulsch_llr
=
segment_params
->
llr
;
uint8_t
*
multi_indata
=
arguments
->
multi_indata
;
int
no_iteration_ldpc
=
arguments
->
no_iteration_ldpc
;
uint32_t
r_first
=
arguments
->
r_first
;
uint32_t
r_span
=
arguments
->
r_span
;
int
r_offset
=
arguments
->
r_offset
;
int
input_CBoffset
=
arguments
->
input_CBoffset
;
int
kc
=
arguments
->
kc
;
int
K_bits_F
=
arguments
->
K_bits_F
;
int16_t
z
[
68
*
384
+
16
]
__attribute__
((
aligned
(
16
)));
simde__m128i
*
pv
=
(
simde__m128i
*
)
&
z
;
// the function processes r_span blocks starting from block at index r_first in ulsch_llr
for
(
uint32_t
r
=
r_first
;
r
<
(
r_first
+
r_span
);
r
++
)
{
nrLDPC_segment_decoding_parameters_t
*
segment_params
=
&
TB_params
->
segments
[
r
];
// ----------------------- FPGA pre process ------------------------
simde__m128i
ones
=
simde_mm_set1_epi8
(
255
);
// Generate a vector with all elements set to 255
simde__m128i
*
temp_multi_indata
=
(
simde__m128i
*
)
&
multi_indata
[
r
*
input_CBoffset
];
// -----------------------------------------------------------------
// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
int16_t
harq_e
[
segment_params
->
E
];
// -------------------------------------------------------------------------------------------
// deinterleaving
// -------------------------------------------------------------------------------------------
start_meas
(
&
segment_params
->
ts_deinterleave
);
nr_deinterleaving_ldpc
(
segment_params
->
E
,
Qm
,
harq_e
,
ulsch_llr
+
r_offset
);
stop_meas
(
&
segment_params
->
ts_deinterleave
);
// -------------------------------------------------------------------------------------------
// dematching
// -------------------------------------------------------------------------------------------
start_meas
(
&
segment_params
->
ts_rate_unmatch
);
if
(
nr_rate_matching_ldpc_rx
(
tbslbrm
,
BG
,
Z
,
segment_params
->
d
,
harq_e
,
C
,
rv_index
,
*
segment_params
->
d_to_be_cleared
,
segment_params
->
E
,
F
,
Kr
-
F
-
2
*
Z
)
==
-
1
)
{
stop_meas
(
&
segment_params
->
ts_rate_unmatch
);
LOG_E
(
PHY
,
"ulsch_decoding.c: Problem in rate_matching
\n
"
);
no_iteration_ldpc
=
max_ldpc_iterations
+
1
;
arguments
->
no_iteration_ldpc
=
no_iteration_ldpc
;
return
;
}
else
{
stop_meas
(
&
segment_params
->
ts_rate_unmatch
);
}
*
segment_params
->
d_to_be_cleared
=
false
;
memset
(
segment_params
->
c
,
0
,
Kr
>>
3
);
// set first 2*Z_c bits to zeros
memset
(
&
z
[
0
],
0
,
2
*
Z
*
sizeof
(
int16_t
));
// set Filler bits
memset
((
&
z
[
0
]
+
K_bits_F
),
127
,
F
*
sizeof
(
int16_t
));
// Move coded bits before filler bits
memcpy
((
&
z
[
0
]
+
2
*
Z
),
segment_params
->
d
,
(
K_bits_F
-
2
*
Z
)
*
sizeof
(
int16_t
));
// skip filler bits
memcpy
((
&
z
[
0
]
+
Kr
),
segment_params
->
d
+
(
Kr
-
2
*
Z
),
(
kc
*
Z
-
Kr
)
*
sizeof
(
int16_t
));
// Saturate coded bits before decoding into 8 bits values
for
(
int
i
=
0
,
j
=
0
;
j
<
((
kc
*
Z
)
>>
4
);
i
+=
2
,
j
++
)
{
temp_multi_indata
[
j
]
=
simde_mm_xor_si128
(
simde_mm_packs_epi16
(
pv
[
i
],
pv
[
i
+
1
]),
simde_mm_cmpeq_epi32
(
ones
,
ones
));
// Perform NOT operation and write the result to temp_multi_indata[j]
}
// the last bytes before reaching "kc * harq_process->Z" should not be written 128 bits at a time to avoid overwritting the
// following block in multi_indata
simde__m128i
tmp
=
simde_mm_xor_si128
(
simde_mm_packs_epi16
(
pv
[
2
*
((
kc
*
Z
)
>>
4
)],
pv
[
2
*
((
kc
*
Z
)
>>
4
)
+
1
]),
simde_mm_cmpeq_epi32
(
ones
,
ones
));
// Perform NOT operation and write the result to temp_multi_indata[j]
uint8_t
*
tmp_p
=
(
uint8_t
*
)
&
tmp
;
for
(
int
i
=
0
,
j
=
((
kc
*
Z
)
&
0xfffffff0
);
j
<
kc
*
Z
;
i
++
,
j
++
)
{
multi_indata
[
r
*
input_CBoffset
+
j
]
=
tmp_p
[
i
];
}
r_offset
+=
segment_params
->
E
;
}
arguments
->
no_iteration_ldpc
=
no_iteration_ldpc
;
}
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.c
0 → 100644
View file @
8756afdb
/*
* Copyright (c) 2016-present, Xilinx, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license
* the terms of the BSD Licence are reported below:
*
* BSD License
*
* For Xilinx DMA IP software
*
* Copyright (c) 2016-present, Xilinx, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name Xilinx nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _DEFAULT_SOURCE
#define _XOPEN_SOURCE 500
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <byteswap.h>
#include <signal.h>
#include <ctype.h>
#include <termios.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include "xdma_diag.h"
#include "nrLDPC_coding_xdma_offload.h"
#include "common/utils/assertions.h"
typedef
unsigned
long
long
U64
;
void
*
map_base
;
int
fd
;
int
fd_enc_write
,
fd_enc_read
;
char
*
dev_enc_write
,
*
dev_enc_read
;
int
fd_dec_write
,
fd_dec_read
;
char
*
dev_dec_write
,
*
dev_dec_read
;
char
allocated_write
[
24
*
1024
]
__attribute__
((
aligned
(
4096
)));
char
allocated_read
[
24
*
1024
*
3
]
__attribute__
((
aligned
(
4096
)));
// dma_from_device.c
// [Start] #include "dma_utils.c" ===================================
/*
* man 2 write:
* On Linux, write() (and similar system calls) will transfer at most
* 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes
* actually transferred. (This is true on both 32-bit and 64-bit
* systems.)
*/
#define RW_MAX_SIZE 0x7ffff000
int
verbose
=
0
;
uint64_t
getopt_integer
(
char
*
optarg
)
{
int
rc
;
uint64_t
value
;
rc
=
sscanf
(
optarg
,
"0x%lx"
,
&
value
);
if
(
rc
<=
0
)
rc
=
sscanf
(
optarg
,
"%lu"
,
&
value
);
return
value
;
}
ssize_t
read_to_buffer
(
char
*
fname
,
int
fd
,
char
*
buffer
,
uint64_t
size
,
uint64_t
base
)
{
ssize_t
rc
;
uint64_t
count
=
0
;
char
*
buf
=
buffer
;
off_t
offset
=
base
;
while
(
count
<
size
)
{
uint64_t
bytes
=
size
-
count
;
if
(
bytes
>
RW_MAX_SIZE
)
bytes
=
RW_MAX_SIZE
;
if
(
offset
)
{
rc
=
lseek
(
fd
,
offset
,
SEEK_SET
);
if
(
rc
!=
offset
)
{
fprintf
(
stderr
,
"%s, seek off 0x%lx != 0x%lx.
\n
"
,
fname
,
rc
,
offset
);
perror
(
"seek file"
);
return
-
EIO
;
}
}
/* read data from file into memory buffer */
rc
=
read
(
fd
,
buf
,
bytes
);
if
(
rc
!=
bytes
)
{
fprintf
(
stderr
,
"%s, R off 0x%lx, 0x%lx != 0x%lx.
\n
"
,
fname
,
count
,
rc
,
bytes
);
perror
(
"read file"
);
return
-
EIO
;
}
count
+=
bytes
;
buf
+=
bytes
;
offset
+=
bytes
;
}
if
(
count
!=
size
)
{
fprintf
(
stderr
,
"%s, R failed 0x%lx != 0x%lx.
\n
"
,
fname
,
count
,
size
);
return
-
EIO
;
}
return
count
;
}
ssize_t
write_from_buffer
(
char
*
fname
,
int
fd
,
char
*
buffer
,
uint64_t
size
,
uint64_t
base
)
{
ssize_t
rc
;
uint64_t
count
=
0
;
char
*
buf
=
buffer
;
off_t
offset
=
base
;
while
(
count
<
size
)
{
uint64_t
bytes
=
size
-
count
;
if
(
bytes
>
RW_MAX_SIZE
)
bytes
=
RW_MAX_SIZE
;
if
(
offset
)
{
rc
=
lseek
(
fd
,
offset
,
SEEK_SET
);
if
(
rc
!=
offset
)
{
fprintf
(
stderr
,
"%s, seek off 0x%lx != 0x%lx.
\n
"
,
fname
,
rc
,
offset
);
perror
(
"seek file"
);
return
-
EIO
;
}
}
/* write data to file from memory buffer */
rc
=
write
(
fd
,
buf
,
bytes
);
if
(
rc
!=
bytes
)
{
fprintf
(
stderr
,
"%s, W off 0x%lx, 0x%lx != 0x%lx.
\n
"
,
fname
,
offset
,
rc
,
bytes
);
perror
(
"write file"
);
return
-
EIO
;
}
count
+=
bytes
;
buf
+=
bytes
;
offset
+=
bytes
;
}
if
(
count
!=
size
)
{
fprintf
(
stderr
,
"%s, R failed 0x%lx != 0x%lx.
\n
"
,
fname
,
count
,
size
);
return
-
EIO
;
}
return
count
;
}
// [End] #include "dma_utils.c" ===================================
int
test_dma_enc_read
(
char
*
EncOut
,
EncIPConf
Confparam
)
{
ssize_t
rc
;
void
*
virt_addr
;
uint64_t
size
;
uint32_t
writeval
;
uint32_t
Z_val
;
uint16_t
max_schedule
,
mb
,
id
,
bg
,
z_j
,
kb
,
z_a
;
uint16_t
z_set
;
uint32_t
ctrl_data
;
uint32_t
CB_num
=
CB_PROCESS_NUMBER
;
// this values should be given by Shane
max_schedule
=
0
;
mb
=
Confparam
.
mb
;
id
=
CB_num
;
bg
=
Confparam
.
BGSel
-
1
;
z_set
=
Confparam
.
z_set
-
1
;
z_j
=
Confparam
.
z_j
;
if
(
z_set
==
0
)
z_a
=
2
;
else
if
(
z_set
==
1
)
z_a
=
3
;
else
if
(
z_set
==
2
)
z_a
=
5
;
else
if
(
z_set
==
3
)
z_a
=
7
;
else
if
(
z_set
==
4
)
z_a
=
9
;
else
if
(
z_set
==
5
)
z_a
=
11
;
else
if
(
z_set
==
6
)
z_a
=
13
;
else
z_a
=
15
;
if
(
bg
==
0
)
kb
=
22
;
else
if
(
bg
==
1
)
kb
=
10
;
else
if
(
bg
==
2
)
kb
=
9
;
else
if
(
bg
==
3
)
kb
=
8
;
else
kb
=
6
;
mb
=
Confparam
.
kb_1
+
kb
;
Z_val
=
(
unsigned
int
)(
z_a
<<
z_j
);
ctrl_data
=
(
max_schedule
<<
30
)
|
((
mb
-
kb
)
<<
24
)
|
(
id
<<
19
)
|
(
bg
<<
6
)
|
(
z_set
<<
3
)
|
z_j
;
uint32_t
OutDataNUM
=
Z_val
*
mb
;
uint32_t
Out_dwNumItems_p128
;
uint32_t
Out_dwNumItems
;
if
((
OutDataNUM
&
0x7F
)
==
0
)
Out_dwNumItems_p128
=
OutDataNUM
>>
5
;
else
Out_dwNumItems_p128
=
((
OutDataNUM
>>
7
)
+
1
)
<<
2
;
Out_dwNumItems
=
((
Out_dwNumItems_p128
<<
2
)
*
CB_num
);
size
=
Out_dwNumItems
;
writeval
=
ctrl_data
;
/* calculate the virtual address to be accessed */
virt_addr
=
map_base
+
OFFSET_ENC_OUT
;
/* swap 32-bit endianess if host is not little-endian */
writeval
=
htoll
(
writeval
);
*
((
uint32_t
*
)
virt_addr
)
=
writeval
;
if
(
fd_enc_read
<
0
)
{
fprintf
(
stderr
,
"unable to open device %s, %d.
\n
"
,
dev_enc_read
,
fd_enc_read
);
perror
(
"open device"
);
return
-
EINVAL
;
}
/* lseek & read data from AXI MM into buffer using SGDMA */
rc
=
read_to_buffer
(
dev_enc_read
,
fd_enc_read
,
EncOut
,
size
,
0
);
if
(
rc
<
0
)
goto
out
;
rc
=
0
;
out:
return
rc
;
}
int
test_dma_enc_write
(
char
*
data
,
EncIPConf
Confparam
)
{
ssize_t
rc
;
void
*
virt_addr
;
uint64_t
size
;
uint32_t
writeval
;
uint32_t
Z_val
;
uint16_t
max_schedule
,
mb
,
id
,
bg
,
z_j
,
kb
,
z_a
;
uint16_t
z_set
;
uint32_t
ctrl_data
;
uint32_t
CB_num
=
CB_PROCESS_NUMBER
;
// this values should be given by Shane
max_schedule
=
0
;
mb
=
Confparam
.
mb
;
id
=
CB_num
;
bg
=
Confparam
.
BGSel
-
1
;
z_set
=
Confparam
.
z_set
-
1
;
z_j
=
Confparam
.
z_j
;
if
(
z_set
==
0
)
z_a
=
2
;
else
if
(
z_set
==
1
)
z_a
=
3
;
else
if
(
z_set
==
2
)
z_a
=
5
;
else
if
(
z_set
==
3
)
z_a
=
7
;
else
if
(
z_set
==
4
)
z_a
=
9
;
else
if
(
z_set
==
5
)
z_a
=
11
;
else
if
(
z_set
==
6
)
z_a
=
13
;
else
z_a
=
15
;
if
(
bg
==
0
)
kb
=
22
;
else
if
(
bg
==
1
)
kb
=
10
;
else
if
(
bg
==
2
)
kb
=
9
;
else
if
(
bg
==
3
)
kb
=
8
;
else
kb
=
6
;
mb
=
Confparam
.
kb_1
+
kb
;
Z_val
=
(
unsigned
int
)(
z_a
<<
z_j
);
ctrl_data
=
(
max_schedule
<<
30
)
|
((
mb
-
kb
)
<<
24
)
|
(
id
<<
19
)
|
(
bg
<<
6
)
|
(
z_set
<<
3
)
|
z_j
;
uint32_t
InDataNUM
=
Z_val
*
kb
;
uint32_t
In_dwNumItems_p128
;
uint32_t
In_dwNumItems
;
if
((
InDataNUM
&
0x7F
)
==
0
)
In_dwNumItems_p128
=
InDataNUM
>>
5
;
else
In_dwNumItems_p128
=
((
InDataNUM
>>
7
)
+
1
)
<<
2
;
In_dwNumItems
=
((
In_dwNumItems_p128
<<
2
)
*
CB_num
);
size
=
In_dwNumItems
;
writeval
=
ctrl_data
;
/* calculate the virtual address to be accessed */
virt_addr
=
map_base
+
OFFSET_ENC_IN
;
/* swap 32-bit endianess if host is not little-endian */
writeval
=
htoll
(
writeval
);
*
((
uint32_t
*
)
virt_addr
)
=
writeval
;
if
(
fd_enc_write
<
0
)
{
fprintf
(
stderr
,
"unable to open device %s, %d.
\n
"
,
dev_enc_write
,
fd_enc_write
);
perror
(
"open device"
);
return
-
EINVAL
;
}
rc
=
write_from_buffer
(
dev_enc_write
,
fd_enc_write
,
data
,
size
,
0
);
if
(
rc
<
0
)
goto
out
;
rc
=
0
;
out:
return
rc
;
}
// int test_dma_dec_read(unsigned int *DecOut, DecIPConf Confparam)
int
test_dma_dec_read
(
char
*
DecOut
,
DecIPConf
Confparam
)
{
ssize_t
rc
;
void
*
virt_addr
;
uint64_t
size
;
uint32_t
writeval
;
uint32_t
Z_val
;
uint16_t
max_schedule
,
mb
,
id
,
bg
,
z_j
,
kb
,
z_a
,
max_iter
,
sc_idx
;
uint16_t
z_set
;
uint32_t
ctrl_data
;
uint32_t
CB_num
=
Confparam
.
CB_num
;
// this values should be given by Shane
max_schedule
=
0
;
mb
=
Confparam
.
mb
;
id
=
CB_num
;
bg
=
Confparam
.
BGSel
-
1
;
z_set
=
Confparam
.
z_set
-
1
;
z_j
=
Confparam
.
z_j
;
max_iter
=
8
;
sc_idx
=
12
;
if
(
z_set
==
0
)
z_a
=
2
;
else
if
(
z_set
==
1
)
z_a
=
3
;
else
if
(
z_set
==
2
)
z_a
=
5
;
else
if
(
z_set
==
3
)
z_a
=
7
;
else
if
(
z_set
==
4
)
z_a
=
9
;
else
if
(
z_set
==
5
)
z_a
=
11
;
else
if
(
z_set
==
6
)
z_a
=
13
;
else
z_a
=
15
;
if
(
bg
==
0
)
kb
=
22
;
else
if
(
bg
==
1
)
kb
=
10
;
else
if
(
bg
==
2
)
kb
=
9
;
else
if
(
bg
==
3
)
kb
=
8
;
else
kb
=
6
;
Z_val
=
(
unsigned
int
)(
z_a
<<
z_j
);
ctrl_data
=
(
max_schedule
<<
30
)
|
((
mb
-
kb
)
<<
24
)
|
(
id
<<
19
)
|
(
max_iter
<<
13
)
|
(
sc_idx
<<
9
)
|
(
bg
<<
6
)
|
(
z_set
)
<<
3
|
z_j
;
uint32_t
OutDataNUM
=
Z_val
*
kb
;
uint32_t
Out_dwNumItems_p128
;
uint32_t
Out_dwNumItems
;
if
(
CB_num
&
0x01
)
// odd cb number
{
if
((
OutDataNUM
&
0xFF
)
==
0
)
Out_dwNumItems_p128
=
OutDataNUM
;
else
Out_dwNumItems_p128
=
256
*
((
OutDataNUM
/
256
)
+
1
);
Out_dwNumItems
=
(
Out_dwNumItems_p128
*
CB_num
)
>>
3
;
}
else
{
if
((
OutDataNUM
&
0x7F
)
==
0
)
Out_dwNumItems_p128
=
OutDataNUM
;
else
Out_dwNumItems_p128
=
128
*
((
OutDataNUM
/
128
)
+
1
);
Out_dwNumItems
=
(
Out_dwNumItems_p128
*
CB_num
)
>>
3
;
if
((
Out_dwNumItems
&
0x1f
)
!=
0
)
Out_dwNumItems
=
((
Out_dwNumItems
+
31
)
>>
5
)
<<
5
;
}
size
=
Out_dwNumItems
;
writeval
=
ctrl_data
;
/* calculate the virtual address to be accessed */
virt_addr
=
map_base
+
OFFSET_DEC_OUT
;
/* swap 32-bit endianess if host is not little-endian */
writeval
=
htoll
(
writeval
);
*
((
uint32_t
*
)
virt_addr
)
=
writeval
;
if
(
fd_dec_read
<
0
)
{
fprintf
(
stderr
,
"unable to open device %s, %d.
\n
"
,
dev_dec_read
,
fd_dec_read
);
perror
(
"open device"
);
return
-
EINVAL
;
}
/* lseek & read data from AXI MM into buffer using SGDMA */
rc
=
read_to_buffer
(
dev_dec_read
,
fd_dec_read
,
DecOut
,
size
,
0
);
if
(
rc
<
0
)
goto
out
;
rc
=
0
;
out:
return
rc
;
}
// int test_dma_dec_write(unsigned int *data, DecIPConf Confparam)
int
test_dma_dec_write
(
char
*
data
,
DecIPConf
Confparam
)
{
ssize_t
rc
;
void
*
virt_addr
;
uint64_t
size
;
uint32_t
writeval
;
uint32_t
Z_val
;
uint16_t
max_schedule
,
mb
,
id
,
bg
,
z_j
,
kb
,
z_a
,
max_iter
,
sc_idx
;
uint16_t
z_set
;
uint32_t
ctrl_data
;
uint32_t
CB_num
=
Confparam
.
CB_num
;
// CB_PROCESS_NUMBER_Dec;//
// this values should be given by Shane
max_schedule
=
0
;
mb
=
Confparam
.
mb
;
id
=
CB_num
;
bg
=
Confparam
.
BGSel
-
1
;
z_set
=
Confparam
.
z_set
-
1
;
z_j
=
Confparam
.
z_j
;
max_iter
=
8
;
sc_idx
=
12
;
if
(
z_set
==
0
)
z_a
=
2
;
else
if
(
z_set
==
1
)
z_a
=
3
;
else
if
(
z_set
==
2
)
z_a
=
5
;
else
if
(
z_set
==
3
)
z_a
=
7
;
else
if
(
z_set
==
4
)
z_a
=
9
;
else
if
(
z_set
==
5
)
z_a
=
11
;
else
if
(
z_set
==
6
)
z_a
=
13
;
else
z_a
=
15
;
if
(
bg
==
0
)
kb
=
22
;
else
if
(
bg
==
1
)
kb
=
10
;
else
if
(
bg
==
2
)
kb
=
9
;
else
if
(
bg
==
3
)
kb
=
8
;
else
kb
=
6
;
Z_val
=
(
unsigned
int
)(
z_a
<<
z_j
);
ctrl_data
=
(
max_schedule
<<
30
)
|
((
mb
-
kb
)
<<
24
)
|
(
id
<<
19
)
|
(
max_iter
<<
13
)
|
(
sc_idx
<<
9
)
|
(
bg
<<
6
)
|
(
z_set
)
<<
3
|
z_j
;
uint32_t
InDataNUM
=
Z_val
*
mb
;
uint32_t
In_dwNumItems_p128
;
uint32_t
In_dwNumItems
;
InDataNUM
=
Z_val
*
mb
*
8
;
if
((
InDataNUM
&
0x7F
)
==
0
)
In_dwNumItems_p128
=
InDataNUM
;
else
In_dwNumItems_p128
=
128
*
((
InDataNUM
/
128
)
+
1
);
In_dwNumItems
=
(
In_dwNumItems_p128
*
CB_num
)
>>
3
;
if
((
In_dwNumItems
&
0x1f
)
!=
0
)
In_dwNumItems
=
((
In_dwNumItems
+
31
)
>>
5
)
<<
5
;
size
=
In_dwNumItems
;
writeval
=
ctrl_data
;
/* calculate the virtual address to be accessed */
virt_addr
=
map_base
+
OFFSET_DEC_IN
;
/* swap 32-bit endianess if host is not little-endian */
writeval
=
htoll
(
writeval
);
*
((
uint32_t
*
)
virt_addr
)
=
writeval
;
if
(
fd_dec_write
<
0
)
{
fprintf
(
stderr
,
"unable to open device %s, %d.
\n
"
,
dev_dec_write
,
fd_dec_write
);
perror
(
"open device"
);
return
-
EINVAL
;
}
rc
=
write_from_buffer
(
dev_dec_write
,
fd_dec_write
,
data
,
size
,
0
);
if
(
rc
<
0
)
goto
out
;
rc
=
0
;
out:
return
rc
;
}
void
test_dma_init
(
devices_t
devices
)
{
/* access width */
char
*
device2
=
devices
.
user_device
;
AssertFatal
((
fd
=
open
(
device2
,
O_RDWR
|
O_SYNC
))
!=
-
1
,
"CHARACTER DEVICE %s OPEN FAILURE
\n
"
,
device2
);
fflush
(
stdout
);
/* map one page */
map_base
=
mmap
(
0
,
MAP_SIZE
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
fd
,
0
);
AssertFatal
(
map_base
!=
(
void
*
)
-
1
,
"MEMORY MAP AT ADDRESS %p FAILED
\n
"
,
map_base
);
void
*
virt_addr
;
virt_addr
=
map_base
+
OFFSET_RESET
;
*
((
uint32_t
*
)
virt_addr
)
=
1
;
dev_enc_write
=
devices
.
enc_write_device
;
dev_enc_read
=
devices
.
enc_read_device
;
dev_dec_write
=
devices
.
dec_write_device
;
dev_dec_read
=
devices
.
dec_read_device
;
fd_enc_write
=
open
(
dev_enc_write
,
O_RDWR
);
fd_enc_read
=
open
(
dev_enc_read
,
O_RDWR
);
fd_dec_write
=
open
(
dev_dec_write
,
O_RDWR
);
fd_dec_read
=
open
(
dev_dec_read
,
O_RDWR
);
fflush
(
stdout
);
}
void
dma_reset
(
devices_t
devices
)
{
char
*
device2
=
devices
.
user_device
;
void
*
virt_addr
;
virt_addr
=
map_base
+
PCIE_OFF
;
*
((
uint32_t
*
)
virt_addr
)
=
1
;
AssertFatal
(
munmap
(
map_base
,
MAP_SIZE
)
!=
-
1
,
"munmap failure"
);
close
(
fd_enc_write
);
close
(
fd_enc_read
);
close
(
fd_dec_write
);
close
(
fd_dec_read
);
close
(
fd
);
AssertFatal
((
fd
=
open
(
device2
,
O_RDWR
|
O_SYNC
))
!=
-
1
,
"CHARACTER DEVICE %s OPEN FAILURE
\n
"
,
device2
);
fflush
(
stdout
);
/* map one page */
map_base
=
mmap
(
0
,
MAP_SIZE
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
fd
,
0
);
AssertFatal
(
map_base
!=
(
void
*
)
-
1
,
"MEMORY MAP AT ADDRESS %p FAILED
\n
"
,
map_base
);
virt_addr
=
map_base
+
PCIE_OFF
;
*
((
uint32_t
*
)
virt_addr
)
=
1
;
virt_addr
=
map_base
+
OFFSET_RESET
;
*
((
uint32_t
*
)
virt_addr
)
=
1
;
dev_enc_write
=
devices
.
enc_write_device
;
dev_enc_read
=
devices
.
enc_read_device
;
dev_dec_write
=
devices
.
dec_write_device
;
dev_dec_read
=
devices
.
dec_read_device
;
fd_enc_write
=
open
(
dev_enc_write
,
O_RDWR
);
fd_enc_read
=
open
(
dev_enc_read
,
O_RDWR
);
fd_dec_write
=
open
(
dev_dec_write
,
O_RDWR
);
fd_dec_read
=
open
(
dev_dec_read
,
O_RDWR
);
fflush
(
stdout
);
}
void
test_dma_shutdown
()
{
void
*
virt_addr
;
virt_addr
=
map_base
+
PCIE_OFF
;
*
((
uint32_t
*
)
virt_addr
)
=
1
;
AssertFatal
(
munmap
(
map_base
,
MAP_SIZE
)
!=
-
1
,
"munmap failure"
);
close
(
fd_enc_write
);
close
(
fd_enc_read
);
close
(
fd_dec_write
);
close
(
fd_dec_read
);
close
(
fd
);
}
// reg_rx.c
int
nrLDPC_decoder_FPGA_PYM
(
uint8_t
*
buf_in
,
uint8_t
*
buf_out
,
DecIFConf
dec_conf
)
{
struct
timespec
ts_start0
;
// evaluate time from input setting to output setting including xdma
int
Zc
;
int
nRows
;
int
baseGraph
;
int
CB_num
;
DecIPConf
Confparam
;
int
z_a
,
z_tmp
;
int
z_j
=
0
;
int
input_CBoffset
,
output_CBoffset
;
uint8_t
i_LS
;
devices_t
devices
=
{
.
user_device
=
dec_conf
.
user_device
,
.
enc_write_device
=
dec_conf
.
enc_write_device
,
.
enc_read_device
=
dec_conf
.
enc_read_device
,
.
dec_write_device
=
dec_conf
.
dec_write_device
,
.
dec_read_device
=
dec_conf
.
dec_read_device
};
static
int
init_flag
=
0
;
if
(
init_flag
==
0
)
{
/*Init*/
test_dma_init
(
devices
);
init_flag
=
1
;
}
else
{
dma_reset
(
devices
);
}
clock_gettime
(
CLOCK_MONOTONIC
,
&
ts_start0
);
// time start0
// LDPC input parameter
Zc
=
dec_conf
.
Zc
;
// shifting size
nRows
=
dec_conf
.
nRows
;
// number of Rows
baseGraph
=
dec_conf
.
BG
;
// base graph
CB_num
=
dec_conf
.
numCB
;
// 31 number of code block
// calc xdma LDPC parameter
// calc i_LS
if
((
Zc
%
15
)
==
0
)
i_LS
=
7
;
else
if
((
Zc
%
13
)
==
0
)
i_LS
=
6
;
else
if
((
Zc
%
11
)
==
0
)
i_LS
=
5
;
else
if
((
Zc
%
9
)
==
0
)
i_LS
=
4
;
else
if
((
Zc
%
7
)
==
0
)
i_LS
=
3
;
else
if
((
Zc
%
5
)
==
0
)
i_LS
=
2
;
else
if
((
Zc
%
3
)
==
0
)
i_LS
=
1
;
else
i_LS
=
0
;
// calc z_a
if
(
i_LS
==
0
)
z_a
=
2
;
else
z_a
=
i_LS
*
2
+
1
;
// calc z_j
z_tmp
=
Zc
/
z_a
;
while
(
z_tmp
%
2
==
0
)
{
z_j
=
z_j
+
1
;
z_tmp
=
z_tmp
/
2
;
}
// calc CB_num and mb
Confparam
.
CB_num
=
CB_num
;
if
(
baseGraph
==
1
)
Confparam
.
mb
=
22
+
nRows
;
else
Confparam
.
mb
=
10
+
nRows
;
// set BGSel, z_set, z_j
Confparam
.
BGSel
=
baseGraph
;
Confparam
.
z_set
=
i_LS
+
1
;
Confparam
.
z_j
=
z_j
;
// Calc input CB offset
input_CBoffset
=
Zc
*
Confparam
.
mb
*
8
;
if
((
input_CBoffset
&
0x7F
)
==
0
)
input_CBoffset
=
input_CBoffset
/
8
;
else
input_CBoffset
=
16
*
((
input_CBoffset
/
128
)
+
1
);
// Calc output CB offset
output_CBoffset
=
Zc
*
(
Confparam
.
mb
-
nRows
);
if
((
output_CBoffset
&
0x7F
)
==
0
)
output_CBoffset
=
output_CBoffset
/
8
;
else
output_CBoffset
=
16
*
((
output_CBoffset
/
128
)
+
1
);
// LDPC accelerator start
// write into accelerator
if
(
test_dma_dec_write
((
char
*
)
buf_in
,
Confparam
)
!=
0
)
{
exit
(
1
);
printf
(
"write exit!!
\n
"
);
}
// read output of accelerator
if
(
test_dma_dec_read
((
char
*
)
buf_out
,
Confparam
)
!=
0
)
{
exit
(
1
);
printf
(
"read exit!!
\n
"
);
}
return
0
;
}
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.h
0 → 100644
View file @
8756afdb
/*
* 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/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.h
* \briefFPGA accelerator integrated into OAI (for one and multi code block)
* \author Sendren Xu, SY Yeh(fdragon), Hongming, Terng-Yin Hsu
* \date 2022-05-31
* \version 5.0
* \email: summery19961210@gmail.com
*/
#ifndef __NRLDPC_CODING_XDMA_OFFLOAD__H_
#define __NRLDPC_CODING_XDMA_OFFLOAD__H_
#include <stdint.h>
#define DEVICE_NAME_DEFAULT_USER "/dev/xdma0_user"
#define DEVICE_NAME_DEFAULT_ENC_READ "/dev/xdma0_c2h_1"
#define DEVICE_NAME_DEFAULT_ENC_WRITE "/dev/xdma0_h2c_1"
#define DEVICE_NAME_DEFAULT_DEC_READ "/dev/xdma0_c2h_0"
#define DEVICE_NAME_DEFAULT_DEC_WRITE "/dev/xdma0_h2c_0"
/**
\brief LDPC input parameter
\param Zc shifting size
\param Rows
\param baseGraph base graph
\param CB_num number of code block
\param numChannelLlrs input soft bits length, Zc x 66 - length of filler bits
\param numFillerBits filler bits length
*/
typedef
struct
{
char
*
user_device
,
*
enc_write_device
,
*
enc_read_device
,
*
dec_write_device
,
*
dec_read_device
;
unsigned
char
max_schedule
;
unsigned
char
SetIdx
;
int
Zc
;
unsigned
char
numCB
;
unsigned
char
BG
;
unsigned
char
max_iter
;
int
nRows
;
int
numChannelLls
;
int
numFillerBits
;
}
DecIFConf
;
int
nrLDPC_decoder_FPGA_PYM
(
uint8_t
*
buf_in
,
uint8_t
*
buf_out
,
DecIFConf
dec_conf
);
#endif // __NRLDPC_CODING_XDMA_OFFLOAD__H_
openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/xdma_diag.h
0 → 100644
View file @
8756afdb
/*
* Copyright (c) 2016-present, Xilinx, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license
* the terms of the BSD Licence are reported below:
*
* BSD License
*
* For Xilinx DMA IP software
*
* Copyright (c) 2016-present, Xilinx, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name Xilinx nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MODULES_TXCTRL_INC_XDMA_DIAG_H_
#define MODULES_TXCTRL_INC_XDMA_DIAG_H_
#ifdef __cplusplus
extern
"C"
{
#endif
typedef
struct
{
unsigned
char
max_schedule
;
// max_schedule = 0;
unsigned
char
mb
;
// mb = 32;
unsigned
char
CB_num
;
// id = CB_num;
unsigned
char
BGSel
;
// bg = 1;
unsigned
char
z_set
;
// z_set = 0;
unsigned
char
z_j
;
// z_j = 6;
unsigned
char
max_iter
;
// max_iter = 8;
unsigned
char
SetIdx
;
// sc_idx = 12;
}
DecIPConf
;
typedef
struct
{
int
SetIdx
;
int
NumCBSegm
;
int
PayloadLen
;
int
Z
;
int
z_set
;
int
z_j
;
int
Kbmax
;
int
BGSel
;
unsigned
mb
;
unsigned
char
CB_num
;
unsigned
char
kb_1
;
}
EncIPConf
;
typedef
struct
{
char
*
user_device
,
*
enc_write_device
,
*
enc_read_device
,
*
dec_write_device
,
*
dec_read_device
;
}
devices_t
;
/* ltoh: little to host */
/* htol: little to host */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ltohl(x) (x)
#define ltohs(x) (x)
#define htoll(x) (x)
#define htols(x) (x)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ltohl(x) __bswap_32(x)
#define ltohs(x) __bswap_16(x)
#define htoll(x) __bswap_32(x)
#define htols(x) __bswap_16(x)
#endif
#define MAP_SIZE (32 * 1024UL)
#define MAP_MASK (MAP_SIZE - 1)
#define SIZE_DEFAULT (32)
#define COUNT_DEFAULT (1)
#define OFFSET_DEC_IN 0x0000
#define OFFSET_DEC_OUT 0x0004
#define OFFSET_ENC_IN 0x0008
#define OFFSET_ENC_OUT 0x000c
#define OFFSET_RESET 0x0020
#define PCIE_OFF 0x0030
#define CB_PROCESS_NUMBER 24 // add by JW
#define CB_PROCESS_NUMBER_Dec 24
// dma_from_device.c
int
test_dma_enc_read
(
char
*
EncOut
,
EncIPConf
Confparam
);
int
test_dma_enc_write
(
char
*
data
,
EncIPConf
Confparam
);
int
test_dma_dec_read
(
char
*
DecOut
,
DecIPConf
Confparam
);
int
test_dma_dec_write
(
char
*
data
,
DecIPConf
Confparam
);
void
test_dma_init
(
devices_t
devices
);
void
test_dma_shutdown
();
void
dma_reset
(
devices_t
devices
);
#ifdef __cplusplus
}
#endif
#endif
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