mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 12:40:28 +00:00
Compare commits
7 Commits
pre-commit
...
armral_dft
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94f30e41cb | ||
|
|
2da371b02f | ||
|
|
906fcb2091 | ||
|
|
ece34ec190 | ||
|
|
baa2903e0d | ||
|
|
e9b75d6b06 | ||
|
|
aa8eee6531 |
@@ -61,6 +61,12 @@ endif()
|
||||
###################################
|
||||
include(FindPkgConfig)
|
||||
|
||||
# Modules that are required
|
||||
# We provide a find script in cmake_targets/tools/MODULES
|
||||
# for cmake to find the headers and libraries
|
||||
###################################
|
||||
set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}")
|
||||
|
||||
# Check if asn1c is installed, and check if it supports all options we need
|
||||
# a user can provide ASN1C_EXEC to override an asn1c to use (e.g., parallel
|
||||
# installation)
|
||||
@@ -791,6 +797,24 @@ set(PHY_NRLDPC_CODINGIF
|
||||
|
||||
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
|
||||
|
||||
##########################################################
|
||||
# DFT library - ArmRAN Acceleration Library
|
||||
##########################################################
|
||||
|
||||
# TODO: Merge ldpc_armral and dfts_armral in one option?
|
||||
add_boolean_option(ENABLE_DFTS_ARMRAL OFF "Build support for DFT and iDFT with the Arm RAN Acceleration Library" OFF)
|
||||
|
||||
if (ENABLE_DFTS_ARMRAL)
|
||||
|
||||
find_package(armral REQUIRED)
|
||||
add_library(dfts_armral MODULE
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_armral.c
|
||||
)
|
||||
set_target_properties(dfts_armral PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
target_link_libraries(dfts_armral PRIVATE armral)
|
||||
|
||||
endif()
|
||||
|
||||
add_library(crc_byte OBJECT ${OPENAIR1_DIR}/PHY/CODING/crc_byte.c)
|
||||
|
||||
set(PHY_SRC_COMMON
|
||||
@@ -1694,7 +1718,6 @@ include_directories("${NFAPI_DIR}/pnf_sim/inc")
|
||||
add_library(oai_iqplayer MODULE
|
||||
${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c
|
||||
)
|
||||
set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}")
|
||||
|
||||
#################################
|
||||
# add executables for operation
|
||||
|
||||
@@ -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 ldpc_xdma websrv oai_iqplayer imscope imscope_record"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 ldpc_xdma ldpc_armral websrv oai_iqplayer imscope imscope_record dfts_armral"
|
||||
TARGET_LIST=""
|
||||
BUILD_TOOL_OPT="-j$(nproc)"
|
||||
|
||||
|
||||
@@ -143,6 +143,20 @@ void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out)
|
||||
_mm512_storeu_epi8(&out[i], reversed);
|
||||
}
|
||||
|
||||
for (; i < sz; ++i) {
|
||||
out[i] = bit_reverse_table_256[in[i]];
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
int simde_sz = 16;
|
||||
int i = 0;
|
||||
int simde_bound = sz - simde_sz;
|
||||
if((((uintptr_t)in & 63) == 0) && (((uintptr_t)out & 63)== 0)) {
|
||||
for (; i <= simde_bound; i += simde_sz) {
|
||||
uint8x16_t input = vld1q_u8(&in[i]);
|
||||
*((uint8x16_t *)&in[i]) = vrbitq_u8(input);
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < sz; ++i) {
|
||||
out[i] = bit_reverse_table_256[in[i]];
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ RUN git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git /opt/phy && \
|
||||
## Build Arm RAN Acceleration Library
|
||||
RUN git clone https://git.gitlab.arm.com/networking/ral.git /opt/ral && \
|
||||
cd /opt/ral && \
|
||||
git checkout armral-25.01 &&\
|
||||
git checkout armral-25.04 &&\
|
||||
mkdir build && \
|
||||
cd build && \
|
||||
cmake -GNinja -DBUILD_SHARED_LIBS=On /opt/ral/ && \
|
||||
@@ -79,7 +79,7 @@ RUN /bin/sh oaienv && \
|
||||
mkdir -p log && \
|
||||
./build_oai \
|
||||
--gNB \
|
||||
--build-lib "telnetsrv enbscope uescope nrscope" \
|
||||
--build-lib "telnetsrv enbscope uescope nrscope ldpc_armral" \
|
||||
-t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
|
||||
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
$BUILD_OPTION && \
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
add_subdirectory(nrLDPC_coding_segment)
|
||||
add_subdirectory(nrLDPC_coding_xdma)
|
||||
add_subdirectory(nrLDPC_coding_t2)
|
||||
add_subdirectory(nrLDPC_coding_armral)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
##########################################################
|
||||
|
||||
# LDPC coding library - ArmRAN Acceleration Library
|
||||
##########################################################
|
||||
|
||||
add_boolean_option(ENABLE_LDPC_ARMRAL OFF "Build support for LDPC coding with the Arm RAN Acceleration Library" OFF)
|
||||
|
||||
if (ENABLE_LDPC_ARMRAL)
|
||||
|
||||
find_package(armral REQUIRED)
|
||||
add_library(ldpc_armral MODULE
|
||||
nrLDPC_coding_armral_encoder.c
|
||||
nrLDPC_coding_armral_decoder.c
|
||||
)
|
||||
set_target_properties(ldpc_armral PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
target_link_libraries(ldpc_armral PRIVATE ldpc_gen_HEADERS)
|
||||
target_link_libraries(ldpc_armral PRIVATE armral)
|
||||
|
||||
add_dependencies(ldpctest ldpc_armral)
|
||||
add_dependencies(nr-softmodem ldpc_armral)
|
||||
add_dependencies(nr-uesoftmodem ldpc_armral)
|
||||
add_dependencies(nr_ulsim ldpc_armral)
|
||||
add_dependencies(nr_ulschsim ldpc_armral)
|
||||
add_dependencies(nr_dlsim ldpc_armral)
|
||||
add_dependencies(nr_dlschsim ldpc_armral)
|
||||
|
||||
add_library(ldpc_armral_dec MODULE
|
||||
../nrLDPC_coding_segment/nr_rate_matching.c
|
||||
nrLDPC_coding_armral_decoder.c
|
||||
../nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c
|
||||
../../nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
|
||||
)
|
||||
set_target_properties(ldpc_armral_dec PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
target_link_libraries(ldpc_armral_dec PRIVATE ldpc_gen_HEADERS)
|
||||
target_link_libraries(ldpc_armral_dec PRIVATE armral)
|
||||
|
||||
add_dependencies(ldpctest ldpc_armral_dec)
|
||||
add_dependencies(nr-softmodem ldpc_armral_dec)
|
||||
add_dependencies(nr-uesoftmodem ldpc_armral_dec)
|
||||
add_dependencies(nr_ulsim ldpc_armral_dec)
|
||||
add_dependencies(nr_ulschsim ldpc_armral_dec)
|
||||
add_dependencies(nr_dlsim ldpc_armral_dec)
|
||||
add_dependencies(nr_dlschsim ldpc_armral_dec)
|
||||
|
||||
#ensure that the T header files are generated before targets depending on them
|
||||
if (${T_TRACER})
|
||||
add_dependencies(ldpc_armral generate_T)
|
||||
add_dependencies(ldpc_armral_dec generate_T)
|
||||
endif (${T_TRACER})
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* 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_armral/nrLDPC_coding_armral_decoder.c
|
||||
* \brief Top-level routines for decoding LDPC transport channels using the Arm RAN Acceleration Library
|
||||
* \author Romain Beurdouche
|
||||
* \date 2025
|
||||
* \company EURECOM
|
||||
* \email romain.beurdouche@eurecom.fr
|
||||
* \note ArmRAL available at https://git.gitlab.arm.com/networking/ral.git
|
||||
* \warning
|
||||
*/
|
||||
|
||||
// [from gNB coding]
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.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/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "defs.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#include <stdalign.h>
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
#include <time.h>
|
||||
#include <armral.h>
|
||||
// #define gNB_DEBUG_TRACE
|
||||
|
||||
#define OAI_LDPC_DECODER_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
|
||||
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_decoding_parameters_t
|
||||
* \struct nrLDPC_decoding_parameters_s
|
||||
* \brief decoding parameter of transport blocks
|
||||
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
|
||||
* \var K Code block size at decoder output
|
||||
* \var Z lifting size
|
||||
* \var F filler bits size
|
||||
* \var C number of segments
|
||||
* \var E input llr segment size
|
||||
* \var BG Base graph index (BG1: 1, BG2: 2)
|
||||
* \var max_number_iterations maximum number of LDPC iterations
|
||||
* \var tbslbrm transport block size LBRM in bytes
|
||||
* \var Qm modulation order
|
||||
* \var rv_index
|
||||
* \var llr input llr segment array
|
||||
* \var d Pointers to code blocks before LDPC decoding (38.212 V15.4.0 section 5.3.2)
|
||||
* \var d_to_be_cleared
|
||||
* pointer to the flag used to clear d properly
|
||||
* when true, clear d after rate dematching
|
||||
* \var c Pointers to code blocks after LDPC decoding (38.212 V15.4.0 section 5.2.2)
|
||||
* \var decodeSuccess pointer to the flag indicating that the decoding of the segment was successful
|
||||
* \var ans pointer to task answer used by the thread pool to detect task completion
|
||||
* \var abort_decode pointer to decode abort flag
|
||||
* \var p_ts_rate_unmatch pointer to rate unmatching time stats
|
||||
* \var p_ts_ldpc_decode pointer to decoding time stats
|
||||
*/
|
||||
typedef struct nrLDPC_decoding_parameters_s {
|
||||
uint32_t A;
|
||||
uint32_t K;
|
||||
uint32_t Z;
|
||||
uint32_t F;
|
||||
|
||||
uint32_t C;
|
||||
uint32_t E;
|
||||
|
||||
uint8_t BG;
|
||||
uint32_t max_number_iterations;
|
||||
|
||||
uint32_t tbslbrm;
|
||||
uint32_t Qm;
|
||||
uint8_t rv_index;
|
||||
|
||||
short *llr;
|
||||
int16_t *d;
|
||||
bool *d_to_be_cleared;
|
||||
uint8_t *c;
|
||||
bool *decodeSuccess;
|
||||
|
||||
task_ans_t *ans;
|
||||
// decode_abort_t *abort_decode;
|
||||
|
||||
time_stats_t *p_ts_rate_unmatch;
|
||||
time_stats_t *p_ts_ldpc_decode;
|
||||
} nrLDPC_decoding_parameters_t;
|
||||
|
||||
static void nr_process_decode_segment(void *arg)
|
||||
{
|
||||
nrLDPC_decoding_parameters_t *rdata = (nrLDPC_decoding_parameters_t *)arg;
|
||||
const uint32_t A = rdata->A;
|
||||
const uint32_t K = rdata->K;
|
||||
const uint32_t Z = rdata->Z;
|
||||
const uint32_t F = rdata->F;
|
||||
const uint32_t C = rdata->C;
|
||||
const uint32_t Kprime = K - rdata->F;
|
||||
const uint32_t E = rdata->E;
|
||||
const uint32_t max_number_iterations = rdata->max_number_iterations;
|
||||
const uint32_t Qm = rdata->Qm;
|
||||
const uint32_t rv_index = rdata->rv_index;
|
||||
short *ulsch_llr = rdata->llr;
|
||||
uint8_t llrProcBuf[OAI_LDPC_DECODER_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
|
||||
start_meas(rdata->p_ts_rate_unmatch);
|
||||
|
||||
armral_ldpc_graph_t armral_bg = rdata->BG == 2 ? LDPC_BASE_GRAPH_2 : LDPC_BASE_GRAPH_1;
|
||||
|
||||
uint32_t Nref = 3 * rdata->tbslbrm / (2 * C); // R_LBRM = 2/3
|
||||
|
||||
armral_modulation_type armral_mod = ARMRAL_MOD_QPSK;
|
||||
switch (Qm) {
|
||||
case 2:
|
||||
armral_mod = ARMRAL_MOD_QPSK;
|
||||
break;
|
||||
case 4:
|
||||
armral_mod = ARMRAL_MOD_16QAM;
|
||||
break;
|
||||
case 6:
|
||||
armral_mod = ARMRAL_MOD_64QAM;
|
||||
break;
|
||||
case 8:
|
||||
armral_mod = ARMRAL_MOD_256QAM;
|
||||
break;
|
||||
default:
|
||||
LOG_E(PHY, "Modulation order not supported: Qm = %d\n", Qm);
|
||||
break;
|
||||
}
|
||||
|
||||
int size_f = ceil_mod(E, 16);
|
||||
int8_t f[size_f] __attribute__((aligned(64)));
|
||||
memset(f, 0, size_f * sizeof(int8_t));
|
||||
for (int i = 0; i < (size_f >> 4); i++) {
|
||||
((simde__m128i *)f)[i] = simde_mm_packs_epi16(((simde__m128i *)ulsch_llr)[2 * i], ((simde__m128i *)ulsch_llr)[2 * i + 1]);
|
||||
}
|
||||
|
||||
if (*rdata->d_to_be_cleared) {
|
||||
memset(rdata->d, 0, 68 * 384 * sizeof(*rdata->d));
|
||||
*rdata->d_to_be_cleared = false;
|
||||
}
|
||||
|
||||
armral_status status_rate_recovery =
|
||||
armral_ldpc_rate_recovery(armral_bg, Z, E, Nref, F, K, rv_index, armral_mod, f, (int8_t *)rdata->d);
|
||||
if (status_rate_recovery == ARMRAL_ARGUMENT_ERROR) {
|
||||
LOG_E(PHY, "argument error in armral rate recovery\n");
|
||||
} else if (status_rate_recovery == ARMRAL_FAIL) {
|
||||
LOG_E(PHY, "failure in armral rate recovery\n");
|
||||
}
|
||||
|
||||
stop_meas(rdata->p_ts_rate_unmatch);
|
||||
start_meas(rdata->p_ts_ldpc_decode);
|
||||
|
||||
const uint32_t N = rdata->BG == 2 ? 50 * Z : 66 * Z;
|
||||
|
||||
int crc_type = crcType(C, A);
|
||||
uint32_t armral_ldpc_decode_options = ARMRAL_LDPC_DEFAULT_OPTIONS;
|
||||
armral_ldpc_decode_options |= ARMRAL_LDPC_CRC_EVERY_ITER;
|
||||
switch (crc_type) {
|
||||
case CRC24_A:
|
||||
armral_ldpc_decode_options |= ARMRAL_LDPC_CRC_24A;
|
||||
break;
|
||||
|
||||
case CRC24_B:
|
||||
armral_ldpc_decode_options |= ARMRAL_LDPC_CRC_24B;
|
||||
break;
|
||||
|
||||
case CRC16:
|
||||
armral_ldpc_decode_options |= ARMRAL_LDPC_CRC_16;
|
||||
break;
|
||||
|
||||
case CRC8:
|
||||
armral_ldpc_decode_options |= ARMRAL_LDPC_CRC_NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1, "Invalid crc_type \n");
|
||||
}
|
||||
|
||||
armral_status status_decoding = armral_ldpc_decode_block(N,
|
||||
(int8_t *)rdata->d,
|
||||
armral_bg,
|
||||
Z,
|
||||
F,
|
||||
llrProcBuf,
|
||||
max_number_iterations,
|
||||
armral_ldpc_decode_options);
|
||||
if (status_decoding == ARMRAL_ARGUMENT_ERROR) {
|
||||
LOG_E(PHY, "argument error in armral decoding\n");
|
||||
}
|
||||
|
||||
if (check_crc(llrProcBuf, Kprime, crc_type)) {
|
||||
memcpy(rdata->c, llrProcBuf, K >> 3);
|
||||
*rdata->decodeSuccess = true;
|
||||
} else {
|
||||
memset(rdata->c, 0, K >> 3);
|
||||
*rdata->decodeSuccess = false;
|
||||
}
|
||||
stop_meas(rdata->p_ts_ldpc_decode);
|
||||
|
||||
// Task completed
|
||||
completed_task_ans(rdata->ans);
|
||||
}
|
||||
|
||||
int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters,
|
||||
int pusch_id,
|
||||
thread_info_tm_t *t_info)
|
||||
{
|
||||
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
|
||||
|
||||
*nrLDPC_TB_decoding_parameters->processedSegments = 0;
|
||||
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters->C; r++) {
|
||||
nrLDPC_decoding_parameters_t *rdata = &((nrLDPC_decoding_parameters_t *)t_info->buf)[t_info->len];
|
||||
DevAssert(t_info->len < t_info->cap);
|
||||
rdata->ans = t_info->ans;
|
||||
t_info->len += 1;
|
||||
|
||||
rdata->A = nrLDPC_TB_decoding_parameters->A;
|
||||
rdata->K = nrLDPC_TB_decoding_parameters->K;
|
||||
rdata->Z = nrLDPC_TB_decoding_parameters->Z;
|
||||
rdata->F = nrLDPC_TB_decoding_parameters->F;
|
||||
rdata->C = nrLDPC_TB_decoding_parameters->C;
|
||||
rdata->E = nrLDPC_TB_decoding_parameters->segments[r].E;
|
||||
rdata->BG = nrLDPC_TB_decoding_parameters->BG;
|
||||
rdata->max_number_iterations = nrLDPC_TB_decoding_parameters->max_ldpc_iterations;
|
||||
rdata->tbslbrm = nrLDPC_TB_decoding_parameters->tbslbrm;
|
||||
rdata->Qm = nrLDPC_TB_decoding_parameters->Qm;
|
||||
rdata->rv_index = nrLDPC_TB_decoding_parameters->rv_index;
|
||||
rdata->llr = nrLDPC_TB_decoding_parameters->segments[r].llr;
|
||||
rdata->d = nrLDPC_TB_decoding_parameters->segments[r].d;
|
||||
rdata->d_to_be_cleared = nrLDPC_TB_decoding_parameters->segments[r].d_to_be_cleared;
|
||||
rdata->c = nrLDPC_TB_decoding_parameters->segments[r].c;
|
||||
rdata->decodeSuccess = &nrLDPC_TB_decoding_parameters->segments[r].decodeSuccess;
|
||||
// rdata->abort_decode = nrLDPC_TB_decoding_parameters->abort_decode;
|
||||
rdata->p_ts_rate_unmatch = &nrLDPC_TB_decoding_parameters->segments[r].ts_rate_unmatch;
|
||||
rdata->p_ts_ldpc_decode = &nrLDPC_TB_decoding_parameters->segments[r].ts_ldpc_decode;
|
||||
|
||||
task_t t = {.func = &nr_process_decode_segment, .args = rdata};
|
||||
pushTpool(nrLDPC_slot_decoding_parameters->threadPool, t);
|
||||
|
||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
|
||||
}
|
||||
return nrLDPC_TB_decoding_parameters->C;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_shutdown(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters)
|
||||
{
|
||||
int nbSegments = 0;
|
||||
for (int pusch_id = 0; pusch_id < nrLDPC_slot_decoding_parameters->nb_TBs; pusch_id++) {
|
||||
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
|
||||
nbSegments += nrLDPC_TB_decoding_parameters->C;
|
||||
}
|
||||
nrLDPC_decoding_parameters_t arr[nbSegments];
|
||||
task_ans_t ans;
|
||||
init_task_ans(&ans, nbSegments);
|
||||
thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .len = 0, .cap = nbSegments, .ans = &ans};
|
||||
|
||||
for (int pusch_id = 0; pusch_id < nrLDPC_slot_decoding_parameters->nb_TBs; pusch_id++) {
|
||||
(void)nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters, pusch_id, &t_info);
|
||||
}
|
||||
|
||||
// Execute thread pool tasks
|
||||
join_task_ans(t_info.ans);
|
||||
|
||||
for (int pusch_id = 0; pusch_id < nrLDPC_slot_decoding_parameters->nb_TBs; pusch_id++) {
|
||||
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters->C; r++) {
|
||||
if (nrLDPC_TB_decoding_parameters->segments[r].decodeSuccess) {
|
||||
*nrLDPC_TB_decoding_parameters->processedSegments = *nrLDPC_TB_decoding_parameters->processedSegments + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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_segment/nrLDPC_coding_segment_encoder.c
|
||||
* \brief Top-level routines for implementing LDPC encoding of transport channels
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include <openair2/UTIL/OPT/opt.h>
|
||||
|
||||
#include <syscall.h>
|
||||
#include "armral.h"
|
||||
|
||||
#define DEBUG_LDPC_ENCODING
|
||||
//#define DEBUG_LDPC_ENCODING_FREE 1
|
||||
|
||||
typedef struct ldpc8blocks_args_s {
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters;
|
||||
uint32_t macro_num;
|
||||
time_stats_t *toutput;
|
||||
task_ans_t *ans;
|
||||
} ldpc8blocks_args_t;
|
||||
|
||||
static void ldpc8blocks(void *p)
|
||||
{
|
||||
ldpc8blocks_args_t *args = (ldpc8blocks_args_t *)p;
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = args->nrLDPC_TB_encoding_parameters;
|
||||
|
||||
uint32_t A = nrLDPC_TB_encoding_parameters->A;
|
||||
uint32_t K = nrLDPC_TB_encoding_parameters->K;
|
||||
uint32_t Z = nrLDPC_TB_encoding_parameters->Z;
|
||||
uint32_t F = nrLDPC_TB_encoding_parameters->F;
|
||||
uint32_t C = nrLDPC_TB_encoding_parameters->C;
|
||||
uint8_t Qm = nrLDPC_TB_encoding_parameters->Qm;
|
||||
uint16_t nb_rb = nrLDPC_TB_encoding_parameters->nb_rb;
|
||||
|
||||
unsigned int G = nrLDPC_TB_encoding_parameters->G;
|
||||
LOG_D(PHY, "dlsch coding A %d K %d G %d (nb_rb %d, Qm %d)\n", A, K, G, nb_rb, (int)Qm);
|
||||
|
||||
armral_ldpc_graph_t armral_bg = nrLDPC_TB_encoding_parameters->BG == 2 ? LDPC_BASE_GRAPH_2 : LDPC_BASE_GRAPH_1;
|
||||
|
||||
uint32_t Nref = 3 * nrLDPC_TB_encoding_parameters->tbslbrm / (2 * C); // R_LBRM = 2/3
|
||||
|
||||
armral_modulation_type armral_mod = ARMRAL_MOD_QPSK;
|
||||
switch (Qm) {
|
||||
case 2:
|
||||
armral_mod = ARMRAL_MOD_QPSK;
|
||||
break;
|
||||
case 4:
|
||||
armral_mod = ARMRAL_MOD_16QAM;
|
||||
break;
|
||||
case 6:
|
||||
armral_mod = ARMRAL_MOD_64QAM;
|
||||
break;
|
||||
case 8:
|
||||
armral_mod = ARMRAL_MOD_256QAM;
|
||||
break;
|
||||
default:
|
||||
LOG_E(PHY, "Modulation order not supported: Qm = %d\n", Qm);
|
||||
break;
|
||||
}
|
||||
|
||||
// 384 (lifting size in bits) / 8 = 48 (lifting size in bytes)
|
||||
uint8_t d[68 * 48] __attribute__((aligned(64)));
|
||||
uint8_t f[68 * 48] __attribute__((aligned(64)));
|
||||
|
||||
unsigned int macro_segment = 8 * args->macro_num;
|
||||
unsigned int macro_segment_end = (C > 8 * (args->macro_num + 1)) ? 8 * (args->macro_num + 1) : C;
|
||||
unsigned int offset_output_bit = 0;
|
||||
|
||||
// Calculate initial offset in output buffer
|
||||
for (int r = 0; r < macro_segment; r++) {
|
||||
offset_output_bit += nrLDPC_TB_encoding_parameters->segments[r].E;
|
||||
}
|
||||
|
||||
for (int r = macro_segment; r < macro_segment_end; r++) {
|
||||
start_meas(&nrLDPC_TB_encoding_parameters->segments[r].ts_ldpc_encode);
|
||||
|
||||
memset(d, 0, 68 * 48 * sizeof(*d));
|
||||
armral_status status_encoding = armral_ldpc_encode_block(nrLDPC_TB_encoding_parameters->segments[r].c, armral_bg, Z, F, d);
|
||||
if (status_encoding == ARMRAL_ARGUMENT_ERROR) {
|
||||
LOG_E(PHY, "argument error in armral encoding\n");
|
||||
} else if (status_encoding == ARMRAL_FAIL) {
|
||||
LOG_E(PHY, "failure in armral encoding\n");
|
||||
}
|
||||
|
||||
stop_meas(&nrLDPC_TB_encoding_parameters->segments[r].ts_ldpc_encode);
|
||||
|
||||
start_meas(&nrLDPC_TB_encoding_parameters->segments[r].ts_rate_match);
|
||||
|
||||
unsigned int E = nrLDPC_TB_encoding_parameters->segments[r].E;
|
||||
LOG_D(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d Qm %d, nb_rb "
|
||||
"%d,nrOfLayer %d)...\n",
|
||||
r,
|
||||
C,
|
||||
G,
|
||||
E,
|
||||
F,
|
||||
K - F - 2 * Z,
|
||||
Qm,
|
||||
nb_rb,
|
||||
nrLDPC_TB_encoding_parameters->nb_layers);
|
||||
|
||||
if (K - F - 2 * Z > E) {
|
||||
LOG_E(PHY, "dlsch coding A %d Kr %d G %d (nb_rb %d, Qm %d)\n", A, K, G, nb_rb, Qm);
|
||||
|
||||
LOG_E(NR_PHY,
|
||||
"Rate Matching, Code segments %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d Qm %d, "
|
||||
"nb_rb %d)...\n",
|
||||
macro_segment,
|
||||
C,
|
||||
G,
|
||||
E,
|
||||
K,
|
||||
F,
|
||||
K - F - 2 * Z,
|
||||
Qm,
|
||||
nb_rb);
|
||||
}
|
||||
|
||||
memset(f, 0, 68 * 48 * sizeof(*f));
|
||||
armral_status status_rate_matching =
|
||||
armral_ldpc_rate_matching(armral_bg, Z, E, Nref, F, K, nrLDPC_TB_encoding_parameters->rv_index, armral_mod, d, f);
|
||||
if (status_rate_matching == ARMRAL_ARGUMENT_ERROR) {
|
||||
LOG_E(PHY, "argument error in armral rate matching\n");
|
||||
} else if (status_rate_matching == ARMRAL_FAIL) {
|
||||
LOG_E(PHY, "failure in armral rate matching\n");
|
||||
}
|
||||
|
||||
stop_meas(&nrLDPC_TB_encoding_parameters->segments[r].ts_rate_match);
|
||||
|
||||
if (args->toutput != NULL)
|
||||
start_meas(args->toutput);
|
||||
|
||||
unsigned int f_reverse_size = (E & 7) == 0 ? E >> 3 : (E >> 3) + 1;
|
||||
reverse_bits_u8(f, f_reverse_size, f);
|
||||
|
||||
if ((offset_output_bit & 7) == 0) {
|
||||
LOG_D(PHY, "encoder output aligned on byte, using memcpy\n");
|
||||
unsigned int output_copy_size = (E & 7) == 0 ? E >> 3 : (E >> 3) + 1;
|
||||
memcpy(&nrLDPC_TB_encoding_parameters->output[offset_output_bit >> 3], f, output_copy_size);
|
||||
} else {
|
||||
LOG_D(PHY, "encoder output NOT aligned on byte, using Neon\n");
|
||||
uint64_t *f_64 = (uint64_t *)f;
|
||||
unsigned int output_offset_64 = (offset_output_bit >> 3) - ((offset_output_bit >> 3) & 7);
|
||||
uint64_t *output_64 = (uint64_t *)&nrLDPC_TB_encoding_parameters->output[output_offset_64];
|
||||
unsigned int nb_vec = (E & 63) == 0 ? E >> 6 : (E >> 6) + 1;
|
||||
int64_t shift_bit_low = offset_output_bit & 63;
|
||||
int64x1_t shift_bit_low_64x1 = vld1_s64(&shift_bit_low);
|
||||
int64_t shift_bit_high = shift_bit_low - 64;
|
||||
int64x1_t shift_bit_high_64x1 = vld1_s64(&shift_bit_high);
|
||||
for (int i = 0; i < nb_vec; i++) {
|
||||
uint64x1_t f_64x1 = vld1_u64(&f_64[i]);
|
||||
|
||||
uint64x1_t f_64x1_low = vshl_u64(f_64x1, shift_bit_low_64x1);
|
||||
uint64x1_t output_64x1_low = vld1_u64(&output_64[i]);
|
||||
output_64[i] = (uint64_t)vorr_u64(output_64x1_low, f_64x1_low);
|
||||
|
||||
uint64x1_t f_64x1_high = vshl_u64(f_64x1, shift_bit_high_64x1);
|
||||
uint64x1_t output_64x1_high = vld1_u64(&output_64[i + 1]);
|
||||
output_64[i + 1] = (uint64_t)vorr_u64(output_64x1_high, f_64x1_high);
|
||||
}
|
||||
}
|
||||
|
||||
if (args->toutput != NULL)
|
||||
stop_meas(args->toutput);
|
||||
|
||||
// Increment offset in output buffer
|
||||
offset_output_bit += E;
|
||||
// TODO Manage race condition every 8 segment end
|
||||
}
|
||||
|
||||
// Task running in // completed
|
||||
completed_task_ans(args->ans);
|
||||
}
|
||||
|
||||
static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters,
|
||||
int dlsch_id,
|
||||
thread_info_tm_t *t_info)
|
||||
{
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
|
||||
uint32_t C = nrLDPC_TB_encoding_parameters->C;
|
||||
|
||||
size_t const n_seg = (C / 8 + ((C & 7) == 0 ? 0 : 1));
|
||||
|
||||
for (int j = 0; j < n_seg; j++) {
|
||||
ldpc8blocks_args_t *perJobImpp = &((ldpc8blocks_args_t *)t_info->buf)[t_info->len];
|
||||
DevAssert(t_info->len < t_info->cap);
|
||||
perJobImpp->ans = t_info->ans;
|
||||
t_info->len += 1;
|
||||
|
||||
perJobImpp->macro_num = j;
|
||||
perJobImpp->nrLDPC_TB_encoding_parameters = nrLDPC_TB_encoding_parameters;
|
||||
perJobImpp->toutput = nrLDPC_slot_encoding_parameters->toutput;
|
||||
|
||||
task_t t = {.func = ldpc8blocks, .args = perJobImpp};
|
||||
pushTpool(nrLDPC_slot_encoding_parameters->threadPool, t);
|
||||
}
|
||||
return n_seg;
|
||||
}
|
||||
|
||||
int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
||||
{
|
||||
int nbTasks = 0;
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
|
||||
uint32_t C = nrLDPC_TB_encoding_parameters->C;
|
||||
size_t n_seg = (C / 8 + ((C & 7) == 0 ? 0 : 1));
|
||||
nbTasks += n_seg;
|
||||
}
|
||||
ldpc8blocks_args_t arr[nbTasks];
|
||||
task_ans_t ans;
|
||||
init_task_ans(&ans, nbTasks);
|
||||
thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .len = 0, .cap = nbTasks, .ans = &ans};
|
||||
|
||||
int nbEncode = 0;
|
||||
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
|
||||
nbEncode += nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters, dlsch_id, &t_info);
|
||||
}
|
||||
if (nbEncode < nbTasks) {
|
||||
completed_many_task_ans(&ans, nbTasks - nbEncode);
|
||||
}
|
||||
// Execute thread pool tasks
|
||||
join_task_ans(&ans);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -42,10 +42,14 @@
|
||||
|
||||
|
||||
/* function description array, to be used when loading the dfts/idfts lib */
|
||||
static loader_shlibfunc_t shlib_fdesc[2];
|
||||
static loader_shlibfunc_t shlib_fdesc[4];
|
||||
static char *arg[64] = {"phytest", "-O", "cmdlineonly::dbgl0"};
|
||||
|
||||
dftfunc_t dft;
|
||||
idftfunc_t idft;
|
||||
dfts_start_t dfts_start;
|
||||
dfts_stop_t dfts_stop;
|
||||
|
||||
int load_dftslib(void)
|
||||
{
|
||||
char *ptr = (char *)config_get_if();
|
||||
@@ -55,9 +59,27 @@ int load_dftslib(void)
|
||||
}
|
||||
shlib_fdesc[0].fname = "dft_implementation";
|
||||
shlib_fdesc[1].fname = "idft_implementation";
|
||||
shlib_fdesc[2].fname = "dfts_start";
|
||||
shlib_fdesc[3].fname = "dfts_stop";
|
||||
int ret = load_module_shlib("dfts", shlib_fdesc, sizeof(shlib_fdesc) / sizeof(loader_shlibfunc_t), NULL);
|
||||
AssertFatal((ret >= 0), "Error loading dftsc decoder");
|
||||
AssertFatal((ret >= 0), "Error loading dfts decoder");
|
||||
|
||||
dft = (dftfunc_t)shlib_fdesc[0].fptr;
|
||||
idft = (idftfunc_t)shlib_fdesc[1].fptr;
|
||||
dfts_start = (dfts_start_t)shlib_fdesc[2].fptr;
|
||||
dfts_stop = (dfts_stop_t)shlib_fdesc[3].fptr;
|
||||
|
||||
dfts_start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int free_dftslib()
|
||||
{
|
||||
if (dfts_stop) {
|
||||
dfts_stop();
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7730,6 +7730,12 @@ void idft_implementation(uint8_t sizeidx, int16_t *input, int16_t *output, unsig
|
||||
idft_ftab[sizeidx].func(input,output,scale_flag);
|
||||
};
|
||||
|
||||
void dfts_start()
|
||||
{}
|
||||
|
||||
void dfts_stop()
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------------------*/
|
||||
|
||||
249
openair1/PHY/TOOLS/oai_dfts_armral.c
Normal file
249
openair1/PHY/TOOLS/oai_dfts_armral.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <armral.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#define debug_msg
|
||||
#define ONE_OVER_SQRT2_Q15 23170
|
||||
#define ONE_OVER_SQRT3_Q15 18919
|
||||
|
||||
#include "assertions.h"
|
||||
#include "LOG/log.h"
|
||||
#include "time_meas.h"
|
||||
#include "tools_defs.h"
|
||||
#include "../sse_intrin.h"
|
||||
|
||||
#define DEFAULT_NEON
|
||||
|
||||
#ifdef DEFAULT_NEON
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
static loader_shlibfunc_t shlib_fdesc[4];
|
||||
static char *arg[64] = {"phytest", "-O", "cmdlineonly::dbgl0"};
|
||||
dftfunc_t dft_neon;
|
||||
idftfunc_t idft_neon;
|
||||
dfts_start_t dfts_start_neon;
|
||||
dfts_stop_t dfts_stop_neon;
|
||||
#endif
|
||||
|
||||
#define SZ_PTR(Sz) Sz,
|
||||
const int dft_stab[] = {FOREACH_DFTSZ(SZ_PTR)};
|
||||
|
||||
#define SZ_iPTR(Sz) Sz,
|
||||
const int idft_stab[] = {FOREACH_IDFTSZ(SZ_iPTR)};
|
||||
|
||||
// Pre-allocated plans for PRACH
|
||||
armral_fft_plan_t *idft_256_cs16_plan_p;
|
||||
armral_fft_plan_t *idft_1024_cs16_plan_p;
|
||||
|
||||
void armral_dft(uint8_t sizeidx, int16_t *x, int16_t *y, unsigned char scale_flag)
|
||||
{
|
||||
#ifdef DEFAULT_NEON
|
||||
dft_neon(sizeidx, x, y, scale_flag);
|
||||
#else
|
||||
armral_status status;
|
||||
switch (sizeidx) {
|
||||
default:
|
||||
armral_fft_plan_t *dft_cs16_plan_p;
|
||||
status = armral_fft_create_plan_cs16(&dft_cs16_plan_p, idft_stab[sizeidx], ARMRAL_FFT_FORWARDS);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT create plan\n");
|
||||
status = armral_fft_execute_cs16(dft_cs16_plan_p, (armral_cmplx_int16_t *)x, (armral_cmplx_int16_t *)y);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT\n");
|
||||
status = armral_fft_destroy_plan_cs16(&dft_cs16_plan_p);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT destroy plan\n");
|
||||
if (scale_flag > 0) {
|
||||
simd_q15_t *y128 = (simd_q15_t *)y;
|
||||
int sz = dft_stab[sizeidx];
|
||||
for (int i = 0; i < (sz / 4); i++) {
|
||||
y128[i] = shiftright_int16(y128[i], 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void armral_idft(uint8_t sizeidx, int16_t *x, int16_t *y, unsigned char scale_flag)
|
||||
{
|
||||
armral_status status;
|
||||
switch (sizeidx) {
|
||||
case IDFT_256:
|
||||
status = armral_fft_execute_cs16(idft_256_cs16_plan_p, (armral_cmplx_int16_t *)x, (armral_cmplx_int16_t *)y);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT\n");
|
||||
if (scale_flag > 0) {
|
||||
simd_q15_t *y128 = (simd_q15_t *)y;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
y128[0] = shiftright_int16(y128[0], 1);
|
||||
y128[1] = shiftright_int16(y128[1], 1);
|
||||
y128[2] = shiftright_int16(y128[2], 1);
|
||||
y128[3] = shiftright_int16(y128[3], 1);
|
||||
y128[4] = shiftright_int16(y128[4], 1);
|
||||
y128[5] = shiftright_int16(y128[5], 1);
|
||||
y128[6] = shiftright_int16(y128[6], 1);
|
||||
y128[7] = shiftright_int16(y128[7], 1);
|
||||
y128[8] = shiftright_int16(y128[8], 1);
|
||||
y128[9] = shiftright_int16(y128[9], 1);
|
||||
y128[10] = shiftright_int16(y128[10], 1);
|
||||
y128[11] = shiftright_int16(y128[11], 1);
|
||||
y128[12] = shiftright_int16(y128[12], 1);
|
||||
y128[13] = shiftright_int16(y128[13], 1);
|
||||
y128[14] = shiftright_int16(y128[14], 1);
|
||||
y128[15] = shiftright_int16(y128[15], 1);
|
||||
y128 += 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDFT_1024:
|
||||
status = armral_fft_execute_cs16(idft_1024_cs16_plan_p, (armral_cmplx_int16_t *)x, (armral_cmplx_int16_t *)y);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT\n");
|
||||
if (scale_flag > 0) {
|
||||
simd_q15_t *y128 = (simd_q15_t *)y;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
y128[0] = shiftright_int16(y128[0], 1);
|
||||
y128[1] = shiftright_int16(y128[1], 1);
|
||||
y128[2] = shiftright_int16(y128[2], 1);
|
||||
y128[3] = shiftright_int16(y128[3], 1);
|
||||
y128[4] = shiftright_int16(y128[4], 1);
|
||||
y128[5] = shiftright_int16(y128[5], 1);
|
||||
y128[6] = shiftright_int16(y128[6], 1);
|
||||
y128[7] = shiftright_int16(y128[7], 1);
|
||||
y128[8] = shiftright_int16(y128[8], 1);
|
||||
y128[9] = shiftright_int16(y128[9], 1);
|
||||
y128[10] = shiftright_int16(y128[10], 1);
|
||||
y128[11] = shiftright_int16(y128[11], 1);
|
||||
y128[12] = shiftright_int16(y128[12], 1);
|
||||
y128[13] = shiftright_int16(y128[13], 1);
|
||||
y128[14] = shiftright_int16(y128[14], 1);
|
||||
y128[15] = shiftright_int16(y128[15], 1);
|
||||
y128 += 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef DEFAULT_NEON
|
||||
idft_neon(sizeidx, x, y, scale_flag);
|
||||
#else
|
||||
armral_fft_plan_t *idft_cs16_plan_p;
|
||||
status = armral_fft_create_plan_cs16(&idft_cs16_plan_p, idft_stab[sizeidx], ARMRAL_FFT_BACKWARDS);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT create plan\n");
|
||||
status = armral_fft_execute_cs16(idft_cs16_plan_p, (armral_cmplx_int16_t *)x, (armral_cmplx_int16_t *)y);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT\n");
|
||||
status = armral_fft_destroy_plan_cs16(&idft_cs16_plan_p);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT destroy plan\n");
|
||||
if (scale_flag > 0) {
|
||||
simd_q15_t *y128 = (simd_q15_t *)y;
|
||||
int sz = idft_stab[sizeidx];
|
||||
for (int i = 0; i < (sz / 4); i++) {
|
||||
y128[i] = shiftright_int16(y128[i], 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dft_implementation(uint8_t sizeidx, int16_t *input, int16_t *output, unsigned char scale_flag)
|
||||
{
|
||||
AssertFatal((sizeidx >= 0 && sizeidx < DFT_SIZE_IDXTABLESIZE), "Invalid dft size index %i\n", sizeidx);
|
||||
int algn = 0xF;
|
||||
AssertFatal(((intptr_t)output & algn) == 0, "Buffers should be aligned %p", output);
|
||||
|
||||
if (((intptr_t)input) & algn) {
|
||||
int sz = dft_stab[sizeidx];
|
||||
LOG_D(PHY, "DFT called with input not aligned, add a memcpy, size %d\n", sz);
|
||||
if (sizeidx == DFT_12) // This case does 8 DFTs in //
|
||||
sz *= 8;
|
||||
int16_t tmp[sz * 2] __attribute__((aligned(32))); // input and output are not in right type (int16_t instead of c16_t)
|
||||
memcpy(tmp, input, sizeof(tmp));
|
||||
armral_dft(sizeidx, tmp, output, scale_flag);
|
||||
} else {
|
||||
armral_dft(sizeidx, input, output, scale_flag);
|
||||
}
|
||||
}
|
||||
|
||||
void idft_implementation(uint8_t sizeidx, int16_t *input, int16_t *output, unsigned char scale_flag)
|
||||
{
|
||||
AssertFatal((sizeidx >= 0 && sizeidx < DFT_SIZE_IDXTABLESIZE), "Invalid idft size index %i\n", sizeidx);
|
||||
int algn = 0xF;
|
||||
AssertFatal(((intptr_t)output & algn) == 0, "Buffers should be 16 bytes aligned %p", output);
|
||||
|
||||
if (((intptr_t)input) & algn) {
|
||||
int sz = idft_stab[sizeidx];
|
||||
LOG_D(PHY, "IDFT called with input not aligned, add a memcpy, size %d\n", sz);
|
||||
int16_t tmp[sz * 2] __attribute__((aligned(32))); // input and output are not in right type (int16_t instead of c16_t)
|
||||
memcpy(tmp, input, sizeof(tmp));
|
||||
armral_idft(sizeidx, tmp, output, scale_flag);
|
||||
} else {
|
||||
armral_idft(sizeidx, input, output, scale_flag);
|
||||
}
|
||||
}
|
||||
|
||||
void dfts_start()
|
||||
{
|
||||
armral_status status;
|
||||
status = armral_fft_create_plan_cs16(&idft_256_cs16_plan_p, 256, ARMRAL_FFT_BACKWARDS);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT create plan\n");
|
||||
status = armral_fft_create_plan_cs16(&idft_1024_cs16_plan_p, 1024, ARMRAL_FFT_BACKWARDS);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT create plan\n");
|
||||
#ifdef DEFAULT_NEON
|
||||
char *ptr = (char *)config_get_if();
|
||||
if (ptr == NULL) { // phy simulators, config module possibly not loaded
|
||||
uniqCfg = load_configmodule(3, (char **)arg, CONFIG_ENABLECMDLINEONLY);
|
||||
logInit();
|
||||
}
|
||||
shlib_fdesc[0].fname = "dft_implementation";
|
||||
shlib_fdesc[1].fname = "idft_implementation";
|
||||
shlib_fdesc[2].fname = "dfts_start";
|
||||
shlib_fdesc[3].fname = "dfts_stop";
|
||||
int ret = load_module_version_shlib("dfts", "", shlib_fdesc, sizeof(shlib_fdesc) / sizeof(loader_shlibfunc_t), NULL);
|
||||
AssertFatal((ret >= 0), "Error loading dfts decoder");
|
||||
|
||||
dft_neon = (dftfunc_t)shlib_fdesc[0].fptr;
|
||||
idft_neon = (idftfunc_t)shlib_fdesc[1].fptr;
|
||||
dfts_start_neon = (dfts_start_t)shlib_fdesc[2].fptr;
|
||||
dfts_stop_neon = (dfts_stop_t)shlib_fdesc[3].fptr;
|
||||
|
||||
dfts_start_neon();
|
||||
#endif
|
||||
}
|
||||
|
||||
void dfts_stop()
|
||||
{
|
||||
armral_status status;
|
||||
status = armral_fft_destroy_plan_cs16(&idft_256_cs16_plan_p);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT destroy plan\n");
|
||||
status = armral_fft_destroy_plan_cs16(&idft_1024_cs16_plan_p);
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "Failure in ArmRAL FFT destroy plan\n");
|
||||
#ifdef DEFAULT_NEON
|
||||
dfts_stop_neon();
|
||||
#endif
|
||||
}
|
||||
@@ -7126,6 +7126,12 @@ void idft_implementation(uint8_t sizeidx, int16_t *input, int16_t *output, unsig
|
||||
idft_ftab[sizeidx].func(input,output,scale_flag);
|
||||
};
|
||||
|
||||
void dfts_start()
|
||||
{}
|
||||
|
||||
void dfts_stop()
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -630,8 +630,10 @@ void init_fft(uint16_t size,
|
||||
SZ_DEF(65536) \
|
||||
SZ_DEF(98304)
|
||||
|
||||
typedef void(*dftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag);
|
||||
typedef void (*dftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag);
|
||||
typedef void (*idftfunc_t)(uint8_t sizeidx, int16_t *sigF, int16_t *sig, unsigned char scale_flag);
|
||||
typedef void (*dfts_start_t)();
|
||||
typedef void (*dfts_stop_t)();
|
||||
extern dftfunc_t dft;
|
||||
extern idftfunc_t idft;
|
||||
int load_dftslib(void);
|
||||
|
||||
Reference in New Issue
Block a user