mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-15 21:50:27 +00:00
Compare commits
2 Commits
pre-commit
...
polar-armr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29a5df9af6 | ||
|
|
282f4140a3 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -2,3 +2,6 @@
|
||||
path = openair2/E2AP/flexric
|
||||
url = https://gitlab.eurecom.fr/mosaic5g/flexric.git
|
||||
branch = remotes/origin/service-models-integration
|
||||
[submodule "openair1/armRAL_PHY/ral"]
|
||||
path = openair1/armRAL_PHY/ral
|
||||
url = https://gitlab.arm.com/networking/ral/
|
||||
|
||||
@@ -588,7 +588,8 @@ include_directories("${OPENAIR2_DIR}/UTIL/MATH")
|
||||
include_directories("${OPENAIR2_DIR}/UTIL/OTG")
|
||||
include_directories("${OPENAIR2_DIR}/UTIL/OPT")
|
||||
include_directories("${OPENAIR_DIR}")
|
||||
|
||||
include_directories("${OPENAIR1_DIR}/armRAL_PHY/ral/include")
|
||||
include_directories("${OPENAIR1_DIR}/armRAL_PHY/ral")
|
||||
###########
|
||||
# Utilities
|
||||
###############
|
||||
@@ -778,7 +779,10 @@ set(PHY_POLARSRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_matrix_and_array.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_procedures.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_sequence_pattern.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/ral_polar_encoder.cpp
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/ral_polar_decoder.cpp
|
||||
)
|
||||
|
||||
set(PHY_SMALLBLOCKSRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrSmallBlock/encodeSmallBlock.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrSmallBlock/decodeSmallBlock.c
|
||||
@@ -1047,15 +1051,37 @@ target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE
|
||||
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
|
||||
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
|
||||
|
||||
# armral :
|
||||
|
||||
add_library(armral SHARED IMPORTED)
|
||||
set_target_properties(armral PROPERTIES
|
||||
IMPORTED_LOCATION "${OPENAIR1_DIR}/armRAL_PHY/ral/build/libarmral.so"
|
||||
)
|
||||
|
||||
add_library(armral_utils SHARED IMPORTED)
|
||||
set_target_properties(armral_utils PROPERTIES
|
||||
IMPORTED_LOCATION "${OPENAIR1_DIR}/armRAL_PHY/ral/build/libarmral_utils.so"
|
||||
)
|
||||
|
||||
##################################
|
||||
|
||||
add_library(PHY_NR ${PHY_NR_SRC})
|
||||
target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5)
|
||||
#target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5)
|
||||
#target_include_directories(PHY_NR PRIVATE
|
||||
# "${OPENAIR1_DIR}/armRAL_PHY/ral/include"
|
||||
#)
|
||||
|
||||
target_link_libraries(PHY_NR PRIVATE nr_phy_common nr_common nr_fapi_p5 armral armral_utils)
|
||||
|
||||
#############################
|
||||
|
||||
add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC})
|
||||
target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common)
|
||||
target_compile_definitions(PHY_NR_NO_AVX_256 PUBLIC USE_128BIT)
|
||||
|
||||
add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
|
||||
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL)
|
||||
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL armral armral_utils)
|
||||
#target_include_directories(PHY_NR_UE PRIVATE ${OPENAIR1_DIR}/armRAL_PHY/ral/include)
|
||||
|
||||
add_library(PHY_RU ${PHY_SRC_RU})
|
||||
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL)
|
||||
@@ -1925,6 +1951,20 @@ add_executable(rftest
|
||||
target_link_libraries(rftest PRIVATE minimal_lib PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader)
|
||||
target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
|
||||
# armral:
|
||||
|
||||
#include_directories("${OPENAIR1_DIR}/armRAL_PHY/ral/include")
|
||||
|
||||
#add_library(armral SHARED IMPORTED)
|
||||
#set_target_properties(armral PROPERTIES
|
||||
# IMPORTED_LOCATION "${OPENAIR1_DIR}/armRAL_PHY/ral/build/libarmral.so"
|
||||
#)
|
||||
#add_library(armral_utils SHARED IMPORTED)
|
||||
#set_target_properties(armral_utils PROPERTIES
|
||||
# IMPORTED_LOCATION "${OPENAIR1_DIR}/armRAL_PHY/ral/build/libarmral_utils.so"
|
||||
#)
|
||||
###############################
|
||||
add_executable(polartest
|
||||
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c
|
||||
)
|
||||
|
||||
@@ -107,6 +107,7 @@ check_supported_distribution() {
|
||||
"ubuntu22.04") return 0 ;;
|
||||
"ubuntu20.04") return 0 ;;
|
||||
"debian11") return 0 ;;
|
||||
"fedora43") return 0 ;;
|
||||
"fedora41") return 0 ;;
|
||||
"fedora40") return 0 ;;
|
||||
"rhel8.2") return 0 ;;
|
||||
|
||||
@@ -23,7 +23,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
// Default simulation values (Aim for iterations = 1000000.)
|
||||
int ret = 1;
|
||||
int decoder_int16 = 0;
|
||||
int decoder_int16 = 1;
|
||||
int itr, iterations = 1000, arguments, polarMessageType = 0; // 0=PBCH, 1=DCI, 2=UCI
|
||||
double SNRstart = -20.0, SNRstop = 0.0, SNRinc = 0.5; // dB
|
||||
double SNR, SNR_lin;
|
||||
@@ -33,13 +33,14 @@ int main(int argc, char *argv[])
|
||||
uint16_t blockErrorCumulative = 0, bitErrorCumulative = 0;
|
||||
uint8_t aggregation_level = 8, decoderListSize = 8, logFlag = 0;
|
||||
uint16_t rnti = 0;
|
||||
int armral_mode = 1; // default: disabled
|
||||
|
||||
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
|
||||
exit_fun("[POLARTEST] Error, configuration module init failed\n");
|
||||
}
|
||||
logInit();
|
||||
|
||||
while ((arguments = getopt(argc, argv, "--:O:s:d:f:m:i:l:a:p:hqgFL:k:")) != -1) {
|
||||
while ((arguments = getopt(argc, argv, "--:O:s:d:f:m:i:l:a:p:hqgFL:k:A:")) != -1) {
|
||||
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
|
||||
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
|
||||
if (arguments == 1 || arguments == '-' || arguments == 'O')
|
||||
@@ -61,7 +62,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
polarMessageType = atoi(optarg);
|
||||
polarMessageType = atof(optarg);
|
||||
if (polarMessageType != 0 && polarMessageType != 1 && polarMessageType != 2)
|
||||
printf("Illegal polar message type %d (should be 0,1 or 2)\n", polarMessageType);
|
||||
break;
|
||||
@@ -114,6 +115,11 @@ int main(int argc, char *argv[])
|
||||
exit(-1);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
armral_mode = atoi(optarg);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
perror("[polartest.c] Problem at argument parsing with getopt");
|
||||
exit(-1);
|
||||
@@ -260,7 +266,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
start_meas(&timeEncoder);
|
||||
if (decoder_int16 == 1) {
|
||||
polar_encoder_fast((uint64_t *)testInput, encoderOutput, 0, 0, polarMessageType, testLength, aggregation_level);
|
||||
polar_encoder_fast((uint64_t *)testInput, encoderOutput, 0, 0, polarMessageType, testLength, aggregation_level,armral_mode);
|
||||
// polar_encoder_fast((uint64_t*)testInput, (uint64_t*)encoderOutput,0,0,currentPtr);
|
||||
} else { // 0 --> PBCH, 1 --> DCI, -1 --> UCI
|
||||
if (polarMessageType == 0)
|
||||
@@ -305,7 +311,8 @@ int main(int argc, char *argv[])
|
||||
0,
|
||||
polarMessageType,
|
||||
testLength,
|
||||
aggregation_level);
|
||||
aggregation_level,
|
||||
armral_mode);
|
||||
} else { // 0 --> PBCH, 1 --> DCI, -1 --> UCI
|
||||
if (polarMessageType == 0) {
|
||||
decoderState =
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "assertions.h"
|
||||
|
||||
// #define POLAR_CODING_DEBUG
|
||||
#define USE_ARMRAL_FAST 1
|
||||
|
||||
static inline void updateCrcChecksum2(int xlen,
|
||||
int ylen,
|
||||
@@ -669,12 +670,17 @@ static inline void nr_polar_info_extraction_from_u(uint64_t *Cprime,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint32_t polar_decoder_int16(int16_t *input,
|
||||
uint64_t *out,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
uint16_t messageLength,
|
||||
uint8_t aggregation_level)
|
||||
uint8_t aggregation_level,
|
||||
int armral_mode)
|
||||
{
|
||||
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
|
||||
const uint N = polarParams->N;
|
||||
@@ -690,161 +696,211 @@ uint32_t polar_decoder_int16(int16_t *input,
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
int16_t d_tilde[N];
|
||||
const uint E = polarParams->encoderLength;
|
||||
int16_t inbis[E];
|
||||
int16_t *input_deinterleaved;
|
||||
if (polarParams->i_bil) {
|
||||
for (int i = 0; i < E; i++)
|
||||
inbis[i] = input[polarParams->i_bil_pattern[i]];
|
||||
input_deinterleaved = inbis;
|
||||
} else {
|
||||
input_deinterleaved = input;
|
||||
}
|
||||
switch (armral_mode) {
|
||||
case 1: {
|
||||
|
||||
nr_polar_rate_matching_int16(input_deinterleaved,
|
||||
d_tilde,
|
||||
polarParams->rate_matching_pattern,
|
||||
polarParams->K,
|
||||
N,
|
||||
E,
|
||||
polarParams->i_bil);
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("d: ");
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (i % 4 == 0) {
|
||||
printf(" ");
|
||||
const uint32_t L = 1; // list size
|
||||
|
||||
armral_polar_ibil_type i_bil = polarParams->i_bil;
|
||||
uint8_t decoded_bytes[8];
|
||||
|
||||
armral_status ret = ral_polar_decoder(
|
||||
input, // channelOutput_int16
|
||||
polarParams->N,
|
||||
polarParams->encoderLength,
|
||||
polarParams->K,
|
||||
L,
|
||||
i_bil,
|
||||
decoded_bytes
|
||||
);
|
||||
|
||||
//printf("ral status : %d\n", ret);
|
||||
uint64_t tempa = ((uint64_t)decoded_bytes[0] << 56) |
|
||||
((uint64_t)decoded_bytes[1] << 48) |
|
||||
((uint64_t)decoded_bytes[2] << 40) |
|
||||
((uint64_t)decoded_bytes[3] << 32) |
|
||||
((uint64_t)decoded_bytes[4] << 24) |
|
||||
((uint64_t)decoded_bytes[5] << 16) |
|
||||
((uint64_t)decoded_bytes[6] << 8) |
|
||||
((uint64_t)decoded_bytes[7]);
|
||||
|
||||
uint32_t rxcrc = (tempa >> 8) & 0xFFFFFF;
|
||||
|
||||
uint64_t Ar = (uint32_t)(tempa >> 32);
|
||||
out[0] = Ar;
|
||||
uint64_t buffer[2] = {0, 0};
|
||||
buffer[1] = (uint64_t)(*out);
|
||||
uint64_t crc24 = 0;
|
||||
armral_crc24_c_le(16, buffer, &crc24);
|
||||
uint32_t crc = (uint32_t)(crc24 & 0xFFFFFF);
|
||||
polarReturn(polarParams);
|
||||
|
||||
return crc ^ rxcrc;
|
||||
|
||||
break;
|
||||
}
|
||||
printf("%i", d_tilde[i] < 0 ? 1 : 0);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
uint8_t nr_polar_U[N];
|
||||
memset(nr_polar_U, 0, sizeof(nr_polar_U));
|
||||
memcpy(treeAlpha(polarParams->decoder.root), d_tilde, sizeof(d_tilde));
|
||||
generic_polar_decoder(polarParams, polarParams->decoder.root, nr_polar_U);
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("u: ");
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (i % 4 == 0) {
|
||||
printf(" ");
|
||||
case 0: {
|
||||
int16_t d_tilde[N];
|
||||
const uint E = polarParams->encoderLength;
|
||||
int16_t inbis[E];
|
||||
int16_t *input_deinterleaved;
|
||||
if (polarParams->i_bil) {
|
||||
for (int i = 0; i < E; i++)
|
||||
inbis[i] = input[polarParams->i_bil_pattern[i]];
|
||||
input_deinterleaved = inbis;
|
||||
} else {
|
||||
input_deinterleaved = input;
|
||||
}
|
||||
|
||||
nr_polar_rate_matching_int16(input_deinterleaved,
|
||||
d_tilde,
|
||||
polarParams->rate_matching_pattern,
|
||||
polarParams->K,
|
||||
N,
|
||||
E,
|
||||
polarParams->i_bil);
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("d: ");
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (i % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("%i", d_tilde[i] < 0 ? 1 : 0);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
uint8_t nr_polar_U[N];
|
||||
memset(nr_polar_U, 0, sizeof(nr_polar_U));
|
||||
memcpy(treeAlpha(polarParams->decoder.root), d_tilde, sizeof(d_tilde));
|
||||
generic_polar_decoder(polarParams, polarParams->decoder.root, nr_polar_U);
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("u: ");
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (i % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("%i", nr_polar_U[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
// Extract the information bits (û to ĉ)
|
||||
uint64_t B[4] = {0};
|
||||
nr_polar_info_extraction_from_u(B,
|
||||
nr_polar_U,
|
||||
polarParams->information_bit_pattern,
|
||||
polarParams->parity_check_bit_pattern,
|
||||
polarParams->interleaving_pattern,
|
||||
N,
|
||||
polarParams->n_pc,
|
||||
polarParams->K);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("c: ");
|
||||
for (int n = 0; n < polarParams->K; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (B[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
int len = polarParams->payloadBits;
|
||||
// int len_mod64=len&63;
|
||||
int crclen = polarParams->crcParityBits;
|
||||
uint64_t rxcrc = B[0] & ((1 << crclen) - 1);
|
||||
uint32_t crc = 0;
|
||||
uint64_t Ar = 0;
|
||||
AssertFatal(len < 65, "A must be less than 65 bits\n");
|
||||
|
||||
// appending 24 ones before a0 for DCI as stated in 38.212 7.3.2
|
||||
uint8_t offset = 0;
|
||||
if (ones_flag)
|
||||
offset = 3;
|
||||
|
||||
if (len <= 32) {
|
||||
Ar = (uint32_t)(B[0] >> crclen);
|
||||
uint8_t A32_flip[4 + offset];
|
||||
if (ones_flag) {
|
||||
A32_flip[0] = 0xff;
|
||||
A32_flip[1] = 0xff;
|
||||
A32_flip[2] = 0xff;
|
||||
}
|
||||
uint32_t Aprime = (uint32_t)(Ar << (32 - len));
|
||||
A32_flip[0 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A32_flip[1 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A32_flip[2 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A32_flip[3 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (crclen == 24)
|
||||
crc = (uint64_t)((crc24c(A32_flip, 8 * offset + len) >> 8) & 0xffffff);
|
||||
else if (crclen == 11)
|
||||
crc = (uint64_t)((crc11(A32_flip, 8 * offset + len) >> 21) & 0x7ff);
|
||||
else if (crclen == 6)
|
||||
crc = (uint64_t)((crc6(A32_flip, 8 * offset + len) >> 26) & 0x3f);
|
||||
} else if (len <= 64) {
|
||||
Ar = (B[0] >> crclen) | (B[1] << (64 - crclen));
|
||||
uint8_t A64_flip[8 + offset];
|
||||
if (ones_flag) {
|
||||
A64_flip[0] = 0xff;
|
||||
A64_flip[1] = 0xff;
|
||||
A64_flip[2] = 0xff;
|
||||
}
|
||||
uint64_t Aprime = (uint64_t)(Ar << (64 - len));
|
||||
A64_flip[0 + offset] = ((uint8_t *)&Aprime)[7];
|
||||
A64_flip[1 + offset] = ((uint8_t *)&Aprime)[6];
|
||||
A64_flip[2 + offset] = ((uint8_t *)&Aprime)[5];
|
||||
A64_flip[3 + offset] = ((uint8_t *)&Aprime)[4];
|
||||
A64_flip[4 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A64_flip[5 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A64_flip[6 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A64_flip[7 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (crclen == 24)
|
||||
crc = (uint64_t)(crc24c(A64_flip, 8 * offset + len) >> 8) & 0xffffff;
|
||||
else if (crclen == 11)
|
||||
crc = (uint64_t)(crc11(A64_flip, 8 * offset + len) >> 21) & 0x7ff;
|
||||
else if (crclen == 6)
|
||||
crc = (uint64_t)(crc6(A64_flip, 8 * offset + len) >> 26) & 0x3f;
|
||||
}
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
int A_array = (len + 63) >> 6;
|
||||
printf("a: ");
|
||||
for (int n = 0; n < len; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
int alen = n1 == 0 ? len - (A_array << 6) : 64;
|
||||
printf("%lu", (Ar >> (alen - 1 - n2)) & 1);
|
||||
}
|
||||
printf("\n\n");
|
||||
#endif
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("A %lx B %lx|%lx Cprime %lx|%lx (crc %x,rxcrc %lx, XOR %lx, bits%d)\n",
|
||||
Ar,
|
||||
B[1],
|
||||
B[0],
|
||||
Cprime[1],
|
||||
Cprime[0],
|
||||
crc,
|
||||
rxcrc,
|
||||
crc ^ rxcrc,
|
||||
polarParams->payloadBits);
|
||||
#endif
|
||||
|
||||
out[0] = Ar;
|
||||
polarReturn(polarParams);
|
||||
|
||||
return crc ^ rxcrc;
|
||||
|
||||
break;
|
||||
}
|
||||
printf("%i", nr_polar_U[i]);
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
// Extract the information bits (û to ĉ)
|
||||
uint64_t B[4] = {0};
|
||||
nr_polar_info_extraction_from_u(B,
|
||||
nr_polar_U,
|
||||
polarParams->information_bit_pattern,
|
||||
polarParams->parity_check_bit_pattern,
|
||||
polarParams->interleaving_pattern,
|
||||
N,
|
||||
polarParams->n_pc,
|
||||
polarParams->K);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("c: ");
|
||||
for (int n = 0; n < polarParams->K; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (B[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
int len = polarParams->payloadBits;
|
||||
// int len_mod64=len&63;
|
||||
int crclen = polarParams->crcParityBits;
|
||||
uint64_t rxcrc = B[0] & ((1 << crclen) - 1);
|
||||
uint32_t crc = 0;
|
||||
uint64_t Ar = 0;
|
||||
AssertFatal(len < 65, "A must be less than 65 bits\n");
|
||||
|
||||
// appending 24 ones before a0 for DCI as stated in 38.212 7.3.2
|
||||
uint8_t offset = 0;
|
||||
if (ones_flag)
|
||||
offset = 3;
|
||||
|
||||
if (len <= 32) {
|
||||
Ar = (uint32_t)(B[0] >> crclen);
|
||||
uint8_t A32_flip[4 + offset];
|
||||
if (ones_flag) {
|
||||
A32_flip[0] = 0xff;
|
||||
A32_flip[1] = 0xff;
|
||||
A32_flip[2] = 0xff;
|
||||
}
|
||||
uint32_t Aprime = (uint32_t)(Ar << (32 - len));
|
||||
A32_flip[0 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A32_flip[1 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A32_flip[2 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A32_flip[3 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (crclen == 24)
|
||||
crc = (uint64_t)((crc24c(A32_flip, 8 * offset + len) >> 8) & 0xffffff);
|
||||
else if (crclen == 11)
|
||||
crc = (uint64_t)((crc11(A32_flip, 8 * offset + len) >> 21) & 0x7ff);
|
||||
else if (crclen == 6)
|
||||
crc = (uint64_t)((crc6(A32_flip, 8 * offset + len) >> 26) & 0x3f);
|
||||
} else if (len <= 64) {
|
||||
Ar = (B[0] >> crclen) | (B[1] << (64 - crclen));
|
||||
uint8_t A64_flip[8 + offset];
|
||||
if (ones_flag) {
|
||||
A64_flip[0] = 0xff;
|
||||
A64_flip[1] = 0xff;
|
||||
A64_flip[2] = 0xff;
|
||||
}
|
||||
uint64_t Aprime = (uint64_t)(Ar << (64 - len));
|
||||
A64_flip[0 + offset] = ((uint8_t *)&Aprime)[7];
|
||||
A64_flip[1 + offset] = ((uint8_t *)&Aprime)[6];
|
||||
A64_flip[2 + offset] = ((uint8_t *)&Aprime)[5];
|
||||
A64_flip[3 + offset] = ((uint8_t *)&Aprime)[4];
|
||||
A64_flip[4 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A64_flip[5 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A64_flip[6 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A64_flip[7 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (crclen == 24)
|
||||
crc = (uint64_t)(crc24c(A64_flip, 8 * offset + len) >> 8) & 0xffffff;
|
||||
else if (crclen == 11)
|
||||
crc = (uint64_t)(crc11(A64_flip, 8 * offset + len) >> 21) & 0x7ff;
|
||||
else if (crclen == 6)
|
||||
crc = (uint64_t)(crc6(A64_flip, 8 * offset + len) >> 26) & 0x3f;
|
||||
}
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
int A_array = (len + 63) >> 6;
|
||||
printf("a: ");
|
||||
for (int n = 0; n < len; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
int alen = n1 == 0 ? len - (A_array << 6) : 64;
|
||||
printf("%lu", (Ar >> (alen - 1 - n2)) & 1);
|
||||
}
|
||||
printf("\n\n");
|
||||
#endif
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("A %lx B %lx|%lx Cprime %lx|%lx (crc %x,rxcrc %lx, XOR %lx, bits%d)\n",
|
||||
Ar,
|
||||
B[1],
|
||||
B[0],
|
||||
Cprime[1],
|
||||
Cprime[0],
|
||||
crc,
|
||||
rxcrc,
|
||||
crc ^ rxcrc,
|
||||
polarParams->payloadBits);
|
||||
#endif
|
||||
|
||||
out[0] = Ar;
|
||||
|
||||
polarReturn(polarParams);
|
||||
return crc ^ rxcrc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include "armral.h"
|
||||
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h"
|
||||
@@ -146,7 +147,8 @@ void polar_encoder_fast(uint64_t *A,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
uint16_t messageLength,
|
||||
uint8_t aggregation_level);
|
||||
uint8_t aggregation_level,
|
||||
int armral_mode);
|
||||
|
||||
int8_t polar_decoder(double *input,
|
||||
uint32_t *output,
|
||||
@@ -160,7 +162,8 @@ uint32_t polar_decoder_int16(int16_t *input,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
uint16_t messageLength,
|
||||
uint8_t aggregation_level);
|
||||
uint8_t aggregation_level,
|
||||
int armral_mode);
|
||||
|
||||
int8_t polar_decoder_dci(double *input,
|
||||
uint32_t *out,
|
||||
@@ -337,3 +340,99 @@ static inline void polarReturn(t_nrPolar_params *polarParams)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Polar encoder Declaration
|
||||
// ------------------------------------------------------
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Complete 5G NR Polar encoder pipeline:
|
||||
* CRC attachment → frozen mask → interleave → encode → rate-match.
|
||||
*
|
||||
* @param data_in_bits Input raw bits (payload only, without CRC). Size = (K-L)/8 bytes.
|
||||
* @param K Total number of bits after CRC attachment.
|
||||
* @param E Number of bits after rate-matching.
|
||||
* @param N Polar code length (power of 2, 32 ≤ N ≤ 1024).
|
||||
* @param i_bil Enable/disable interleaving (IBIL).
|
||||
* @param data_crc_bits Buffer for K bits after CRC. Size = (K+7)/8.
|
||||
* @param frozen_mask Buffer for frozen mask. Size = N bytes.
|
||||
* @param data_interleaved Buffer for interleaved bits. Size = N bits packed.
|
||||
* @param data_encoded_bytes Buffer for encoded bits. Size = N bits packed.
|
||||
* @param data_out_bits Buffer for output bits after rate-matching. Size = E bits packed.
|
||||
*
|
||||
* @return armral_status Returns ARMRAL_SUCCESS on success.
|
||||
*/
|
||||
armral_status ral_polar_encoder(
|
||||
const uint8_t *data_in,
|
||||
uint32_t K,
|
||||
uint32_t E,
|
||||
uint32_t N,
|
||||
armral_polar_ibil_type i_bil,
|
||||
uint8_t *data_crc,
|
||||
uint8_t *frozen_mask,
|
||||
uint8_t *data_interleaved,
|
||||
uint8_t *data_encoded,
|
||||
uint8_t *data_out
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Polar decoder declaration
|
||||
// ------------------------------------------------------
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Complete 5G NR Polar decoder pipeline:
|
||||
* Rate-recovery → polar decode (SCL/L) → deinterleave → CRC check.
|
||||
*
|
||||
* This function attempts to decode L codewords using SCL decoding.
|
||||
* It stops early and returns ARMRAL_SUCCESS if a CRC pass is obtained
|
||||
* for any of the L paths.
|
||||
*
|
||||
* @param N Polar code length (power of 2, 32 ≤ N ≤ 1024).
|
||||
* @param K Number of information bits (including CRC).
|
||||
* @param E Number of rate-matched bits (demodulated inputs).
|
||||
* @param i_bil IBIL flag (interleaving used during RM).
|
||||
* @param L List size for SCL decoding.
|
||||
*
|
||||
* @param frozen_mask Frozen bits mask. Size = N bytes.
|
||||
*
|
||||
* @param data_demod_soft Input LLRs after demodulator (size: E bytes).
|
||||
*
|
||||
* @param data_recovered Output buffer for rate-recovered LLRs
|
||||
* (size: N bytes).
|
||||
*
|
||||
* @param data_decoded_bits Output buffer for decoded bits (size: N bits × L).
|
||||
* Bits are packed (N/8 per codeword).
|
||||
*
|
||||
* @param data_deint0 Scratch buffer for deinterleaving first path.
|
||||
* Size = ceil(K/8) bytes.
|
||||
*
|
||||
* @param data_deint Scratch buffer for deinterleaving paths 1..L−1.
|
||||
* Size = ceil(K/8) bytes.
|
||||
*
|
||||
* @return armral_status Returns ARMRAL_SUCCESS if decoding completed
|
||||
* (including CRC early stop). Non-zero on failure.
|
||||
*/
|
||||
armral_status ral_polar_decoder(
|
||||
const int16_t *input_llr16,
|
||||
uint32_t N,
|
||||
uint32_t E,
|
||||
uint32_t K,
|
||||
uint32_t L,
|
||||
armral_polar_ibil_type i_bil,
|
||||
uint8_t *decoded_out
|
||||
);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
// #define DEBUG_POLAR_MATLAB
|
||||
// #define POLAR_CODING_DEBUG
|
||||
|
||||
#define USE_ARMRAL_FAST 1
|
||||
#define USE_ARMRAL_SLOW 0
|
||||
#define USE_ARMRAL_DCI 0
|
||||
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
#include "assertions.h"
|
||||
#include <stdint.h>
|
||||
@@ -46,10 +50,13 @@ void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t mes
|
||||
{
|
||||
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
|
||||
uint8_t nr_polar_A[polarParams->payloadBits];
|
||||
|
||||
nr_bit2byte_uint32_8(in, polarParams->payloadBits, nr_polar_A);
|
||||
|
||||
/*
|
||||
* Bytewise operations
|
||||
*/
|
||||
|
||||
// Calculate CRC.
|
||||
uint8_t nr_polar_crc[polarParams->crcParityBits];
|
||||
nr_matrix_multiplication_uint8_1D_uint8_2D(nr_polar_A,
|
||||
@@ -61,12 +68,15 @@ void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t mes
|
||||
for (uint i = 0; i < polarParams->crcParityBits; i++)
|
||||
nr_polar_crc[i] %= 2;
|
||||
|
||||
|
||||
uint8_t nr_polar_B[polarParams->K];
|
||||
|
||||
// Attach CRC to the Transport Block. (a to b)
|
||||
memcpy(nr_polar_B, nr_polar_A, polarParams->payloadBits);
|
||||
for (uint i = polarParams->payloadBits; i < polarParams->K; i++)
|
||||
nr_polar_B[i] = nr_polar_crc[i - (polarParams->payloadBits)];
|
||||
|
||||
|
||||
#ifdef DEBUG_POLAR_ENCODER
|
||||
uint64_t B2 = 0;
|
||||
|
||||
@@ -96,6 +106,7 @@ void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t mes
|
||||
#endif
|
||||
// Bit insertion (c' to u)
|
||||
uint8_t nr_polar_U[polarParams->N];
|
||||
|
||||
nr_polar_bit_insertion(nr_polar_CPrime,
|
||||
nr_polar_U,
|
||||
polarParams->N,
|
||||
@@ -103,7 +114,9 @@ void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t mes
|
||||
polarParams->Q_I_N,
|
||||
polarParams->Q_PC_N,
|
||||
polarParams->n_pc);
|
||||
|
||||
uint8_t nr_polar_D[polarParams->N];
|
||||
|
||||
nr_matrix_multiplication_uint8_1D_uint8_2D(nr_polar_U, polarParams->G_N, nr_polar_D, polarParams->N, polarParams->N);
|
||||
|
||||
for (uint i = 0; i < polarParams->N; i++)
|
||||
@@ -111,6 +124,7 @@ void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t mes
|
||||
|
||||
uint64_t D[8];
|
||||
memset(D, 0, sizeof(D));
|
||||
|
||||
#ifdef DEBUG_POLAR_ENCODER
|
||||
|
||||
for (int i = 0; i < polarParams->N; i++)
|
||||
@@ -133,6 +147,149 @@ void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t mes
|
||||
#endif
|
||||
nr_byte2bit_uint8_32(nr_polar_E, polarParams->encoderLength, out);
|
||||
|
||||
#if USE_ARMRAL_SLOW
|
||||
// Entrée bit-dépackée (1 bit par octet)
|
||||
// uint8_t *armral_in = (uint8_t *)calloc(polarParams->payloadBits, sizeof(uint8_t));
|
||||
|
||||
uint8_t *armral_in = (uint8_t *)calloc((polarParams->payloadBits + 7)/8, sizeof(uint8_t));
|
||||
|
||||
|
||||
// CRC attachment output (packé MSB-first, payload + CRC)
|
||||
uint8_t *armral_B = (uint8_t *)calloc((polarParams->K + 7) / 8, sizeof(uint8_t));
|
||||
|
||||
// Frozen mask : 1 octet par bit
|
||||
uint8_t *armral_frozen_mask = (uint8_t *)calloc(polarParams->N, sizeof(uint8_t));
|
||||
|
||||
// Interleaved bits (bit-dépacké)
|
||||
uint8_t *armral_CPrime = (uint8_t *)calloc(polarParams->K, sizeof(uint8_t));
|
||||
|
||||
// Interleaved bytes pour encodeur
|
||||
uint32_t *armral_out = (uint32_t *)calloc(polarParams->encoderLength, sizeof(uint32_t));
|
||||
|
||||
// Encode block output (octets packés)
|
||||
uint8_t *armral_D = (uint8_t *)calloc(polarParams->N, sizeof(uint8_t));
|
||||
// Rate-matched / final output
|
||||
uint8_t *armral_E = (uint8_t *)calloc(polarParams->encoderLength, sizeof(uint8_t));
|
||||
|
||||
// uint8_t nr_polar_E[polarParams->encoderLength];
|
||||
|
||||
// Remplir armral_in avec tes bits, packés MSB-first
|
||||
for (uint32_t i = 0; i < polarParams->payloadBits ; ++i) {
|
||||
uint32_t word_idx = i / 32;
|
||||
uint32_t bit_idx = i % 32;
|
||||
uint8_t bit = (in[word_idx] >> bit_idx) & 0x1;
|
||||
|
||||
uint32_t byte_ind = i / 8;
|
||||
uint32_t idx = 7 - (i % 8);
|
||||
armral_in[byte_ind] |= bit << idx;
|
||||
}
|
||||
|
||||
|
||||
armral_status status = ral_polar_encoder(
|
||||
armral_in,
|
||||
polarParams->K,
|
||||
polarParams->encoderLength,
|
||||
polarParams->N,
|
||||
polarParams->i_bil,
|
||||
armral_B,
|
||||
armral_frozen_mask,
|
||||
armral_CPrime,
|
||||
armral_D,
|
||||
armral_E
|
||||
);
|
||||
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "armRAL polar encoder failed\n");
|
||||
|
||||
|
||||
nr_byte2bit_uint8_32(armral_E, polarParams->encoderLength, armral_out);
|
||||
|
||||
printf("Encoder output (first 64 bits):\n");
|
||||
for (int i = 0; i < polarParams->encoderLength && i < 64; i++) {
|
||||
printf("%u ", out[i]);
|
||||
if ((i+1) % 8 == 0) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
printf("=== armRAL buffers ===\n");
|
||||
|
||||
// Print input bits
|
||||
printf("armral_in:\n");
|
||||
for (int i = 0; i < polarParams->payloadBits; i++) {
|
||||
printf("%u ", armral_in[i]);
|
||||
if ((i+1) % 32 == 0) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Print CRC bits / B
|
||||
printf("armral_B:\n");
|
||||
for (int i = 0; i < polarParams->K; i++) {
|
||||
printf("%u ", armral_B[i]);
|
||||
if ((i+1) % 32 == 0) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Print frozen mask
|
||||
printf("armral_frozen_mask:\n");
|
||||
for (int i = 0; i < polarParams->N; i++) {
|
||||
printf("%u ", armral_frozen_mask[i]);
|
||||
if ((i+1) % 32 == 0) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Print interleaved bits
|
||||
printf("armral_CPrime:\n");
|
||||
for (int i = 0; i < polarParams->N; i++) {
|
||||
printf("%u ", armral_CPrime[i]);
|
||||
//if ((i+1) % 32 == 0) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
||||
// Print encoded bits (D)
|
||||
printf("armral_D:\n");
|
||||
for (int i = 0; i < polarParams->N; i++) {
|
||||
printf("%u ", armral_D[i]);
|
||||
//if ((i+1) % 32 == 0) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Print final output bits
|
||||
printf("armral_E:\n");
|
||||
for (int i = 0; i < polarParams->encoderLength; i++) {
|
||||
printf("%u ", armral_E[i]);
|
||||
if ((i+1) % 32 == 0) printf("\n");
|
||||
}
|
||||
printf("====================\n");
|
||||
free(armral_in);
|
||||
free(armral_B);
|
||||
free(armral_frozen_mask);
|
||||
free(armral_out);
|
||||
free(armral_D);
|
||||
free(armral_CPrime);
|
||||
free(armral_E);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
uint8_t *frozen_mask = calloc(polarParams->N, sizeof(uint8_t));
|
||||
|
||||
ral_polar_encoder(
|
||||
in,
|
||||
polarParams->K,
|
||||
polarParams->encoderLength,
|
||||
polarParams->N,
|
||||
polarParams->i_bil,
|
||||
nr_polar_B,
|
||||
frozen_mask,
|
||||
nr_polar_CPrime,
|
||||
nr_polar_E,
|
||||
nr_polar_D,
|
||||
out
|
||||
);
|
||||
// free(frozen_mask);
|
||||
*/
|
||||
return;
|
||||
#endif
|
||||
|
||||
polarReturn(polarParams);
|
||||
}
|
||||
|
||||
@@ -247,6 +404,77 @@ void polar_encoder_dci(uint32_t *in,
|
||||
for (int i = 0; i < outputInd; i++)
|
||||
printf("[%d]->0x%08x\t", i, out[i]);
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_ARMRAL_DCI
|
||||
// Entrée bit-dépackée (1 bit par octet)
|
||||
// uint8_t *armral_in = (uint8_t *)calloc(polarParams->payloadBits, sizeof(uint8_t));
|
||||
|
||||
uint8_t *armral_in = (uint8_t *)calloc((polarParams->payloadBits + 7)/8, sizeof(uint8_t));
|
||||
|
||||
|
||||
// CRC attachment output (packé MSB-first, payload + CRC)
|
||||
uint8_t *armral_B = (uint8_t *)calloc((polarParams->K + 7) / 8, sizeof(uint8_t));
|
||||
|
||||
// Frozen mask : 1 octet par bit
|
||||
uint8_t *armral_frozen_mask = (uint8_t *)calloc(polarParams->N, sizeof(uint8_t));
|
||||
|
||||
// Interleaved bits (bit-dépacké)
|
||||
uint8_t *armral_CPrime = (uint8_t *)calloc(polarParams->K, sizeof(uint8_t));
|
||||
|
||||
// Interleaved bytes pour encodeur
|
||||
uint32_t *armral_out = (uint32_t *)calloc(polarParams->encoderLength, sizeof(uint32_t));
|
||||
|
||||
// Encode block output (octets packés)
|
||||
uint8_t *armral_D = (uint8_t *)calloc(polarParams->N, sizeof(uint8_t));
|
||||
// Rate-matched / final output
|
||||
uint8_t *armral_E = (uint8_t *)calloc(polarParams->encoderLength, sizeof(uint8_t));
|
||||
|
||||
// uint8_t nr_polar_E[polarParams->encoderLength];
|
||||
|
||||
// Remplir armral_in avec tes bits, packés MSB-first
|
||||
for (uint32_t i = 0; i < polarParams->payloadBits ; ++i) {
|
||||
uint32_t word_idx = i / 32;
|
||||
uint32_t bit_idx = i % 32;
|
||||
uint8_t bit = (in[word_idx] >> bit_idx) & 0x1;
|
||||
|
||||
uint32_t byte_ind = i / 8;
|
||||
uint32_t idx = 7 - (i % 8);
|
||||
armral_in[byte_ind] |= bit << idx;
|
||||
}
|
||||
|
||||
|
||||
armral_status status = ral_polar_encoder(
|
||||
armral_in,
|
||||
polarParams->K,
|
||||
polarParams->encoderLength,
|
||||
polarParams->N,
|
||||
polarParams->i_bil,
|
||||
armral_B,
|
||||
armral_frozen_mask,
|
||||
armral_CPrime,
|
||||
armral_D,
|
||||
armral_E
|
||||
);
|
||||
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "armRAL polar encoder failed\n");
|
||||
|
||||
|
||||
nr_byte2bit_uint8_32(armral_E, polarParams->encoderLength, armral_out);
|
||||
|
||||
|
||||
printf("====================\n");
|
||||
free(armral_in);
|
||||
free(armral_B);
|
||||
free(armral_frozen_mask);
|
||||
free(armral_out);
|
||||
free(armral_D);
|
||||
free(armral_CPrime);
|
||||
free(armral_E);
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
polarReturn(polarParams);
|
||||
}
|
||||
|
||||
@@ -474,7 +702,8 @@ void polar_encoder_fast(uint64_t *A,
|
||||
uint8_t ones_flag,
|
||||
int8_t messageType,
|
||||
uint16_t messageLength,
|
||||
uint8_t aggregation_level)
|
||||
uint8_t aggregation_level,
|
||||
int armral_mode)
|
||||
{
|
||||
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
|
||||
|
||||
@@ -512,195 +741,246 @@ void polar_encoder_fast(uint64_t *A,
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
switch (armral_mode) {
|
||||
case 1:
|
||||
{
|
||||
size_t size_in = (polarParams->payloadBits + 7)/8;
|
||||
size_t size_B = (polarParams->K + 7)/8;
|
||||
size_t size_frozen = polarParams->N;
|
||||
size_t size_CPrime = polarParams->K;
|
||||
size_t size_D = polarParams->N;
|
||||
size_t size_Invalid = polarParams->N;
|
||||
size_t size_E = polarParams->encoderLength;
|
||||
|
||||
uint64_t tcrc = 0;
|
||||
uint offset = 0;
|
||||
size_t total = size_in + size_B + size_frozen + size_CPrime +
|
||||
size_D + size_Invalid + size_E;
|
||||
uint8_t base[total];
|
||||
uint8_t *armral_in=base;
|
||||
uint8_t *armral_B = armral_in + size_in;
|
||||
uint8_t *armral_frozen_mask = armral_B + size_B;
|
||||
uint8_t *armral_CPrime = armral_frozen_mask + size_frozen;
|
||||
uint8_t *armral_D = armral_CPrime + size_CPrime;
|
||||
uint8_t *armral_Invalid = armral_D + size_D;
|
||||
uint8_t *armral_E = armral_Invalid + size_Invalid;
|
||||
|
||||
// appending 24 ones before a0 for DCI as stated in 38.212 7.3.2
|
||||
if (ones_flag)
|
||||
offset = 3;
|
||||
|
||||
// A bit string should be stored as 0, 0, ..., 0, a'_0, a'_1, ..., a'_A-1,
|
||||
//???a'_{N-1} a'_{N-2} ... a'_{N-A} 0 .... 0, where N=64,128,192,..., N is smallest multiple of 64 greater than or equal to A
|
||||
|
||||
// First flip A bitstring byte endian for CRC routines (optimized for DLSCH/ULSCH, not PBCH/PDCCH)
|
||||
// CRC reads in each byte in bit positions 7 down to 0, for PBCH/PDCCH we need to read in a_{A-1} down to a_{0}, A = length of bit
|
||||
// string (e.g. 32 for PBCH)
|
||||
if (bitlen <= 32) {
|
||||
uint8_t A32_flip[4 + offset];
|
||||
if (ones_flag) {
|
||||
A32_flip[0] = 0xff;
|
||||
A32_flip[1] = 0xff;
|
||||
A32_flip[2] = 0xff;
|
||||
|
||||
uint32_t v = __builtin_bswap32((uint32_t)A[0]);
|
||||
memcpy(armral_in, &v, 4);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
armral_status status = ral_polar_encoder(armral_in, polarParams->K, polarParams->encoderLength, polarParams->N, polarParams->i_bil, armral_B, armral_frozen_mask, armral_CPrime, armral_D, armral_E);
|
||||
|
||||
AssertFatal(status == ARMRAL_SUCCESS, "armRAL polar encoder failed\n");
|
||||
|
||||
|
||||
int nbytes = (polarParams->encoderLength + 7) / 8;
|
||||
memcpy(out, armral_E, nbytes);
|
||||
// tempa
|
||||
|
||||
|
||||
polarReturn(polarParams);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
uint32_t Aprime = (uint32_t)(((uint32_t)*A) << (32 - bitlen));
|
||||
A32_flip[0 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A32_flip[1 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A32_flip[2 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A32_flip[3 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (polarParams->crcParityBits == 24)
|
||||
tcrc = (uint64_t)(((crcmask ^ (crc24c(A32_flip, 8 * offset + bitlen) >> 8))) & 0xffffff);
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)(((crcmask ^ (crc11(A32_flip, bitlen) >> 21))) & 0x7ff);
|
||||
else if (polarParams->crcParityBits == 6)
|
||||
tcrc = (uint64_t)(((crcmask ^ (crc6(A32_flip, bitlen) >> 26))) & 0x3f);
|
||||
} else if (bitlen <= 64) {
|
||||
uint8_t A64_flip[8 + offset];
|
||||
if (ones_flag) {
|
||||
A64_flip[0] = 0xff;
|
||||
A64_flip[1] = 0xff;
|
||||
A64_flip[2] = 0xff;
|
||||
}
|
||||
uint64_t Aprime = (uint64_t)(((uint64_t)*A) << (64 - bitlen));
|
||||
A64_flip[0 + offset] = ((uint8_t *)&Aprime)[7];
|
||||
A64_flip[1 + offset] = ((uint8_t *)&Aprime)[6];
|
||||
A64_flip[2 + offset] = ((uint8_t *)&Aprime)[5];
|
||||
A64_flip[3 + offset] = ((uint8_t *)&Aprime)[4];
|
||||
A64_flip[4 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A64_flip[5 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A64_flip[6 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A64_flip[7 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (polarParams->crcParityBits == 24)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc24c(A64_flip, 8 * offset + bitlen) >> 8))) & 0xffffff;
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc11(A64_flip, bitlen) >> 21))) & 0x7ff;
|
||||
} else if (bitlen <= 128) {
|
||||
uint8_t A128_flip[16 + offset];
|
||||
if (ones_flag) {
|
||||
A128_flip[0] = 0xff;
|
||||
A128_flip[1] = 0xff;
|
||||
A128_flip[2] = 0xff;
|
||||
}
|
||||
uint128_t Aprime = (uint128_t)(((uint128_t)*A) << (128 - bitlen));
|
||||
for (int i = 0; i < 16; i++)
|
||||
A128_flip[i + offset] = ((uint8_t *)&Aprime)[15 - i];
|
||||
if (polarParams->crcParityBits == 24)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc24c(A128_flip, 8 * offset + bitlen) >> 8))) & 0xffffff;
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc11(A128_flip, bitlen) >> 21))) & 0x7ff;
|
||||
}
|
||||
case 0:
|
||||
uint64_t tcrc = 0;
|
||||
uint offset = 0;
|
||||
|
||||
// this is number of quadwords in the bit string
|
||||
int quadwlen = (polarParams->K + 63) / 64;
|
||||
// appending 24 ones before a0 for DCI as stated in 38.212 7.3.2
|
||||
if (ones_flag)
|
||||
offset = 3;
|
||||
|
||||
// Create the B bit string as
|
||||
// 0, 0, ..., 0, a'_0, a'_1, ..., a'_A-1, p_0, p_1, ..., p_{N_parity-1}
|
||||
// A bit string should be stored as 0, 0, ..., 0, a'_0, a'_1, ..., a'_A-1,
|
||||
//???a'_{N-1} a'_{N-2} ... a'_{N-A} 0 .... 0, where N=64,128,192,..., N is smallest multiple of 64 greater than or equal to A
|
||||
|
||||
//??? b_{N'-1} b_{N'-2} ... b_{N'-A} b_{N'-A-1} ... b_{N'-A-Nparity} = a_{N-1} a_{N-2} ... a_{N-A} p_{N_parity-1} ... p_0
|
||||
uint64_t B[4] = {0};
|
||||
B[0] = (A[0] << polarParams->crcParityBits) | tcrc;
|
||||
for (int n = 1; n < quadwlen; n++)
|
||||
if ((bitlen + 63) / 64 > n)
|
||||
B[n] = (A[n] << polarParams->crcParityBits) | (A[n - 1] >> (64 - polarParams->crcParityBits));
|
||||
else
|
||||
B[n] = (A[n - 1] >> (64 - polarParams->crcParityBits));
|
||||
// First flip A bitstring byte endian for CRC routines (optimized for DLSCH/ULSCH, not PBCH/PDCCH)
|
||||
// CRC reads in each byte in bit positions 7 down to 0, for PBCH/PDCCH we need to read in a_{A-1} down to a_{0}, A = length of bit
|
||||
// string (e.g. 32 for PBCH)
|
||||
if (bitlen <= 32) {
|
||||
uint8_t A32_flip[4 + offset];
|
||||
if (ones_flag) {
|
||||
A32_flip[0] = 0xff;
|
||||
A32_flip[1] = 0xff;
|
||||
A32_flip[2] = 0xff;
|
||||
}
|
||||
uint32_t Aprime = (uint32_t)(((uint32_t)*A) << (32 - bitlen));
|
||||
A32_flip[0 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A32_flip[1 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A32_flip[2 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A32_flip[3 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (polarParams->crcParityBits == 24)
|
||||
tcrc = (uint64_t)(((crcmask ^ (crc24c(A32_flip, 8 * offset + bitlen) >> 8))) & 0xffffff);
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)(((crcmask ^ (crc11(A32_flip, bitlen) >> 21))) & 0x7ff);
|
||||
else if (polarParams->crcParityBits == 6)
|
||||
tcrc = (uint64_t)(((crcmask ^ (crc6(A32_flip, bitlen) >> 26))) & 0x3f);
|
||||
} else if (bitlen <= 64) {
|
||||
uint8_t A64_flip[8 + offset];
|
||||
if (ones_flag) {
|
||||
A64_flip[0] = 0xff;
|
||||
A64_flip[1] = 0xff;
|
||||
A64_flip[2] = 0xff;
|
||||
}
|
||||
uint64_t Aprime = (uint64_t)(((uint64_t)*A) << (64 - bitlen));
|
||||
A64_flip[0 + offset] = ((uint8_t *)&Aprime)[7];
|
||||
A64_flip[1 + offset] = ((uint8_t *)&Aprime)[6];
|
||||
A64_flip[2 + offset] = ((uint8_t *)&Aprime)[5];
|
||||
A64_flip[3 + offset] = ((uint8_t *)&Aprime)[4];
|
||||
A64_flip[4 + offset] = ((uint8_t *)&Aprime)[3];
|
||||
A64_flip[5 + offset] = ((uint8_t *)&Aprime)[2];
|
||||
A64_flip[6 + offset] = ((uint8_t *)&Aprime)[1];
|
||||
A64_flip[7 + offset] = ((uint8_t *)&Aprime)[0];
|
||||
if (polarParams->crcParityBits == 24)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc24c(A64_flip, 8 * offset + bitlen) >> 8))) & 0xffffff;
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc11(A64_flip, bitlen) >> 21))) & 0x7ff;
|
||||
} else if (bitlen <= 128) {
|
||||
uint8_t A128_flip[16 + offset];
|
||||
if (ones_flag) {
|
||||
A128_flip[0] = 0xff;
|
||||
A128_flip[1] = 0xff;
|
||||
A128_flip[2] = 0xff;
|
||||
}
|
||||
uint128_t Aprime = (uint128_t)(((uint128_t)*A) << (128 - bitlen));
|
||||
for (int i = 0; i < 16; i++)
|
||||
A128_flip[i + offset] = ((uint8_t *)&Aprime)[15 - i];
|
||||
if (polarParams->crcParityBits == 24)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc24c(A128_flip, 8 * offset + bitlen) >> 8))) & 0xffffff;
|
||||
else if (polarParams->crcParityBits == 11)
|
||||
tcrc = (uint64_t)((crcmask ^ (crc11(A128_flip, bitlen) >> 21))) & 0x7ff;
|
||||
}
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
int bitlen_B = bitlen + polarParams->crcParityBits;
|
||||
int B_array = (bitlen_B + 63) >> 6;
|
||||
int n_start = (B_array << 6) - bitlen_B;
|
||||
printf("b: ");
|
||||
for (int n = 0; n < bitlen_B; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = (n + n_start) >> 6;
|
||||
int n2 = (n + n_start) - (n1 << 6);
|
||||
printf("%lu", (B[B_array - 1 - n1] >> (63 - n2)) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
// this is number of quadwords in the bit string
|
||||
int quadwlen = (polarParams->K + 63) / 64;
|
||||
|
||||
// TS 38.212 - Section 5.3.1.1 Interleaving
|
||||
// For each byte of B, lookup in corresponding table for 64-bit word corresponding to that byte and its position
|
||||
uint64_t Cprime[4] = {0};
|
||||
uint8_t *Bbyte = (uint8_t *)B;
|
||||
if (polarParams->K < 65) {
|
||||
Cprime[0] = polarParams->cprime_tab0[0][Bbyte[0]] | polarParams->cprime_tab0[1][Bbyte[1]]
|
||||
| polarParams->cprime_tab0[2][Bbyte[2]] | polarParams->cprime_tab0[3][Bbyte[3]]
|
||||
| polarParams->cprime_tab0[4][Bbyte[4]] | polarParams->cprime_tab0[5][Bbyte[5]]
|
||||
| polarParams->cprime_tab0[6][Bbyte[6]] | polarParams->cprime_tab0[7][Bbyte[7]];
|
||||
} else if (polarParams->K < 129) {
|
||||
for (int i = 0; i < 1 + (polarParams->K / 8); i++) {
|
||||
Cprime[0] |= polarParams->cprime_tab0[i][Bbyte[i]];
|
||||
Cprime[1] |= polarParams->cprime_tab1[i][Bbyte[i]];
|
||||
}
|
||||
}
|
||||
// Create the B bit string as
|
||||
// 0, 0, ..., 0, a'_0, a'_1, ..., a'_A-1, p_0, p_1, ..., p_{N_parity-1}
|
||||
|
||||
#ifdef DEBUG_POLAR_MATLAB
|
||||
// Cprime = pbchCprime
|
||||
for (int i = 0; i < quadwlen; i++)
|
||||
printf("[polar_encoder_fast]C'[%d]= 0x%llx\n", i, (unsigned long long)(Cprime[i]));
|
||||
#endif
|
||||
//??? b_{N'-1} b_{N'-2} ... b_{N'-A} b_{N'-A-1} ... b_{N'-A-Nparity} = a_{N-1} a_{N-2} ... a_{N-A} p_{N_parity-1} ... p_0
|
||||
uint64_t B[4] = {0};
|
||||
B[0] = (A[0] << polarParams->crcParityBits) | tcrc;
|
||||
for (int n = 1; n < quadwlen; n++)
|
||||
if ((bitlen + 63) / 64 > n)
|
||||
B[n] = (A[n] << polarParams->crcParityBits) | (A[n - 1] >> (64 - polarParams->crcParityBits));
|
||||
else
|
||||
B[n] = (A[n - 1] >> (64 - polarParams->crcParityBits));
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("c: ");
|
||||
for (int n = 0; n < bitlen_B; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (Cprime[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
int bitlen_B = bitlen + polarParams->crcParityBits;
|
||||
int B_array = (bitlen_B + 63) >> 6;
|
||||
int n_start = (B_array << 6) - bitlen_B;
|
||||
printf("b: ");
|
||||
for (int n = 0; n < bitlen_B; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = (n + n_start) >> 6;
|
||||
int n2 = (n + n_start) - (n1 << 6);
|
||||
printf("%lu", (B[B_array - 1 - n1] >> (63 - n2)) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
uint64_t u[16] = {0};
|
||||
nr_polar_generate_u(u,
|
||||
Cprime,
|
||||
polarParams->information_bit_pattern,
|
||||
polarParams->parity_check_bit_pattern,
|
||||
polarParams->N,
|
||||
polarParams->n_pc);
|
||||
// TS 38.212 - Section 5.3.1.1 Interleaving
|
||||
// For each byte of B, lookup in corresponding table for 64-bit word corresponding to that byte and its position
|
||||
uint64_t Cprime[4] = {0};
|
||||
uint8_t *Bbyte = (uint8_t *)B;
|
||||
if (polarParams->K < 65) {
|
||||
Cprime[0] = polarParams->cprime_tab0[0][Bbyte[0]] | polarParams->cprime_tab0[1][Bbyte[1]]
|
||||
| polarParams->cprime_tab0[2][Bbyte[2]] | polarParams->cprime_tab0[3][Bbyte[3]]
|
||||
| polarParams->cprime_tab0[4][Bbyte[4]] | polarParams->cprime_tab0[5][Bbyte[5]]
|
||||
| polarParams->cprime_tab0[6][Bbyte[6]] | polarParams->cprime_tab0[7][Bbyte[7]];
|
||||
} else if (polarParams->K < 129) {
|
||||
for (int i = 0; i < 1 + (polarParams->K / 8); i++) {
|
||||
Cprime[0] |= polarParams->cprime_tab0[i][Bbyte[i]];
|
||||
Cprime[1] |= polarParams->cprime_tab1[i][Bbyte[i]];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
int N_array = polarParams->N >> 6;
|
||||
printf("u: ");
|
||||
for (int n = 0; n < polarParams->N; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (u[N_array - 1 - n1] >> (63 - n2)) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef DEBUG_POLAR_MATLAB
|
||||
// Cprime = pbchCprime
|
||||
for (int i = 0; i < quadwlen; i++)
|
||||
printf("[polar_encoder_fast]C'[%d]= 0x%llx\n", i, (unsigned long long)(Cprime[i]));
|
||||
#endif
|
||||
|
||||
uint64_t D[8];
|
||||
nr_polar_uxG((uint8_t *)u, polarParams->N, (uint8_t *)D);
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("c: ");
|
||||
for (int n = 0; n < bitlen_B; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (Cprime[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("d: ");
|
||||
for (int n = 0; n < polarParams->N; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (D[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
#endif
|
||||
uint64_t u[16] = {0};
|
||||
nr_polar_generate_u(u,
|
||||
Cprime,
|
||||
polarParams->information_bit_pattern,
|
||||
polarParams->parity_check_bit_pattern,
|
||||
polarParams->N,
|
||||
polarParams->n_pc);
|
||||
|
||||
memset((void *)out, 0, polarParams->encoderLength >> 3);
|
||||
polar_rate_matching(polarParams, (void *)D, out);
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
int N_array = polarParams->N >> 6;
|
||||
printf("u: ");
|
||||
for (int n = 0; n < polarParams->N; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (u[N_array - 1 - n1] >> (63 - n2)) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
uint64_t *out64 = (uint64_t *)out;
|
||||
printf("rm:");
|
||||
for (int n = 0; n < polarParams->encoderLength; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (out64[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
uint64_t D[8];
|
||||
nr_polar_uxG((uint8_t *)u, polarParams->N, (uint8_t *)D);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
printf("d: ");
|
||||
for (int n = 0; n < polarParams->N; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (D[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
memset((void *)out, 0, polarParams->encoderLength >> 3);
|
||||
polar_rate_matching(polarParams, (void *)D, out);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
uint64_t *out64 = (uint64_t *)out;
|
||||
printf("rm:");
|
||||
for (int n = 0; n < polarParams->encoderLength; n++) {
|
||||
if (n % 4 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
int n1 = n >> 6;
|
||||
int n2 = n - (n1 << 6);
|
||||
printf("%lu", (out64[n1] >> n2) & 1);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
polarReturn(polarParams);
|
||||
return;
|
||||
break;
|
||||
|
||||
polarReturn(polarParams);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
// Sec. 7.1.4: Channel Coding
|
||||
#define NR_POLAR_PBCH_N_MAX 9 // uint8_t
|
||||
#define NR_POLAR_PBCH_I_IL 1 // uint8_t
|
||||
#define NR_POLAR_PBCH_I_IL 0 // uint8_t
|
||||
#define NR_POLAR_PBCH_I_SEG 0 // uint8_t
|
||||
#define NR_POLAR_PBCH_N_PC 0 // uint8_t
|
||||
#define NR_POLAR_PBCH_N_PC_WM 0 // uint8_t
|
||||
|
||||
88
openair1/PHY/CODING/nrPolar_tools/ral_polar_decoder.cpp
Normal file
88
openair1/PHY/CODING/nrPolar_tools/ral_polar_decoder.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
//#include "src/utils/bits_to_bytes.hpp"
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <arm_neon.h>
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
armral_status ral_polar_decoder(
|
||||
const int16_t *input_llr16,
|
||||
uint32_t N,
|
||||
uint32_t E,
|
||||
uint32_t K,
|
||||
uint32_t L,
|
||||
armral_polar_ibil_type i_bil,
|
||||
uint8_t *decoded_out
|
||||
) {
|
||||
/* Convert input LLRs to int8_t (ArmRAL format) */
|
||||
|
||||
std::vector<int8_t> input_llr(E);
|
||||
for (uint32_t i = 0; i < E; i++)
|
||||
input_llr[i] = static_cast<int8_t>(input_llr16[i]);
|
||||
|
||||
/* Buffers */
|
||||
std::vector<int8_t> data_recovered(N);
|
||||
const uint32_t cw_bytes = (N + 7) / 8;
|
||||
std::vector<uint8_t> data_decoded(L * cw_bytes);
|
||||
std::vector<uint8_t> data_deint0((K + 7) / 8);
|
||||
std::vector<uint8_t> data_deint((K + 7) / 8);
|
||||
//std::vector<uint8_t> decoded_out(8);
|
||||
/* Rate recovery */
|
||||
|
||||
armral_polar_rate_recovery(
|
||||
N, E, K, i_bil,
|
||||
input_llr.data(),
|
||||
data_recovered.data());
|
||||
|
||||
/* Frozen mask (1 entry per bit) */
|
||||
std::vector<uint8_t> frozen_mask(N);
|
||||
armral_polar_frozen_mask(N, E, K, 0, 0, frozen_mask.data());
|
||||
|
||||
/* Decode */
|
||||
|
||||
armral_polar_decode_block(
|
||||
N, frozen_mask.data(), L,
|
||||
data_recovered.data(),
|
||||
data_decoded.data());
|
||||
|
||||
/* CRC check on candidates */
|
||||
|
||||
armral_polar_subchannel_deinterleave(
|
||||
K, frozen_mask.data(),
|
||||
data_decoded.data(),
|
||||
data_deint0.data());
|
||||
|
||||
/*
|
||||
if (armral_polar_crc_check(data_deint0.data(), K)) {
|
||||
memcpy(decoded_out, data_deint0.data(), (K + 7) / 8);
|
||||
return ARMRAL_SUCCESS;
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < L; i++) {
|
||||
const uint8_t *data_dec_l_ptr =
|
||||
data_decoded.data() + i * cw_bytes;
|
||||
|
||||
armral_polar_subchannel_deinterleave(
|
||||
K, frozen_mask.data(),
|
||||
data_dec_l_ptr,
|
||||
data_deint.data());
|
||||
|
||||
if (armral_polar_crc_check(data_deint.data(), K)) {
|
||||
memcpy(decoded_out, data_deint.data(), (K + 7) / 8);
|
||||
return ARMRAL_SUCCESS;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/* No CRC passed → return best candidate */
|
||||
//memcpy(decoded_out, data_deint0.data(), (K + 7) / 8);
|
||||
//return ARMRAL_FAIL;
|
||||
memcpy(decoded_out, data_deint0.data(), (K + 7) / 8);
|
||||
return ARMRAL_SUCCESS;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
108
openair1/PHY/CODING/nrPolar_tools/ral_polar_encoder.cpp
Normal file
108
openair1/PHY/CODING/nrPolar_tools/ral_polar_encoder.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
//#include "src/utils/bits_to_bytes.hpp"
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <arm_neon.h>
|
||||
|
||||
|
||||
|
||||
// 16-entry nibble table for reversing 4-bit nibbles
|
||||
static const uint8_t bitrev_nibble[16] = {
|
||||
0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,
|
||||
0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF
|
||||
};
|
||||
|
||||
void reverse_bits_per_byte_neon_aarch64(uint8_t *buf, size_t len) {
|
||||
size_t i = 0;
|
||||
|
||||
// Load 16-byte nibble table into NEON register
|
||||
uint8x16_t tbl = vld1q_u8(bitrev_nibble);
|
||||
|
||||
// Process 64 bytes per iteration (4 vectors × 16 bytes)
|
||||
for (; i + 64 <= len; i += 64) {
|
||||
// Load 4 NEON vectors
|
||||
uint8x16_t v0 = vld1q_u8(buf + i);
|
||||
uint8x16_t v1 = vld1q_u8(buf + i + 16);
|
||||
uint8x16_t v2 = vld1q_u8(buf + i + 32);
|
||||
uint8x16_t v3 = vld1q_u8(buf + i + 48);
|
||||
|
||||
// Pointer array to simplify loop
|
||||
uint8x16_t *vecs[4] = { &v0, &v1, &v2, &v3 };
|
||||
|
||||
// Process each vector
|
||||
for (int j = 0; j < 4; j++) {
|
||||
uint8x16_t v = *vecs[j];
|
||||
|
||||
// Split high and low nibbles
|
||||
uint8x16_t hi = vshrq_n_u8(v, 4); // high nibble
|
||||
uint8x16_t lo = vandq_u8(v, vdupq_n_u8(0x0F)); // low nibble
|
||||
|
||||
// Lookup reversed nibbles
|
||||
uint8x16_t rev_hi = vqtbl1q_u8(tbl, hi);
|
||||
uint8x16_t rev_lo = vqtbl1q_u8(tbl, lo);
|
||||
|
||||
// Combine nibbles
|
||||
*vecs[j] = vorrq_u8(vshlq_n_u8(rev_lo, 4), rev_hi);
|
||||
}
|
||||
|
||||
// Store back
|
||||
vst1q_u8(buf + i, v0);
|
||||
vst1q_u8(buf + i + 16, v1);
|
||||
vst1q_u8(buf + i + 32, v2);
|
||||
vst1q_u8(buf + i + 48, v3);
|
||||
}
|
||||
|
||||
// Handle remaining bytes (<64)
|
||||
for (; i < len; i++) {
|
||||
uint8_t byte = buf[i];
|
||||
buf[i] = (bitrev_nibble[byte & 0x0F] << 4) | bitrev_nibble[byte >> 4];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
armral_status ral_polar_encoder(
|
||||
const uint8_t *data_in,
|
||||
uint32_t K,
|
||||
uint32_t E,
|
||||
uint32_t N,
|
||||
armral_polar_ibil_type i_bil,
|
||||
uint8_t *data_crc,
|
||||
uint8_t *frozen_mask,
|
||||
uint8_t *data_interleaved,
|
||||
uint8_t *data_encoded,
|
||||
uint8_t *data_out
|
||||
) {
|
||||
// Step 1: CRC attachment
|
||||
// Input: data_in_bits (payload)
|
||||
// Output: data_crc_bits (payload + CRC)
|
||||
uint32_t crc_bits = 24; // CRC-24 (L = 24)
|
||||
uint32_t msg_bits = K - crc_bits; // message length (A = K - L)
|
||||
armral_polar_crc_attachment(data_in, msg_bits, data_crc); // CRC-24
|
||||
|
||||
// Step 2: Frozen mask creation
|
||||
// Marks which bits are frozen and which carry information
|
||||
armral_polar_frozen_mask(N, E, K, 0, 0, frozen_mask);
|
||||
// Step 3: Subchannel interleaving
|
||||
// Permutes input bits according to Polar rate-matching interleaver
|
||||
armral_polar_subchannel_interleave(N, K, frozen_mask, data_crc, data_interleaved);
|
||||
|
||||
|
||||
// Step 4: Polar encoding
|
||||
// Encodes N bits from interleaved input bits
|
||||
armral_polar_encode_block(N, data_interleaved, data_encoded);
|
||||
|
||||
// Step 5: Rate matching
|
||||
// Converts N bits to E bits for transmission
|
||||
armral_polar_rate_matching(N, E, K, i_bil, data_encoded, data_out);
|
||||
reverse_bits_per_byte_neon_aarch64(data_out,E);
|
||||
return ARMRAL_SUCCESS;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@@ -12,7 +12,7 @@ data storage. */
|
||||
#include<complex.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/version.h>
|
||||
#if defined RHEL_RELEASE_CODE
|
||||
#if 0
|
||||
#include <cblas/cblas.h>
|
||||
#else
|
||||
#include <cblas.h>
|
||||
|
||||
@@ -145,7 +145,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
|
||||
|
||||
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI, 1,
|
||||
NR_POLAR_DCI_MESSAGE_TYPE, dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
|
||||
NR_POLAR_DCI_MESSAGE_TYPE, dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel,0);
|
||||
#ifdef DEBUG_CHANNEL_CODING
|
||||
//debug dump dci
|
||||
printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu->AggregationLevel);
|
||||
|
||||
@@ -295,7 +295,8 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB,
|
||||
0,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL,
|
||||
0);
|
||||
|
||||
#ifdef DEBUG_PBCH_ENCODING
|
||||
printf("Channel coding:\n");
|
||||
|
||||
@@ -1285,7 +1285,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
||||
} // symb
|
||||
|
||||
// run polar decoder on llrs
|
||||
decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size);
|
||||
decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size,0);
|
||||
|
||||
// Decoder reversal
|
||||
decodedPayload[0] = reverse_bits(decodedPayload[0], nb_bit);
|
||||
|
||||
@@ -619,7 +619,7 @@ static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id,
|
||||
tmp_e);
|
||||
|
||||
const uint32_t crc = polar_decoder_int16(tmp_e, dci_estimation, 1, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
|
||||
const uint32_t crc = polar_decoder_int16(tmp_e, dci_estimation, 1, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L,0);
|
||||
|
||||
rnti_t n_rnti = rel15->rnti;
|
||||
if (crc == n_rnti) {
|
||||
|
||||
@@ -417,7 +417,8 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
0,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL,
|
||||
0);
|
||||
pbch_a_prime = tmp;
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
|
||||
@@ -208,7 +208,8 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
0,
|
||||
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
|
||||
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
|
||||
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL,
|
||||
0);
|
||||
|
||||
uint32_t psbch_payload = tmp;
|
||||
|
||||
|
||||
@@ -184,7 +184,8 @@ void sl_generate_and_map_psbch(c16_t *txF,
|
||||
0,
|
||||
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
|
||||
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
|
||||
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL,
|
||||
0);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i = 0; i < SL_NR_POLAR_PSBCH_E_DWORD; i++)
|
||||
|
||||
@@ -702,7 +702,8 @@ void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci
|
||||
polar_encoder_fast(&payload, b, 0,0,
|
||||
NR_POLAR_UCI_PUCCH_MESSAGE_TYPE,
|
||||
A,
|
||||
nrofPRB);
|
||||
nrofPRB,
|
||||
0);
|
||||
}
|
||||
|
||||
if (uci_on_pusch) {
|
||||
|
||||
1
openair1/armRAL_PHY/ral
Submodule
1
openair1/armRAL_PHY/ral
Submodule
Submodule openair1/armRAL_PHY/ral added at e4663894af
Reference in New Issue
Block a user