Merge remote-tracking branch 'origin/better-polar-decode' into integration_2024_w45 (!2949)

- simplify the code
- prevent to use "beta" tables from one decoder run to the next one (to see it
is the case, don't initialize beta, you will see it doesn't decode)
- decrease memory footprint of the decoder by x10 or more
- save about 15% of cpu in polartest unitary test tool, and more if we run in
realistic use case
- still this decoder performs much worse than the (very) slow OAI version by 3dB
This commit is contained in:
Jaroslava Fiedlerova
2024-11-08 08:20:08 +01:00
19 changed files with 1484 additions and 1401 deletions
+1 -1
View File
@@ -772,7 +772,7 @@ set(PHY_TURBOSRC
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder.c
)
set(PHY_POLARSRC
${OPENAIR1_DIR}/PHY/CODING/nr_polar_init.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_init.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_bitwise_operations.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_crc_byte.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_decoder.c
+245 -216
View File
@@ -12,159 +12,162 @@
#include "PHY/CODING/coding_defs.h"
#include "SIMULATION/TOOLS/sim.h"
#include "common/config/config_userapi.h"
//#include "common/utils/LOG/log.h"
// #include "common/utils/LOG/log.h"
#include "coding_unitary_defs.h"
//#define DEBUG_DCI_POLAR_PARAMS
//#define DEBUG_POLAR_TIMING
//#define DEBUG_POLARTEST
// #define DEBUG_DCI_POLAR_PARAMS
// #define DEBUG_POLAR_TIMING
// #define DEBUG_POLARTEST
configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char *argv[])
{
//Default simulation values (Aim for iterations = 1000000.)
int decoder_int16=0;
int itr, iterations = 1000, arguments, polarMessageType = 0; //0=PBCH, 1=DCI, 2=UCI
double SNRstart = -20.0, SNRstop = 0.0, SNRinc= 0.5; //dB
// Default simulation values (Aim for iterations = 1000000.)
int decoder_int16 = 0;
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;
int16_t nBitError = 0; // -1 = Decoding failed (All list entries have failed the CRC checks).
uint32_t decoderState=0, blockErrorState=0; //0 = Success, -1 = Decoding failed, 1 = Block Error.
uint32_t decoderState = 0, blockErrorState = 0; // 0 = Success, -1 = Decoding failed, 1 = Block Error.
uint16_t testLength = NR_POLAR_PBCH_PAYLOAD_BITS, coderLength = NR_POLAR_PBCH_E;
uint16_t blockErrorCumulative=0, bitErrorCumulative=0;
uint16_t blockErrorCumulative = 0, bitErrorCumulative = 0;
uint8_t aggregation_level = 8, decoderListSize = 8, logFlag = 0;
uint16_t rnti=0;
uint16_t rnti = 0;
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:")) != -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')
continue;
printf("handling optarg %c\n",arguments);
printf("handling optarg %c\n", arguments);
switch (arguments) {
case 's':
SNRstart = atof(optarg);
SNRstop = SNRstart + 2;
break;
case 's':
SNRstart = atof(optarg);
SNRstop = SNRstart + 2;
break;
case 'd':
SNRinc = atof(optarg);
break;
case 'd':
SNRinc = atof(optarg);
break;
case 'f':
SNRstop = atof(optarg);
break;
case 'f':
SNRstop = atof(optarg);
break;
case 'm':
polarMessageType = atoi(optarg);
if (polarMessageType!=0 && polarMessageType!=1 && polarMessageType!=2)
printf("Illegal polar message type %d (should be 0,1 or 2)\n", polarMessageType);
break;
case 'm':
polarMessageType = atoi(optarg);
if (polarMessageType != 0 && polarMessageType != 1 && polarMessageType != 2)
printf("Illegal polar message type %d (should be 0,1 or 2)\n", polarMessageType);
break;
case 'i':
iterations = atoi(optarg);
break;
case 'i':
iterations = atoi(optarg);
break;
case 'l':
decoderListSize = (uint8_t) atoi(optarg);
break;
case 'l':
decoderListSize = (uint8_t)atoi(optarg);
break;
case 'q':
decoder_int16 = 1;
break;
case 'q':
decoder_int16 = 1;
break;
case 'g':
iterations = 1;
SNRstart = -6.0;
SNRstop = -6.0;
decoder_int16 = 1;
break;
case 'g':
iterations = 1;
SNRstart = -6.0;
SNRstop = -6.0;
decoder_int16 = 1;
break;
case 'F':
logFlag = 1;
break;
case 'F':
logFlag = 1;
break;
case 'L':
aggregation_level=atoi(optarg);
if (aggregation_level != 1 && aggregation_level != 2 && aggregation_level != 4 && aggregation_level != 8 && aggregation_level != 16) {
printf("Illegal aggregation level %d \n",aggregation_level);
exit(-1);
}
break;
case 'L':
aggregation_level = atoi(optarg);
if (aggregation_level != 1 && aggregation_level != 2 && aggregation_level != 4 && aggregation_level != 8
&& aggregation_level != 16) {
printf("Illegal aggregation level %d \n", aggregation_level);
exit(-1);
}
break;
case 'k':
testLength=atoi(optarg);
if (testLength < 12 || testLength > 127) {
printf("Illegal packet bitlength %d \n",testLength);
exit(-1);
}
break;
case 'k':
testLength = atoi(optarg);
if (testLength < 12 || testLength > 127) {
printf("Illegal packet bitlength %d \n", testLength);
exit(-1);
}
break;
case 'h':
printf("./polartest\nOptions\n-h Print this help\n-s SNRstart (dB)\n-d SNRinc (dB)\n-f SNRstop (dB)\n-m [0=PBCH|1=DCI|2=UCI]\n"
"-i Number of iterations\n-l decoderListSize\n-q Flag for optimized coders usage\n-F Flag for test results logging\n"
"-L aggregation level (for DCI)\n-k packet_length (bits) for DCI/UCI\n");
exit(-1);
break;
case 'h':
printf(
"./polartest\nOptions\n-h Print this help\n-s SNRstart (dB)\n-d SNRinc (dB)\n-f SNRstop (dB)\n-m [0=PBCH|1=DCI|2=UCI]\n"
"-i Number of iterations\n-l decoderListSize\n-q Flag for optimized coders usage\n-F Flag for test results logging\n"
"-L aggregation level (for DCI)\n-k packet_length (bits) for DCI/UCI\n");
exit(-1);
break;
default:
perror("[polartest.c] Problem at argument parsing with getopt");
exit(-1);
break;
default:
perror("[polartest.c] Problem at argument parsing with getopt");
exit(-1);
break;
}
}
//Initiate timing. (Results depend on CPU Frequency. Therefore, might change due to performance variances during simulation.)
time_stats_t timeEncoder,timeDecoder;
// Initiate timing. (Results depend on CPU Frequency. Therefore, might change due to performance variances during simulation.)
time_stats_t timeEncoder, timeDecoder;
cpu_meas_enabled = 1;
reset_meas(&timeEncoder);
reset_meas(&timeDecoder);
randominit(0);
crcTableInit();
if (polarMessageType == 0) { //PBCH
if (polarMessageType == 0) { // PBCH
aggregation_level = NR_POLAR_PBCH_AGGREGATION_LEVEL;
} else if (polarMessageType == 1) { //DCI
coderLength = 108*aggregation_level;
} else if (polarMessageType == 2) { //UCI
//pucch2 parameters, 1 symbol, aggregation_level = NPRB
AssertFatal(aggregation_level>2,"For UCI formats, aggregation (N_RB) should be > 2\n");
coderLength = 16*aggregation_level;
} else if (polarMessageType == 1) { // DCI
coderLength = 108 * aggregation_level;
} else if (polarMessageType == 2) { // UCI
// pucch2 parameters, 1 symbol, aggregation_level = NPRB
AssertFatal(aggregation_level > 2, "For UCI formats, aggregation (N_RB) should be > 2\n");
coderLength = 16 * aggregation_level;
}
//Logging
// Logging
time_t currentTime;
char fileName[512], currentTimeInfo[25];
char folderName[] = ".";
FILE *logFile = NULL;
if (logFlag){
time (&currentTime);
if (logFlag) {
time(&currentTime);
#ifdef DEBUG_POLAR_TIMING
sprintf(fileName,"%s/TIMING_ListSize_%d_Payload_%d_Itr_%d", folderName, decoderListSize, testLength, iterations);
sprintf(fileName, "%s/TIMING_ListSize_%d_Payload_%d_Itr_%d", folderName, decoderListSize, testLength, iterations);
#else
sprintf(fileName,"%s/_ListSize_%d_Payload_%d_Itr_%d", folderName, decoderListSize, testLength, iterations);
sprintf(fileName, "%s/_ListSize_%d_Payload_%d_Itr_%d", folderName, decoderListSize, testLength, iterations);
#endif
strftime(currentTimeInfo, 25, "_%Y-%m-%d-%H-%M-%S.csv", localtime(&currentTime));
strcat(fileName,currentTimeInfo);
//Create "~/Desktop/polartestResults" folder if it doesn't already exist.
strcat(fileName, currentTimeInfo);
// Create "~/Desktop/polartestResults" folder if it doesn't already exist.
/*struct stat folder = {0};
if (stat(folderName, &folder) == -1) mkdir(folderName, S_IRWXU | S_IRWXG | S_IRWXO);*/
if (stat(folderName, &folder) == -1) mkdir(folderName, S_IRWXU | S_IRWXG | S_IRWXO);*/
logFile = fopen(fileName, "w");
if (logFile==NULL) {
fprintf(stderr,"[polartest.c] Problem creating file %s with fopen\n",fileName);
if (logFile == NULL) {
fprintf(stderr, "[polartest.c] Problem creating file %s with fopen\n", fileName);
exit(-1);
}
#ifdef DEBUG_POLAR_TIMING
fprintf(logFile,",timeEncoderCRCByte[us],timeEncoderCRCBit[us],timeEncoderInterleaver[us],timeEncoderBitInsertion[us],timeEncoder1[us],timeEncoder2[us],timeEncoderRateMatching[us],timeEncoderByte2Bit[us]\n");
fprintf(logFile,
",timeEncoderCRCByte[us],timeEncoderCRCBit[us],timeEncoderInterleaver[us],timeEncoderBitInsertion[us],timeEncoder1[us],"
"timeEncoder2[us],timeEncoderRateMatching[us],timeEncoderByte2Bit[us]\n");
#else
fprintf(logFile,",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n");
fprintf(logFile, ",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n");
#endif
}
@@ -175,54 +178,55 @@ int main(int argc, char *argv[])
// satisfies uint64_t array length
const uint8_t realArrayLength = ((testArrayLength + 1) / 2) * 2;
printf("testArrayLength %d realArrayLength %d\n", testArrayLength, realArrayLength);
uint32_t testInput[realArrayLength]; //generate randomly
uint32_t testInput[realArrayLength]; // generate randomly
uint32_t encoderOutput[coderArrayLength];
uint32_t estimatedOutput[realArrayLength]; //decoder output
memset(testInput,0,sizeof(uint32_t) * realArrayLength); // does not reset all
memset(encoderOutput,0,sizeof(uint32_t) * coderArrayLength);
memset(estimatedOutput,0,sizeof(uint32_t) * realArrayLength);
uint32_t estimatedOutput[realArrayLength]; // decoder output
memset(testInput, 0, sizeof(uint32_t) * realArrayLength); // does not reset all
memset(encoderOutput, 0, sizeof(uint32_t) * coderArrayLength);
memset(estimatedOutput, 0, sizeof(uint32_t) * realArrayLength);
uint8_t encoderOutputByte[coderLength];
double modulatedInput[coderLength]; //channel input
double channelOutput[coderLength]; //add noise
double modulatedInput[coderLength]; // channel input
double channelOutput[coderLength]; // add noise
int16_t channelOutput_int16[coderLength];
t_nrPolar_params *currentPtr = nr_polar_params(polarMessageType, testLength, aggregation_level, true);
t_nrPolar_params *currentPtr = nr_polar_params(polarMessageType, testLength, aggregation_level);
#ifdef DEBUG_DCI_POLAR_PARAMS
uint32_t dci_pdu[4];
memset(dci_pdu,0,sizeof(uint32_t)*4);
dci_pdu[0]=0x01189400;
memset(dci_pdu, 0, sizeof(uint32_t) * 4);
dci_pdu[0] = 0x01189400;
printf("dci_pdu: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", dci_pdu[0], dci_pdu[1], dci_pdu[2], dci_pdu[3]);
uint16_t size=41;
rnti=3;
aggregation_level=8;
uint16_t size = 41;
rnti = 3;
aggregation_level = 8;
uint32_t encoder_output[54];
memset(encoder_output,0,sizeof(uint32_t)*54);
t_nrPolar_params *currentPtrDCI=nr_polar_params(1, size, aggregation_level);
memset(encoder_output, 0, sizeof(uint32_t) * 54);
t_nrPolar_params *currentPtrDCI = nr_polar_params(1, size, aggregation_level);
polar_encoder_dci(dci_pdu, encoder_output, currentPtrDCI, rnti);
for (int i=0; i<54; i++) printf("encoder_output: [%2d]->0x%08x \n", i, encoder_output[i]);
for (int i = 0; i < 54; i++)
printf("encoder_output: [%2d]->0x%08x \n", i, encoder_output[i]);
uint8_t *encoder_outputByte = malloc(sizeof(uint8_t) * currentPtrDCI->encoderLength);
double *modulated_input = malloc (sizeof(double) * currentPtrDCI->encoderLength);
double *channel_output = malloc (sizeof(double) * currentPtrDCI->encoderLength);
double *modulated_input = malloc(sizeof(double) * currentPtrDCI->encoderLength);
double *channel_output = malloc(sizeof(double) * currentPtrDCI->encoderLength);
uint32_t dci_est[4];
memset(dci_est,0,sizeof(uint32_t)*4);
printf("dci_est: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", dci_est[0], dci_est[1], dci_est[2], dci_est[3]);
memset(dci_est, 0, sizeof(dci_est));
nr_bit2byte_uint32_8(encoder_output, currentPtrDCI->encoderLength, encoder_outputByte);
printf("[polartest] encoder_outputByte: ");
for (int i = 0; i < currentPtrDCI->encoderLength; i++) printf("%d-", encoder_outputByte[i]); printf("\n");
for (int i = 0; i < currentPtrDCI->encoderLength; i++)
printf("%d-", encoder_outputByte[i]);
printf("\n");
SNR_lin = pow(10, 0/10); //SNR = 0 dB
for(int i=0; i<currentPtrDCI->encoderLength; i++) {
if (encoder_outputByte[i] == 0)
modulated_input[i]=1/sqrt(2);
else
modulated_input[i]=(-1)/sqrt(2);
channel_output[i] = modulated_input[i] + (gaussdouble(0.0,1.0) * (1/sqrt(2*SNR_lin)));
SNR_lin = pow(10, 0 / 10); // SNR = 0 dB
for (int i = 0; i < currentPtrDCI->encoderLength; i++) {
if (encoder_outputByte[i] == 0)
modulated_input[i] = 1 / sqrt(2);
else
modulated_input[i] = (-1) / sqrt(2);
channel_output[i] = modulated_input[i] + (gaussdouble(0.0, 1.0) * (1 / sqrt(2 * SNR_lin)));
}
decoderState = polar_decoder_dci(channel_output, dci_est, NR_POLAR_DECODER_LISTSIZE, rnti,
1, size, aggregation_level);
decoderState = polar_decoder_dci(channel_output, dci_est, NR_POLAR_DECODER_LISTSIZE, rnti, 1, size, aggregation_level);
printf("dci_est: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", dci_est[0], dci_est[1], dci_est[2], dci_est[3]);
free(encoder_outputByte);
free(channel_output);
@@ -233,141 +237,166 @@ int main(int argc, char *argv[])
#endif
for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) {
printf("SNR %f\n",SNR);
SNR_lin = pow(10, SNR/10);
printf("SNR %f\n", SNR);
SNR_lin = pow(10, SNR / 10);
for (itr = 1; itr <= iterations; itr++) {
//Generate random values for all the bits of "testInput", not just as much as "currentPtr->payloadBits".
for (int i = 0; i < testArrayLength; i++) {
for (int j = 0; j < (sizeof(testInput[0])*8)-1; j++) {
testInput[i] |= ( ((uint32_t) (rand()%2)) &1);
testInput[i]<<=1;
}
testInput[i] |= ( ((uint32_t) (rand()%2)) &1);
}
for (itr = 1; itr <= iterations; itr++) {
// Generate random values for all the bits of "testInput", not just as much as "currentPtr->payloadBits".
for (int i = 0; i < testArrayLength; i++) {
for (int j = 0; j < (sizeof(testInput[0]) * 8) - 1; j++) {
testInput[i] |= (((uint32_t)(rand() % 2)) & 1);
testInput[i] <<= 1;
}
testInput[i] |= (((uint32_t)(rand() % 2)) & 1);
}
#ifdef DEBUG_POLARTEST
//testInput[0] = 0x360f8a5c;
printf("testInput: [0]->0x%08x\n", testInput[0]);
// testInput[0] = 0x360f8a5c;
printf("testInput: [0]->0x%08x\n", testInput[0]);
#endif
int len_mod64=currentPtr->payloadBits&63;
((uint64_t *)testInput)[currentPtr->payloadBits/64]&=((((uint64_t)1)<<len_mod64)-1);
int len_mod64 = currentPtr->payloadBits & 63;
((uint64_t *)testInput)[currentPtr->payloadBits / 64] &= ((((uint64_t)1) << len_mod64) - 1);
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, (uint64_t*)encoderOutput,0,0,currentPtr);
} else { //0 --> PBCH, 1 --> DCI, -1 --> UCI
if (polarMessageType == 0)
polar_encoder(testInput, encoderOutput, polarMessageType, testLength, aggregation_level);
else if (polarMessageType == 1)
polar_encoder_dci(testInput, encoderOutput, rnti, polarMessageType, testLength, aggregation_level);
}
stop_meas(&timeEncoder);
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, (uint64_t*)encoderOutput,0,0,currentPtr);
} else { // 0 --> PBCH, 1 --> DCI, -1 --> UCI
if (polarMessageType == 0)
polar_encoder(testInput, encoderOutput, polarMessageType, testLength, aggregation_level);
else if (polarMessageType == 1)
polar_encoder_dci(testInput, encoderOutput, rnti, polarMessageType, testLength, aggregation_level);
}
stop_meas(&timeEncoder);
#ifdef DEBUG_POLARTEST
printf("encoderOutput: [0]->0x%08x\n", encoderOutput[0]);
//for (int i=1;i<coderArrayLength;i++) printf("encoderOutput: [i]->0x%08x\n", i, encoderOutput[1]);
printf("encoderOutput: [0]->0x%08x\n", encoderOutput[0]);
// for (int i=1;i<coderArrayLength;i++) printf("encoderOutput: [i]->0x%08x\n", i, encoderOutput[1]);
#endif
//Bit-to-byte:
// Bit-to-byte:
nr_bit2byte_uint32_8(encoderOutput, coderLength, encoderOutputByte);
//BPSK modulation
for(int i=0; i<coderLength; i++) {
if (encoderOutputByte[i] == 0)
modulatedInput[i]=1/sqrt(2);
else
modulatedInput[i]=(-1)/sqrt(2);
// BPSK modulation
for (int i = 0; i < coderLength; i++) {
if (encoderOutputByte[i] == 0)
modulatedInput[i] = 1 / sqrt(2);
else
modulatedInput[i] = (-1) / sqrt(2);
channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0,1.0) * (1/sqrt(2*SNR_lin)));
channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0, 1.0) * (1 / sqrt(2 * SNR_lin)));
if (decoder_int16==1) {
if (channelOutput[i] > 15) channelOutput_int16[i] = 127;
else if (channelOutput[i] < -16) channelOutput_int16[i] = -128;
else channelOutput_int16[i] = (int16_t) (8*channelOutput[i]);
}
if (decoder_int16 == 1) {
if (channelOutput[i] > 15)
channelOutput_int16[i] = 127;
else if (channelOutput[i] < -16)
channelOutput_int16[i] = -128;
else
channelOutput_int16[i] = (int16_t)(8 * channelOutput[i]);
}
}
start_meas(&timeDecoder);
if (decoder_int16==1) {
decoderState = polar_decoder_int16(channelOutput_int16, (uint64_t *)estimatedOutput, 0,
polarMessageType, testLength, aggregation_level);
} else { //0 --> PBCH, 1 --> DCI, -1 --> UCI
if (polarMessageType == 0) {
decoderState = polar_decoder(channelOutput,
estimatedOutput,
decoderListSize,
polarMessageType, testLength, aggregation_level);
} else if (polarMessageType == 1) {
decoderState = polar_decoder_dci(channelOutput,
estimatedOutput,
decoderListSize,
rnti,
polarMessageType, testLength, aggregation_level);
}
if (decoder_int16 == 1) {
decoderState = polar_decoder_int16(channelOutput_int16,
(uint64_t *)estimatedOutput,
0,
polarMessageType,
testLength,
aggregation_level);
} else { // 0 --> PBCH, 1 --> DCI, -1 --> UCI
if (polarMessageType == 0) {
decoderState =
polar_decoder(channelOutput, estimatedOutput, decoderListSize, polarMessageType, testLength, aggregation_level);
} else if (polarMessageType == 1) {
decoderState = polar_decoder_dci(channelOutput,
estimatedOutput,
decoderListSize,
rnti,
polarMessageType,
testLength,
aggregation_level);
}
}
stop_meas(&timeDecoder);
#ifdef DEBUG_POLARTEST
printf("estimatedOutput: [0]->0x%08x\n", estimatedOutput[0]);
#endif
//calculate errors
if (decoderState!=0) {
blockErrorState=-1;
nBitError=-1;
// calculate errors
if (decoderState != 0) {
blockErrorState = -1;
nBitError = -1;
} else {
for (int i = 0; i < (testArrayLength-1); i++) {
for (int j = 0; j < 32; j++) {
if ( ((estimatedOutput[i]>>j) & 1) != ((testInput[i]>>j) & 1) )
nBitError++;
}
}
for (int j = 0; j < testLength - ((testArrayLength-1) * 32); j++)
if ( ((estimatedOutput[(testArrayLength-1)]>>j) & 1) != ((testInput[(testArrayLength-1)]>>j) & 1) )
nBitError++;
for (int i = 0; i < (testArrayLength - 1); i++) {
for (int j = 0; j < 32; j++) {
if (((estimatedOutput[i] >> j) & 1) != ((testInput[i] >> j) & 1))
nBitError++;
}
}
for (int j = 0; j < testLength - ((testArrayLength - 1) * 32); j++)
if (((estimatedOutput[(testArrayLength - 1)] >> j) & 1) != ((testInput[(testArrayLength - 1)] >> j) & 1))
nBitError++;
}
if (nBitError>0) blockErrorState=1;
if (nBitError > 0)
blockErrorState = 1;
#ifdef DEBUG_POLARTEST
for (int i = 0; i < testArrayLength; i++)
printf("[polartest/decoderState=%u] testInput[%d]=0x%08x, estimatedOutput[%d]=0x%08x\n",decoderState, i, testInput[i], i, estimatedOutput[i]);
for (int i = 0; i < testArrayLength; i++)
printf("[polartest/decoderState=%u] testInput[%d]=0x%08x, estimatedOutput[%d]=0x%08x\n",
decoderState,
i,
testInput[i],
i,
estimatedOutput[i]);
#endif
//Iteration times are in microseconds.
if (logFlag) fprintf(logFile,",%f,%d,%u,%f,%f\n", SNR, nBitError, blockErrorState, (timeEncoder.diff/(get_cpu_freq_GHz()*1000.0)), (timeDecoder.diff/(get_cpu_freq_GHz()*1000.0)));
// Iteration times are in microseconds.
if (logFlag)
fprintf(logFile,
",%f,%d,%u,%f,%f\n",
SNR,
nBitError,
blockErrorState,
(timeEncoder.diff / (get_cpu_freq_GHz() * 1000.0)),
(timeDecoder.diff / (get_cpu_freq_GHz() * 1000.0)));
if (nBitError<0) {
if (nBitError < 0) {
blockErrorCumulative++;
bitErrorCumulative+=testLength;
bitErrorCumulative += testLength;
} else {
blockErrorCumulative+=blockErrorState;
bitErrorCumulative+=nBitError;
blockErrorCumulative += blockErrorState;
bitErrorCumulative += nBitError;
}
decoderState=0;
nBitError=0;
blockErrorState=0;
memset(testInput,0,sizeof(uint32_t) * realArrayLength);
memset(encoderOutput,0,sizeof(uint32_t) * coderArrayLength);
memset(estimatedOutput,0,sizeof(uint32_t) * realArrayLength);
decoderState = 0;
nBitError = 0;
blockErrorState = 0;
memset(testInput, 0, sizeof(uint32_t) * realArrayLength);
memset(encoderOutput, 0, sizeof(uint32_t) * coderArrayLength);
memset(estimatedOutput, 0, sizeof(uint32_t) * realArrayLength);
}
//Calculate error statistics for the SNR.
// Calculate error statistics for the SNR.
printf("[ListSize=%d] SNR=%+8.3f, BLER=%9.6f, BER=%12.9f, t_Encoder=%9.3fus, t_Decoder=%9.3fus\n",
decoderListSize, SNR, ((double)blockErrorCumulative/iterations),
((double)bitErrorCumulative / (iterations*testLength)),
(double)timeEncoder.diff/timeEncoder.trials/(get_cpu_freq_GHz()*1000.0),(double)timeDecoder.diff/timeDecoder.trials/(get_cpu_freq_GHz()*1000.0));
decoderListSize,
SNR,
((double)blockErrorCumulative / iterations),
((double)bitErrorCumulative / (iterations * testLength)),
(double)timeEncoder.diff / timeEncoder.trials / (get_cpu_freq_GHz() * 1000.0),
(double)timeDecoder.diff / timeDecoder.trials / (get_cpu_freq_GHz() * 1000.0));
if (blockErrorCumulative==0 && bitErrorCumulative==0) break;
if (blockErrorCumulative == 0 && bitErrorCumulative == 0)
break;
blockErrorCumulative = 0;
bitErrorCumulative = 0;
}
print_meas(&timeEncoder,"polar_encoder",NULL,NULL);
print_meas(&timeDecoder,"polar_decoder",NULL,NULL);
if (logFlag) fclose(logFile);
print_meas(&timeEncoder, "polar_encoder", NULL, NULL);
print_meas(&timeDecoder, "polar_decoder", NULL, NULL);
if (logFlag)
fclose(logFile);
return (0);
}
@@ -28,11 +28,12 @@
* \email turker.yilmaz@eurecom.fr
* \note
* \warning
*/
*/
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
void nr_bit2byte_uint32_8(uint32_t *in, uint16_t arraySize, uint8_t *out) {
void nr_bit2byte_uint32_8(uint32_t *in, uint16_t arraySize, uint8_t *out)
{
const uint arrayInd = ceil(arraySize / 32.0);
for (int i = 0; i < (arrayInd - 1); i++) {
for (int j = 0; j < 32; j++) {
@@ -44,7 +45,8 @@ void nr_bit2byte_uint32_8(uint32_t *in, uint16_t arraySize, uint8_t *out) {
out[j + ((arrayInd - 1) * 32)] = (in[(arrayInd - 1)] >> j) & 1;
}
void nr_byte2bit_uint8_32(uint8_t *in, uint16_t arraySize, uint32_t *out) {
void nr_byte2bit_uint8_32(uint8_t *in, uint16_t arraySize, uint32_t *out)
{
const uint arrayInd = ceil(arraySize / 32.0);
for (int i = 0; i < arrayInd; i++) {
out[i] = 0;
@@ -29,7 +29,8 @@ const uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits)
uint8_t crcPolynomialSize = 24;
uint8_t temp1[crcPolynomialSize], temp2[crcPolynomialSize];
uint8_t **crc_generator_matrix = malloc(payloadSizeBits*sizeof(uint8_t *) + payloadSizeBits*crcPolynomialSize*sizeof(uint8_t));
uint8_t **crc_generator_matrix =
malloc(payloadSizeBits * sizeof(uint8_t *) + payloadSizeBits * crcPolynomialSize * sizeof(uint8_t));
if (crc_generator_matrix)
for (int i = 0; i < payloadSizeBits; i++)
crc_generator_matrix[i] = ((uint8_t *)&crc_generator_matrix[payloadSizeBits]) + i * crcPolynomialSize;
@@ -38,7 +39,8 @@ const uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits)
crc_generator_matrix[payloadSizeBits - 1][i] = crcPolynomialPattern[i + 1];
for (int i = payloadSizeBits - 2; i >= 0; i--) {
for (int j = 0; j < crcPolynomialSize-1; j++) temp1[j]=crc_generator_matrix[i+1][j+1];
for (int j = 0; j < crcPolynomialSize - 1; j++)
temp1[j] = crc_generator_matrix[i + 1][j + 1];
temp1[crcPolynomialSize - 1] = 0;
@@ -46,10 +48,10 @@ const uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits)
temp2[j] = crc_generator_matrix[i + 1][0] * crcPolynomialPattern[j + 1];
for (int j = 0; j < crcPolynomialSize; j++) {
if(temp1[j]+temp2[j] == 1)
crc_generator_matrix[i][j]=1;
else
crc_generator_matrix[i][j]=0;
if (temp1[j] + temp2[j] == 1)
crc_generator_matrix[i][j] = 1;
else
crc_generator_matrix[i][j] = 0;
}
}
return (const uint8_t **)crc_generator_matrix;
@@ -20,31 +20,31 @@
*/
/*! \file PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h
* \brief Defines the constant variables for polar coding of the DCI from 38-212, V15.1.1 2018-04.
* \author
* \date 2018
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
* \brief Defines the constant variables for polar coding of the DCI from 38-212, V15.1.1 2018-04.
* \author
* \date 2018
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
#ifndef __NR_POLAR_DCI_DEFS__H__
#define __NR_POLAR_DCI_DEFS__H__
#define NR_POLAR_DCI_MESSAGE_TYPE 1 //int8_t
#define NR_POLAR_DCI_MESSAGE_TYPE 1 // int8_t
#define NR_POLAR_DCI_CRC_PARITY_BITS 24
#define NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS 3
//Sec. 7.3.3: Channel Coding
#define NR_POLAR_DCI_N_MAX 9 //uint8_t
#define NR_POLAR_DCI_I_IL 1 //uint8_t
#define NR_POLAR_DCI_I_SEG 0 //uint8_t
#define NR_POLAR_DCI_N_PC 0 //uint8_t
#define NR_POLAR_DCI_N_PC_WM 0 //uint8_t
// Sec. 7.3.3: Channel Coding
#define NR_POLAR_DCI_N_MAX 9 // uint8_t
#define NR_POLAR_DCI_I_IL 1 // uint8_t
#define NR_POLAR_DCI_I_SEG 0 // uint8_t
#define NR_POLAR_DCI_N_PC 0 // uint8_t
#define NR_POLAR_DCI_N_PC_WM 0 // uint8_t
//Sec. 7.3.4: Rate Matching
#define NR_POLAR_DCI_I_BIL 0 //uint8_t
// Sec. 7.3.4: Rate Matching
#define NR_POLAR_DCI_I_BIL 0 // uint8_t
#endif
@@ -39,17 +39,17 @@
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include "assertions.h"
//#define POLAR_CODING_DEBUG
// #define POLAR_CODING_DEBUG
static inline void updateCrcChecksum2(int xlen,
int ylen,
uint8_t crcChecksum[xlen][ylen],
int gxlen,
int gylen,
uint8_t crcGen[gxlen][gylen],
uint8_t listSize,
uint32_t i2,
uint8_t len)
int ylen,
uint8_t crcChecksum[xlen][ylen],
int gxlen,
int gylen,
uint8_t crcGen[gxlen][gylen],
uint8_t listSize,
uint32_t i2,
uint8_t len)
{
for (uint i = 0; i < listSize; i++) {
for (uint j = 0; j < len; j++) {
@@ -63,67 +63,71 @@ int8_t polar_decoder(double *input,
uint8_t listSize,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level
)
uint8_t aggregation_level)
{
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true);
//Assumes no a priori knowledge.
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
// Assumes no a priori knowledge.
uint8_t bit[polarParams->N][polarParams->n + 1][2 * listSize];
memset(bit, 0, sizeof bit);
uint8_t bitUpdated[polarParams->N][polarParams->n+1]; //0=False, 1=True
memset(bitUpdated,0,sizeof bitUpdated);
uint8_t llrUpdated[polarParams->N][polarParams->n+1]; //0=False, 1=True
memset(llrUpdated,0,sizeof llrUpdated);
uint8_t bitUpdated[polarParams->N][polarParams->n + 1]; // 0=False, 1=True
memset(bitUpdated, 0, sizeof bitUpdated);
uint8_t llrUpdated[polarParams->N][polarParams->n + 1]; // 0=False, 1=True
memset(llrUpdated, 0, sizeof llrUpdated);
double llr[polarParams->N][polarParams->n + 1][2 * listSize];
uint8_t crcChecksum[polarParams->crcParityBits][2*listSize];
memset(crcChecksum,0,sizeof crcChecksum);
double pathMetric[2*listSize];
uint8_t crcState[2*listSize]; //0=False, 1=True
uint8_t crcChecksum[polarParams->crcParityBits][2 * listSize];
memset(crcChecksum, 0, sizeof crcChecksum);
double pathMetric[2 * listSize];
uint8_t crcState[2 * listSize]; // 0=False, 1=True
for (int i=0; i<(2*listSize); i++) {
for (int i = 0; i < (2 * listSize); i++) {
pathMetric[i] = 0;
crcState[i]=1;
crcState[i] = 1;
}
for (int i=0; i<polarParams->N; i++) {
llrUpdated[i][polarParams->n]=1;
for (int i = 0; i < polarParams->N; i++) {
llrUpdated[i][polarParams->n] = 1;
bitUpdated[i][0] = (polarParams->information_bit_pattern[i] + 1) % 2;
}
uint8_t extended_crc_generator_matrix[polarParams->K][polarParams->crcParityBits]; //G_P3
uint8_t tempECGM[polarParams->K][polarParams->crcParityBits]; //G_P2
uint8_t extended_crc_generator_matrix[polarParams->K][polarParams->crcParityBits]; // G_P3
uint8_t tempECGM[polarParams->K][polarParams->crcParityBits]; // G_P2
for (int i=0; i<polarParams->payloadBits; i++) {
for (int j=0; j<polarParams->crcParityBits; j++) {
tempECGM[i][j]=polarParams->crc_generator_matrix[i][j];
for (int i = 0; i < polarParams->payloadBits; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
tempECGM[i][j] = polarParams->crc_generator_matrix[i][j];
}
}
for (int i=polarParams->payloadBits; i<polarParams->K; i++) {
for (int j=0; j<polarParams->crcParityBits; j++) {
for (int i = polarParams->payloadBits; i < polarParams->K; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
tempECGM[i][j] = (i - polarParams->payloadBits) == j;
}
}
for (int i=0; i<polarParams->K; i++) {
for (int j=0; j<polarParams->crcParityBits; j++) {
extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j];
for (int i = 0; i < polarParams->K; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
extended_crc_generator_matrix[i][j] = tempECGM[polarParams->interleaving_pattern[i]][j];
}
}
//The index of the last 1-valued bit that appears in each column.
AssertFatal(polarParams->crcParityBits > 0, "UB for VLA. crcParityBits negative\n");
// The index of the last 1-valued bit that appears in each column.
AssertFatal(polarParams->crcParityBits > 0, "UB for VLA. crcParityBits negative\n");
uint16_t last1ind[polarParams->crcParityBits];
for (int j=0; j<polarParams->crcParityBits; j++) {
for (int i=0; i<polarParams->K; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
for (int i = 0; i < polarParams->K; i++) {
if (extended_crc_generator_matrix[i][j] == 1)
last1ind[j] = i;
}
}
double d_tilde[polarParams->N];
nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength);
nr_polar_rate_matching(input,
d_tilde,
polarParams->rate_matching_pattern,
polarParams->K,
polarParams->N,
polarParams->encoderLength);
for (int j = 0; j < polarParams->N; j++)
llr[j][polarParams->n][0] = d_tilde[j];
@@ -131,18 +135,18 @@ int8_t polar_decoder(double *input,
/*
* SCL polar decoder.
*/
uint32_t nonFrozenBit=0;
uint32_t nonFrozenBit = 0;
uint currentListSize = 1;
uint decoderIterationCheck = 0;
int checkCrcBits = -1;
uint8_t listIndex[2*listSize], copyIndex;
uint8_t listIndex[2 * listSize], copyIndex;
for (uint currentBit = 0; currentBit < polarParams->N; currentBit++) {
updateLLR(currentListSize, currentBit, 0, polarParams->N, polarParams->n + 1, 2 * listSize, llr, llrUpdated, bit, bitUpdated);
if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit.
if (polarParams->information_bit_pattern[currentBit] == 0) { // Frozen bit.
updatePathMetric(pathMetric, currentListSize, 0, currentBit, polarParams->N, polarParams->n + 1, 2 * listSize, llr);
} else { //Information or CRC bit.
} else { // Information or CRC bit.
updatePathMetric2(pathMetric, currentListSize, currentBit, polarParams->N, polarParams->n + 1, 2 * listSize, llr);
for (int i = 0; i < currentListSize; i++) {
@@ -198,30 +202,30 @@ int8_t polar_decoder(double *input,
break;
}
//First, backup the best "listSize" number of entries.
for (int k=(listSize-1); k>0; k--) {
for (int i=0; i<polarParams->N; i++) {
for (int j=0; j<(polarParams->n+1); j++) {
// First, backup the best "listSize" number of entries.
for (int k = (listSize - 1); k > 0; k--) {
for (int i = 0; i < polarParams->N; i++) {
for (int j = 0; j < (polarParams->n + 1); j++) {
bit[i][j][listIndex[(2 * listSize - 1) - k]] = bit[i][j][listIndex[k]];
llr[i][j][listIndex[(2 * listSize - 1) - k]] = llr[i][j][listIndex[k]];
}
}
}
for (int k=(listSize-1); k>0; k--) {
for (int k = (listSize - 1); k > 0; k--) {
for (int i = 0; i < polarParams->crcParityBits; i++) {
crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]];
crcChecksum[i][listIndex[(2 * listSize - 1) - k]] = crcChecksum[i][listIndex[k]];
}
}
for (int k = (listSize - 1); k > 0; k--)
crcState[listIndex[(2 * listSize - 1) - k]] = crcState[listIndex[k]];
//Copy the best "listSize" number of entries to the first indices.
// Copy the best "listSize" number of entries to the first indices.
for (int k = 0; k < listSize; k++) {
if (k > listIndex[k]) {
copyIndex = listIndex[(2*listSize-1)-k];
} else { //Use the backup.
copyIndex = listIndex[(2 * listSize - 1) - k];
} else { // Use the backup.
copyIndex = listIndex[k];
}
@@ -235,40 +239,40 @@ int8_t polar_decoder(double *input,
for (int k = 0; k < listSize; k++) {
if (k > listIndex[k]) {
copyIndex = listIndex[(2*listSize-1)-k];
} else { //Use the backup.
copyIndex = listIndex[(2 * listSize - 1) - k];
} else { // Use the backup.
copyIndex = listIndex[k];
}
for (int i = 0; i < polarParams->crcParityBits; i++) {
crcChecksum[i][k]=crcChecksum[i][copyIndex];
crcChecksum[i][k] = crcChecksum[i][copyIndex];
}
}
for (int k = 0; k < listSize; k++) {
if (k > listIndex[k]) {
copyIndex = listIndex[(2*listSize-1)-k];
} else { //Use the backup.
copyIndex = listIndex[(2 * listSize - 1) - k];
} else { // Use the backup.
copyIndex = listIndex[k];
}
crcState[k]=crcState[copyIndex];
crcState[k] = crcState[copyIndex];
}
currentListSize = listSize;
}
for (int i=0; i<polarParams->crcParityBits; i++) {
if (last1ind[i]==nonFrozenBit) {
checkCrcBits=i;
for (int i = 0; i < polarParams->crcParityBits; i++) {
if (last1ind[i] == nonFrozenBit) {
checkCrcBits = i;
break;
}
}
if ( checkCrcBits > (-1) ) {
if (checkCrcBits > (-1)) {
for (uint i = 0; i < currentListSize; i++) {
if (crcChecksum[checkCrcBits][i]==1) {
crcState[i]=0; //0=False, 1=True
if (crcChecksum[checkCrcBits][i] == 1) {
crcState[i] = 0; // 0=False, 1=True
}
}
}
@@ -276,15 +280,15 @@ int8_t polar_decoder(double *input,
for (uint i = 0; i < currentListSize; i++)
decoderIterationCheck += crcState[i];
if (decoderIterationCheck==0) {
//perror("[SCL polar decoder] All list entries have failed the CRC checks.");
if (decoderIterationCheck == 0) {
// perror("[SCL polar decoder] All list entries have failed the CRC checks.");
polarReturn(polarParams);
return -1;
}
nonFrozenBit++;
decoderIterationCheck=0;
checkCrcBits=-1;
decoderIterationCheck = 0;
checkCrcBits = -1;
}
}
@@ -294,19 +298,19 @@ int8_t polar_decoder(double *input,
nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize);
uint8_t nr_polar_A[polarParams->payloadBits];
for (uint i = 0; i < fmin(listSize, (pow(2, polarParams->crcCorrectionBits))); i++) {
if ( crcState[listIndex[i]] == 1 ) {
if (crcState[listIndex[i]] == 1) {
uint8_t nr_polar_U[polarParams->N];
for (int j = 0; j < polarParams->N; j++)
nr_polar_U[j] = bit[j][0][listIndex[i]];
//Extract the information bits (û to ĉ)
// Extract the information bits (û to ĉ)
uint8_t nr_polar_CPrime[polarParams->N];
nr_polar_info_bit_extraction(nr_polar_U, nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N);
//Deinterleaving (ĉ to b)
// Deinterleaving (ĉ to b)
uint8_t nr_polar_B[polarParams->K];
nr_polar_deinterleaver(nr_polar_CPrime, nr_polar_B, polarParams->interleaving_pattern, polarParams->K);
//Remove the CRC (â)
// Remove the CRC (â)
memcpy(nr_polar_A, nr_polar_B, polarParams->payloadBits);
break;
@@ -328,123 +332,137 @@ int8_t polar_decoder_dci(double *input,
uint16_t n_RNTI,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level ) {
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true);
uint8_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
uint8_t bit[polarParams->N][polarParams->n+1][2*listSize];
memset(bit,0,sizeof bit);
uint8_t bitUpdated[polarParams->N][polarParams->n+1]; //0=False, 1=True
memset(bitUpdated,0,sizeof bitUpdated);
uint8_t llrUpdated[polarParams->N][polarParams->n+1]; //0=False, 1=True
memset(llrUpdated,0,sizeof llrUpdated);
double llr[polarParams->N][polarParams->n+1][2*listSize];
uint8_t crcChecksum[polarParams->crcParityBits][2*listSize];
memset(crcChecksum,0,sizeof crcChecksum);
double pathMetric[2*listSize];
uint8_t crcState[2*listSize]; //0=False, 1=True
uint8_t bit[polarParams->N][polarParams->n + 1][2 * listSize];
memset(bit, 0, sizeof bit);
uint8_t bitUpdated[polarParams->N][polarParams->n + 1]; // 0=False, 1=True
memset(bitUpdated, 0, sizeof bitUpdated);
uint8_t llrUpdated[polarParams->N][polarParams->n + 1]; // 0=False, 1=True
memset(llrUpdated, 0, sizeof llrUpdated);
double llr[polarParams->N][polarParams->n + 1][2 * listSize];
uint8_t crcChecksum[polarParams->crcParityBits][2 * listSize];
memset(crcChecksum, 0, sizeof crcChecksum);
double pathMetric[2 * listSize];
uint8_t crcState[2 * listSize]; // 0=False, 1=True
uint8_t extended_crc_scrambling_pattern[polarParams->crcParityBits];
for (int i=0; i<(2*listSize); i++) {
for (int i = 0; i < (2 * listSize); i++) {
pathMetric[i] = 0;
crcState[i]=1;
crcState[i] = 1;
}
for (int i=0; i<polarParams->N; i++) {
llrUpdated[i][polarParams->n]=1;
for (int i = 0; i < polarParams->N; i++) {
llrUpdated[i][polarParams->n] = 1;
bitUpdated[i][0] = (polarParams->information_bit_pattern[i] + 1) % 2;
}
uint8_t extended_crc_generator_matrix[polarParams->K][polarParams->crcParityBits]; //G_P3: K-by-P
uint8_t tempECGM[polarParams->K][polarParams->crcParityBits]; //G_P2: K-by-P
uint8_t extended_crc_generator_matrix[polarParams->K][polarParams->crcParityBits]; // G_P3: K-by-P
uint8_t tempECGM[polarParams->K][polarParams->crcParityBits]; // G_P2: K-by-P
for (int i=0; i<polarParams->payloadBits; i++) {
for (int j=0; j<polarParams->crcParityBits; j++) {
tempECGM[i][j]=polarParams->crc_generator_matrix[i+polarParams->crcParityBits][j];
for (int i = 0; i < polarParams->payloadBits; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
tempECGM[i][j] = polarParams->crc_generator_matrix[i + polarParams->crcParityBits][j];
}
}
for (int i=polarParams->payloadBits; i<polarParams->K; i++) {
for (int j=0; j<polarParams->crcParityBits; j++) {
for (int i = polarParams->payloadBits; i < polarParams->K; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
tempECGM[i][j] = (i - polarParams->payloadBits) == j;
}
}
for (int i=0; i<polarParams->K; i++) {
for (int j=0; j<polarParams->crcParityBits; j++) {
extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j];
for (int i = 0; i < polarParams->K; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++) {
extended_crc_generator_matrix[i][j] = tempECGM[polarParams->interleaving_pattern[i]][j];
}
}
//The index of the last 1-valued bit that appears in each column.
// The index of the last 1-valued bit that appears in each column.
uint16_t last1ind[polarParams->crcParityBits];
for (int j=0; j<polarParams->crcParityBits; j++) {
for (int i=0; i<polarParams->K; i++) {
if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i;
for (int j = 0; j < polarParams->crcParityBits; j++) {
for (int i = 0; i < polarParams->K; i++) {
if (extended_crc_generator_matrix[i][j] == 1)
last1ind[j] = i;
}
}
for (int i = 0; i < 8; i++)
extended_crc_scrambling_pattern[i] = 0;
for (int i=8; i<polarParams->crcParityBits; i++) {
extended_crc_scrambling_pattern[i]=(n_RNTI>>(23-i))&1;
for (int i = 8; i < polarParams->crcParityBits; i++) {
extended_crc_scrambling_pattern[i] = (n_RNTI >> (23 - i)) & 1;
}
double d_tilde[polarParams->N];
nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength);
nr_polar_rate_matching(input,
d_tilde,
polarParams->rate_matching_pattern,
polarParams->K,
polarParams->N,
polarParams->encoderLength);
for (int j = 0; j < polarParams->N; j++)
llr[j][polarParams->n][0]=d_tilde[j];
llr[j][polarParams->n][0] = d_tilde[j];
/*
* SCL polar decoder.
*/
for (int i=0; i<polarParams->crcParityBits; i++) {
for (int j=0; j<polarParams->crcParityBits; j++)
crcChecksum[i][0]=crcChecksum[i][0]+polarParams->crc_generator_matrix[j][i];
for (int i = 0; i < polarParams->crcParityBits; i++) {
for (int j = 0; j < polarParams->crcParityBits; j++)
crcChecksum[i][0] = crcChecksum[i][0] + polarParams->crc_generator_matrix[j][i];
crcChecksum[i][0]=(crcChecksum[i][0]%2);
crcChecksum[i][0] = (crcChecksum[i][0] % 2);
}
uint32_t nonFrozenBit=0;
uint32_t nonFrozenBit = 0;
uint currentListSize = 1;
uint decoderIterationCheck = 0;
int checkCrcBits = -1;
uint8_t listIndex[2*listSize], copyIndex;
uint8_t listIndex[2 * listSize], copyIndex;
for (uint currentBit = 0; currentBit < polarParams->N; currentBit++) {
updateLLR(currentListSize, currentBit, 0, polarParams->N, polarParams->n+1, 2*listSize, llr, llrUpdated, bit, bitUpdated);
updateLLR(currentListSize, currentBit, 0, polarParams->N, polarParams->n + 1, 2 * listSize, llr, llrUpdated, bit, bitUpdated);
if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit.
updatePathMetric(pathMetric, currentListSize, 0, currentBit,polarParams->N, polarParams->n+1, 2*listSize, llr);
} else { //Information or CRC bit.
updatePathMetric2(pathMetric, currentListSize, currentBit, polarParams->N, polarParams->n+1, 2*listSize, llr);
if (polarParams->information_bit_pattern[currentBit] == 0) { // Frozen bit.
updatePathMetric(pathMetric, currentListSize, 0, currentBit, polarParams->N, polarParams->n + 1, 2 * listSize, llr);
} else { // Information or CRC bit.
updatePathMetric2(pathMetric, currentListSize, currentBit, polarParams->N, polarParams->n + 1, 2 * listSize, llr);
for (int i = 0; i < currentListSize; i++) {
for (int j = 0; j < polarParams->N; j++) {
for (int k = 0; k < (polarParams->n+1); k++) {
bit[j][k][i+currentListSize]=bit[j][k][i];
llr[j][k][i+currentListSize]=llr[j][k][i];
for (int k = 0; k < (polarParams->n + 1); k++) {
bit[j][k][i + currentListSize] = bit[j][k][i];
llr[j][k][i + currentListSize] = llr[j][k][i];
}
}
}
for (int i = 0; i < currentListSize; i++) {
bit[currentBit][0][i]=0;
crcState[i+currentListSize]=crcState[i];
bit[currentBit][0][i] = 0;
crcState[i + currentListSize] = crcState[i];
}
for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1;
for (int i = currentListSize; i < 2 * currentListSize; i++)
bit[currentBit][0][i] = 1;
bitUpdated[currentBit][0]=1;
updateCrcChecksum2(polarParams->crcParityBits, 2*listSize, crcChecksum,
polarParams->K, polarParams->crcParityBits, extended_crc_generator_matrix,
currentListSize, nonFrozenBit, polarParams->crcParityBits);
currentListSize*=2;
bitUpdated[currentBit][0] = 1;
updateCrcChecksum2(polarParams->crcParityBits,
2 * listSize,
crcChecksum,
polarParams->K,
polarParams->crcParityBits,
extended_crc_generator_matrix,
currentListSize,
nonFrozenBit,
polarParams->crcParityBits);
currentListSize *= 2;
//Keep only the best "listSize" number of entries.
// Keep only the best "listSize" number of entries.
if (currentListSize > listSize) {
for (uint i = 0; i < 2 * listSize; i++)
listIndex[i] = i;
@@ -456,7 +474,7 @@ int8_t polar_decoder_dci(double *input,
int swaps = 0;
for (uint j = listSize; j < (2 * listSize - i) - 1; j++) {
if (listIndex[j+1] > listIndex[j]) {
if (listIndex[j + 1] > listIndex[j]) {
int tempInd = listIndex[j];
listIndex[j] = listIndex[j + 1];
listIndex[j + 1] = tempInd;
@@ -468,30 +486,30 @@ int8_t polar_decoder_dci(double *input,
break;
}
//First, backup the best "listSize" number of entries.
for (int k=(listSize-1); k>0; k--) {
for (int i=0; i<polarParams->N; i++) {
for (int j=0; j<(polarParams->n+1); j++) {
bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]];
llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]];
// First, backup the best "listSize" number of entries.
for (int k = (listSize - 1); k > 0; k--) {
for (int i = 0; i < polarParams->N; i++) {
for (int j = 0; j < (polarParams->n + 1); j++) {
bit[i][j][listIndex[(2 * listSize - 1) - k]] = bit[i][j][listIndex[k]];
llr[i][j][listIndex[(2 * listSize - 1) - k]] = llr[i][j][listIndex[k]];
}
}
}
for (int k=(listSize-1); k>0; k--) {
for (int k = (listSize - 1); k > 0; k--) {
for (int i = 0; i < polarParams->crcParityBits; i++) {
crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]];
crcChecksum[i][listIndex[(2 * listSize - 1) - k]] = crcChecksum[i][listIndex[k]];
}
}
for (int k = (listSize - 1); k > 0; k--)
crcState[listIndex[(2 * listSize - 1) - k]] = crcState[listIndex[k]];
//Copy the best "listSize" number of entries to the first indices.
// Copy the best "listSize" number of entries to the first indices.
for (int k = 0; k < listSize; k++) {
if (k > listIndex[k]) {
copyIndex = listIndex[(2*listSize-1)-k];
} else { //Use the backup.
copyIndex = listIndex[(2 * listSize - 1) - k];
} else { // Use the backup.
copyIndex = listIndex[k];
}
@@ -505,40 +523,40 @@ int8_t polar_decoder_dci(double *input,
for (int k = 0; k < listSize; k++) {
if (k > listIndex[k]) {
copyIndex = listIndex[(2*listSize-1)-k];
} else { //Use the backup.
copyIndex = listIndex[(2 * listSize - 1) - k];
} else { // Use the backup.
copyIndex = listIndex[k];
}
for (int i = 0; i < polarParams->crcParityBits; i++) {
crcChecksum[i][k]=crcChecksum[i][copyIndex];
crcChecksum[i][k] = crcChecksum[i][copyIndex];
}
}
for (int k = 0; k < listSize; k++) {
if (k > listIndex[k]) {
copyIndex = listIndex[(2*listSize-1)-k];
} else { //Use the backup.
copyIndex = listIndex[(2 * listSize - 1) - k];
} else { // Use the backup.
copyIndex = listIndex[k];
}
crcState[k]=crcState[copyIndex];
crcState[k] = crcState[copyIndex];
}
currentListSize = listSize;
}
for (int i=0; i<polarParams->crcParityBits; i++) {
if (last1ind[i]==nonFrozenBit) {
checkCrcBits=i;
for (int i = 0; i < polarParams->crcParityBits; i++) {
if (last1ind[i] == nonFrozenBit) {
checkCrcBits = i;
break;
}
}
if ( checkCrcBits > (-1) ) {
if (checkCrcBits > (-1)) {
for (uint i = 0; i < currentListSize; i++) {
if (crcChecksum[checkCrcBits][i]!=extended_crc_scrambling_pattern[checkCrcBits]) {
crcState[i]=0; //0=False, 1=True
if (crcChecksum[checkCrcBits][i] != extended_crc_scrambling_pattern[checkCrcBits]) {
crcState[i] = 0; // 0=False, 1=True
}
}
}
@@ -546,15 +564,15 @@ int8_t polar_decoder_dci(double *input,
for (uint i = 0; i < currentListSize; i++)
decoderIterationCheck += crcState[i];
if (decoderIterationCheck==0) {
//perror("[SCL polar decoder] All list entries have failed the CRC checks.");
if (decoderIterationCheck == 0) {
// perror("[SCL polar decoder] All list entries have failed the CRC checks.");
polarReturn(polarParams);
return -1;
}
nonFrozenBit++;
decoderIterationCheck=0;
checkCrcBits=-1;
decoderIterationCheck = 0;
checkCrcBits = -1;
}
}
@@ -565,19 +583,19 @@ int8_t polar_decoder_dci(double *input,
uint8_t nr_polar_A[polarParams->payloadBits];
for (uint i = 0; i < fmin(listSize, (pow(2, polarParams->crcCorrectionBits))); i++) {
if ( crcState[listIndex[i]] == 1 ) {
if (crcState[listIndex[i]] == 1) {
uint8_t nr_polar_U[polarParams->N];
for (int j = 0; j < polarParams->N; j++)
nr_polar_U[j] = bit[j][0][listIndex[i]];
//Extract the information bits (û to ĉ)
// Extract the information bits (û to ĉ)
uint8_t nr_polar_CPrime[polarParams->N];
nr_polar_info_bit_extraction(nr_polar_U, nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N);
//Deinterleaving (ĉ to b)
// Deinterleaving (ĉ to b)
uint8_t nr_polar_B[polarParams->K];
nr_polar_deinterleaver(nr_polar_CPrime, nr_polar_B, polarParams->interleaving_pattern, polarParams->K);
//Remove the CRC (â)
// Remove the CRC (â)
memcpy(nr_polar_A, nr_polar_B, polarParams->payloadBits);
break;
}
@@ -592,32 +610,60 @@ int8_t polar_decoder_dci(double *input,
return 0;
}
void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) {
AssertFatal(polarParams->K > 17, "K = %d < 18, is not allowed\n",polarParams->K);
AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K);
int bit_i,ip,ipmod64;
int numbytes = polarParams->K>>3;
int residue = polarParams->K & 7;
static inline void nr_polar_rate_matching_int16(int16_t *input,
int16_t *output,
const uint16_t *rmp,
const uint16_t K,
const uint16_t N,
const uint16_t E,
const uint8_t i_bil)
{
if (E >= N) { // repetition
memset(output, 0, N * sizeof(*output));
for (int i = 0; i <= E - 1; i++)
output[rmp[i]] += input[i];
} else {
if ((K / (double)E) <= (7.0 / 16))
memset(output, 0, N * sizeof(*output)); // puncturing
else { // shortening
for (int i = 0; i <= N - 1; i++)
output[i] = 32767; // instead of INFINITY, to prevent [-Woverflow]
}
if (residue > 0)
numbytes++;
for (int i = 0; i <= E - 1; i++)
output[rmp[i]] = input[i];
}
}
for (int byte=0; byte<numbytes; byte++) {
int numbits = byte < (polarParams->K >> 3) ? 8 : residue;
static inline void nr_polar_info_extraction_from_u(uint64_t *Cprime,
const uint8_t *u,
const uint8_t *information_bit_pattern,
const uint8_t *parity_check_bit_pattern,
const uint16_t *interleaving_pattern,
uint16_t N,
uint8_t n_pc,
int K)
{
int k = 0;
for (int i=0; i<numbits; i++) {
// flip bit endian for B
ip = polarParams->K - 1 - polarParams->interleaving_pattern[(8 * byte) + i];
ipmod64 = ip&63;
AssertFatal(ip<128,"ip = %d\n",ip);
for (int val=0; val<256; val++) {
bit_i=(val>>i)&1;
if (ip < 64)
polarParams->B_tab0[byte][val] |= ((uint64_t)bit_i) << ipmod64;
else
polarParams->B_tab1[byte][val] |= ((uint64_t)bit_i) << ipmod64;
if (n_pc > 0) {
for (int n = 0; n < N; n++) {
if (information_bit_pattern[n] == 1 && parity_check_bit_pattern[n] == 0) {
int targetBit = K - 1 - interleaving_pattern[k];
int k1 = targetBit >> 6;
int k2 = targetBit & 63;
Cprime[k1] |= (uint64_t)u[n] << k2;
k++;
}
}
} else {
for (int n = 0; n < N; n++) {
if (information_bit_pattern[n] == 1) {
int targetBit = K - 1 - interleaving_pattern[k];
int k1 = targetBit >> 6;
int k2 = targetBit & 63;
Cprime[k1] |= (uint64_t)u[n] << k2;
k++;
}
}
}
@@ -630,12 +676,12 @@ uint32_t polar_decoder_int16(int16_t *input,
uint16_t messageLength,
uint8_t aggregation_level)
{
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true);
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
const uint N = polarParams->N;
#ifdef POLAR_CODING_DEBUG
printf("\nRX\n");
printf("rm:");
for (int i = 0; i < polarParams->N; i++) {
for (int i = 0; i < N; i++) {
if (i % 4 == 0) {
printf(" ");
}
@@ -644,25 +690,28 @@ uint32_t polar_decoder_int16(int16_t *input,
printf("\n");
#endif
int16_t d_tilde[polarParams->N];
nr_polar_rate_matching_int16(input,
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,
polarParams->N,
polarParams->encoderLength,
N,
E,
polarParams->i_bil);
for (int i=0; i<polarParams->N; i++) {
if (d_tilde[i] < -128)
d_tilde[i] = -128;
else if (d_tilde[i] > 127)
d_tilde[i] = 128;
}
#ifdef POLAR_CODING_DEBUG
printf("d: ");
for (int i = 0; i < polarParams->N; i++) {
for (int i = 0; i < N; i++) {
if (i % 4 == 0) {
printf(" ");
}
@@ -670,15 +719,13 @@ uint32_t polar_decoder_int16(int16_t *input,
}
printf("\n");
#endif
memcpy(polarParams->tree.root->alpha, d_tilde, sizeof(d_tilde));
uint8_t nr_polar_U[polarParams->N];
uint8_t nr_polar_U[N];
memset(nr_polar_U, 0, sizeof(nr_polar_U));
generic_polar_decoder(polarParams, polarParams->tree.root, 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 < polarParams->N; i++) {
for (int i = 0; i < N; i++) {
if (i % 4 == 0) {
printf(" ");
}
@@ -688,13 +735,15 @@ uint32_t polar_decoder_int16(int16_t *input,
#endif
// Extract the information bits (û to ĉ)
uint64_t Cprime[4]= {0};
nr_polar_info_extraction_from_u(Cprime,
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->N,
polarParams->n_pc);
polarParams->interleaving_pattern,
N,
polarParams->n_pc,
polarParams->K);
#ifdef POLAR_CODING_DEBUG
printf("c: ");
@@ -704,95 +753,66 @@ uint32_t polar_decoder_int16(int16_t *input,
}
int n1 = n >> 6;
int n2 = n - (n1 << 6);
printf("%lu", (Cprime[n1] >> n2) & 1);
printf("%lu", (B[n1] >> n2) & 1);
}
printf("\n");
#endif
//Deinterleaving (ĉ to b)
uint8_t *Cprimebyte = (uint8_t *)Cprime;
uint64_t B[4] = {0};
if (polarParams->K<65) {
B[0] = polarParams->B_tab0[0][Cprimebyte[0]] | polarParams->B_tab0[1][Cprimebyte[1]] | polarParams->B_tab0[2][Cprimebyte[2]]
| polarParams->B_tab0[3][Cprimebyte[3]] | polarParams->B_tab0[4][Cprimebyte[4]] | polarParams->B_tab0[5][Cprimebyte[5]]
| polarParams->B_tab0[6][Cprimebyte[6]] | polarParams->B_tab0[7][Cprimebyte[7]];
} else if (polarParams->K<129) {
int len = polarParams->K/8;
if ((polarParams->K & 7) > 0)
len++;
for (int k=0; k<len; k++) {
B[0] |= polarParams->B_tab0[k][Cprimebyte[k]];
B[1] |= polarParams->B_tab1[k][Cprimebyte[k]];
}
}
#ifdef POLAR_CODING_DEBUG
int B_array = (polarParams->K + 63) >> 6;
int n_start = (B_array << 6) - polarParams->K;
printf("b: ");
for (int n = 0; n < polarParams->K; 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
int len=polarParams->payloadBits;
//int len_mod64=len&63;
int len = polarParams->payloadBits;
// int len_mod64=len&63;
int crclen = polarParams->crcParityBits;
uint64_t rxcrc=B[0]&((1<<crclen)-1);
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");
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 (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) {
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];
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;
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
@@ -819,7 +839,7 @@ uint32_t polar_decoder_int16(int16_t *input,
Cprime[0],
crc,
rxcrc,
crc^rxcrc,
crc ^ rxcrc,
polarParams->payloadBits);
#endif
@@ -28,22 +28,22 @@
* \email turker.yilmaz@eurecom.fr
* \note
* \warning
*/
*/
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include "PHY/sse_intrin.h"
#include "PHY/impl_defs_top.h"
//#define DEBUG_NEW_IMPL 1
// #define DEBUG_NEW_IMPL 1
static inline void updateBit(uint8_t listSize,
uint16_t row,
uint16_t col,
uint16_t xlen,
uint8_t ylen,
int zlen,
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen])
uint16_t row,
uint16_t col,
uint16_t xlen,
uint8_t ylen,
int zlen,
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen])
{
const uint offset = (xlen / (pow(2, (ylen - col))));
@@ -64,18 +64,12 @@ static inline void updateBit(uint8_t listSize,
bitU[row][col] = 1;
}
static inline void computeLLR(uint16_t row,
uint16_t col,
uint8_t i,
uint16_t offset,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen])
static inline void
computeLLR(uint16_t row, uint16_t col, uint8_t i, uint16_t offset, int xlen, int ylen, int zlen, double llr[xlen][ylen][zlen])
{
double a = llr[row][col + 1][i];
double b = llr[row + offset][col + 1][i];
llr[row][col][i] = log((exp(a + b) + 1) / (exp(a) + exp(b))); //eq. (8a)
llr[row][col][i] = log((exp(a + b) + 1) / (exp(a) + exp(b))); // eq. (8a)
}
void updateLLR(uint8_t listSize,
@@ -113,14 +107,13 @@ void updateLLR(uint8_t listSize,
}
void updatePathMetric(double *pathMetric,
uint8_t listSize,
uint8_t bitValue,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen]
)
uint8_t listSize,
uint8_t bitValue,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen])
{
const int multiplier = (2 * bitValue) - 1;
for (uint i = 0; i < listSize; i++)
@@ -128,12 +121,12 @@ void updatePathMetric(double *pathMetric,
}
void updatePathMetric2(double *pathMetric,
uint8_t listSize,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen])
uint8_t listSize,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen])
{
double tempPM[listSize];
memcpy(tempPM, pathMetric, (sizeof(double) * listSize));
@@ -149,271 +142,308 @@ void updatePathMetric2(double *pathMetric,
pathMetric[i] = tempPM[(i - listSize)] + log(1 + exp(multiplier * llr[row][0][(i - listSize)])); // eq. (11b)
}
decoder_node_t *new_decoder_node(int first_leaf_index, int level) {
decoder_node_t *node=(decoder_node_t *)malloc(sizeof(decoder_node_t));
node->first_leaf_index=first_leaf_index;
node->level=level;
node->Nv = 1<<level;
node->leaf = 0;
node->left=(decoder_node_t *)NULL;
node->right=(decoder_node_t *)NULL;
node->all_frozen=0;
node->alpha = (int16_t*)malloc16(node->Nv*sizeof(int16_t));
node->beta = (int16_t*)malloc16(node->Nv*sizeof(int16_t));
memset((void*)node->beta,-1,node->Nv*sizeof(int16_t));
return(node);
}
decoder_node_t *add_nodes(int level, int first_leaf_index, t_nrPolar_params *polarParams) {
int all_frozen_below = 1;
int Nv = 1<<level;
decoder_node_t *new_node = new_decoder_node(first_leaf_index, level);
#ifdef DEBUG_NEW_IMPL
printf("New node %d order %d, level %d\n",polarParams->tree.num_nodes,Nv,level);
#endif
polarParams->tree.num_nodes++;
if (level==0) {
#ifdef DEBUG_NEW_IMPL
printf("leaf %d (%s)\n", first_leaf_index, polarParams->information_bit_pattern[first_leaf_index]==1 ? "information or crc" : "frozen");
#endif
new_node->leaf=1;
new_node->all_frozen = polarParams->information_bit_pattern[first_leaf_index]==0 ? 1 : 0;
return new_node; // this is a leaf node
}
for (int i=0;i<Nv;i++) {
if (polarParams->information_bit_pattern[i+first_leaf_index]>0) {
all_frozen_below = 0;
break;
}
}
if (all_frozen_below==0)
new_node->left = add_nodes(level - 1, first_leaf_index, polarParams);
else {
#ifdef DEBUG_NEW_IMPL
printf("aggregating frozen bits %d ... %d at level %d (%s)\n",first_leaf_index,first_leaf_index+Nv-1,level,((first_leaf_index/Nv)&1)==0?"left":"right");
#endif
new_node->leaf=1;
new_node->all_frozen=1;
}
if (all_frozen_below==0)
new_node->right = add_nodes(level - 1, first_leaf_index + (Nv / 2), polarParams);
#ifdef DEBUG_NEW_IMPL
printf("new_node (%d): first_leaf_index %d, left %p, right %p\n",Nv,first_leaf_index,new_node->left,new_node->right);
#endif
return(new_node);
}
void delete_nodes(decoder_node_t * n) {
if (n) {
if(n->left)
delete_nodes(n->left);
if(n->right)
delete_nodes(n->right);
free(n->alpha);
free(n->beta);
free(n);
}
}
void delete_decoder_tree(t_nrPolar_params *polarParams) {
if (polarParams->tree.root)
delete_nodes(polarParams->tree.root);
}
void build_decoder_tree(t_nrPolar_params *polarParams)
static inline decoder_node_t *new_decoder_node(simde__m256i **buffer,
const int level,
const int first_leaf_index,
const bool leaf,
const bool frozen)
{
polarParams->tree.num_nodes=0;
polarParams->tree.root = add_nodes(polarParams->n,0,polarParams);
#ifdef DEBUG_NEW_IMPL
printf("root : left %p, right %p\n",polarParams->tree.root->left,polarParams->tree.root->right);
#endif
int leaf_sz = 1 << level;
// we will use SIMD128 minimum
leaf_sz = (leaf_sz + 7) & ~7;
if (leaf_sz > 15) // we will use SIMD256
leaf_sz = (leaf_sz + 15) & ~15;
const int tree_sz = (sizeof(decoder_node_t) + 31) & ~31;
uintptr_t tmp = (uintptr_t)*buffer;
tmp = (tmp + sizeof(**buffer) - 1) & ~(sizeof(**buffer) - 1);
decoder_node_t *node = (decoder_node_t *)tmp;
*buffer = (simde__m256i *)(tmp + tree_sz + leaf_sz * sizeof(int16_t) + leaf_sz);
*node = (decoder_node_t){.first_leaf_index = first_leaf_index,
.level = level,
.leaf = leaf,
.all_frozen = frozen,
.alpha = tree_sz,
.beta = tree_sz + leaf_sz * sizeof(int16_t),
.betaInit = false};
return (node);
}
static void applyFtoleft(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output)
static inline decoder_node_t *add_nodes(decoder_tree_t *tree,
int level,
int first_leaf_index,
const uint8_t *information_bit_pattern,
simde__m256i **buffer)
{
int16_t *alpha_v=node->alpha;
int16_t *alpha_l=node->left->alpha;
int16_t *betal = node->left->beta;
int16_t a,b,absa,absb,maska,maskb,minabs;
if (level == 0) {
#ifdef DEBUG_NEW_IMPL
printf("leaf %d (%s)\n", first_leaf_index, information_bit_pattern[first_leaf_index] == 1 ? "information or crc" : "frozen");
#endif
return new_decoder_node(buffer, level, first_leaf_index, true, information_bit_pattern[first_leaf_index] == 0);
}
int Nv = 1 << level;
const uint8_t *ptr = information_bit_pattern + first_leaf_index;
const uint8_t *end = ptr + Nv;
bool all_frozen_below = true;
while (ptr < end && all_frozen_below) {
all_frozen_below = *ptr++ <= 0;
}
if (all_frozen_below) {
return new_decoder_node(buffer, level, first_leaf_index, true, true);
}
decoder_node_t *new_node = new_decoder_node(buffer, level, first_leaf_index, false, false);
new_node->left = add_nodes(tree, level - 1, first_leaf_index, information_bit_pattern, buffer);
new_node->right = add_nodes(tree, level - 1, first_leaf_index + (Nv / 2), information_bit_pattern, buffer);
return (new_node);
}
void build_decoder_tree(t_nrPolar_params *pp)
{
uintptr_t tmp = (uintptr_t)pp->decoder.buffer;
tmp = (tmp + sizeof(*pp->decoder.buffer) - 1) & ~(sizeof(*pp->decoder.buffer) - 1);
simde__m256i *buffer = (simde__m256i *)tmp;
pp->decoder.root = add_nodes(&pp->decoder, pp->n, 0, pp->information_bit_pattern, &buffer);
AssertFatal(buffer < pp->decoder.buffer + sizeofArray(pp->decoder.buffer),
"Arbitrary size too small (also check arbitrary max size of the entire polar decoder) %ld instead of max %ld\n",
buffer - pp->decoder.buffer,
sizeofArray(pp->decoder.buffer));
}
static inline void applyFtoleft(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output)
{
int16_t *alpha_v = treeAlpha(node);
int16_t *alpha_l = treeAlpha(node->left);
int8_t *betal = treeBeta(node->left);
#ifdef DEBUG_NEW_IMPL
printf("applyFtoleft %d, Nv %d (level %d,node->left (leaf %d, AF %d))\n",node->first_leaf_index,node->Nv,node->level,node->left->leaf,node->left->all_frozen);
printf("applyFtoleft %d, Nv %d (level %d,node->left (leaf %d, AF %d))\n",
node->first_leaf_index,
node->Nv,
node->level,
node->left->leaf,
node->left->all_frozen);
for (int i = 0; i < node->Nv; i++)
printf("i%d (frozen %d): alpha_v[i] = %d\n", i, 1 - pp->information_bit_pattern[node->first_leaf_index + i], alpha_v[i]);
#endif
assert(node->level);
const int sz = 1 << (node->level - 1);
if (node->left->all_frozen == 0) {
int avx2mod = (node->Nv/2)&15;
int avx2mod = sz & 15;
if (avx2mod == 0) {
simde__m256i a256,b256,absa256,absb256,minabs256;
int avx2len = node->Nv/2/16;
int avx2len = sz / 16;
// printf("avx2len %d\n",avx2len);
for (int i=0;i<avx2len;i++) {
a256 =((simde__m256i*)alpha_v)[i];
b256 =((simde__m256i*)alpha_v)[i+avx2len];
absa256 =simde_mm256_abs_epi16(a256);
absb256 =simde_mm256_abs_epi16(b256);
minabs256 =simde_mm256_min_epi16(absa256,absb256);
((simde__m256i*)alpha_l)[i] =simde_mm256_sign_epi16(minabs256,simde_mm256_sign_epi16(a256,b256));
for (int i = 0; i < avx2len; i++) {
simde__m256i a256 = ((simde__m256i *)alpha_v)[i];
simde__m256i b256 = ((simde__m256i *)alpha_v)[i + avx2len];
simde__m256i absa256 = simde_mm256_abs_epi16(a256);
simde__m256i absb256 = simde_mm256_abs_epi16(b256);
simde__m256i minabs256 = simde_mm256_min_epi16(absa256, absb256);
((simde__m256i *)alpha_l)[i] = simde_mm256_sign_epi16(minabs256, simde_mm256_sign_epi16(a256, b256));
}
} else if (avx2mod == 8) {
simde__m128i a128 = *((simde__m128i *)alpha_v);
simde__m128i b128 = ((simde__m128i *)alpha_v)[1];
simde__m128i absa128 = simde_mm_abs_epi16(a128);
simde__m128i absb128 = simde_mm_abs_epi16(b128);
simde__m128i minabs128 = simde_mm_min_epi16(absa128, absb128);
*((simde__m128i *)alpha_l) = simde_mm_sign_epi16(minabs128, simde_mm_sign_epi16(a128, b128));
} else if (avx2mod == 4) {
simde__m64 a64 = *((simde__m64 *)alpha_v);
simde__m64 b64 = ((simde__m64 *)alpha_v)[1];
simde__m64 absa64 = simde_mm_abs_pi16(a64);
simde__m64 absb64 = simde_mm_abs_pi16(b64);
simde__m64 minabs64 = simde_mm_min_pi16(absa64, absb64);
*((simde__m64 *)alpha_l) = simde_mm_sign_pi16(minabs64, simde_mm_sign_pi16(a64, b64));
} else { // equivalent scalar code to above, activated only on non x86/ARM architectures
for (int i = 0; i < sz; i++) {
int16_t a = alpha_v[i];
int16_t b = alpha_v[i + sz];
int16_t maska = a >> 15;
int16_t maskb = b >> 15;
int16_t absa = (a + maska) ^ maska;
int16_t absb = (b + maskb) ^ maskb;
int16_t minabs = absa < absb ? absa : absb;
alpha_l[i] = (maska ^ maskb) == 0 ? minabs : -minabs;
// printf("alphal[%d] %d (%d,%d)\n",i,alpha_l[i],a,b);
}
}
else if (avx2mod == 8) {
simde__m128i a128,b128,absa128,absb128,minabs128;
a128 =*((simde__m128i*)alpha_v);
b128 =((simde__m128i*)alpha_v)[1];
absa128 =simde_mm_abs_epi16(a128);
absb128 =simde_mm_abs_epi16(b128);
minabs128 =simde_mm_min_epi16(absa128,absb128);
*((simde__m128i*)alpha_l) =simde_mm_sign_epi16(minabs128,simde_mm_sign_epi16(a128,b128));
}
else if (avx2mod == 4) {
simde__m64 a64,b64,absa64,absb64,minabs64;
a64 =*((simde__m64*)alpha_v);
b64 =((simde__m64*)alpha_v)[1];
absa64 =simde_mm_abs_pi16(a64);
absb64 =simde_mm_abs_pi16(b64);
minabs64 =simde_mm_min_pi16(absa64,absb64);
*((simde__m64*)alpha_l) =simde_mm_sign_pi16(minabs64,simde_mm_sign_pi16(a64,b64));
}
else
{ // equivalent scalar code to above, activated only on non x86/ARM architectures
for (int i=0;i<node->Nv/2;i++) {
a=alpha_v[i];
b=alpha_v[i+(node->Nv/2)];
maska=a>>15;
maskb=b>>15;
absa=(a+maska)^maska;
absb=(b+maskb)^maskb;
minabs = absa<absb ? absa : absb;
alpha_l[i] = (maska^maskb)==0 ? minabs : -minabs;
// printf("alphal[%d] %d (%d,%d)\n",i,alpha_l[i],a,b);
}
}
if (node->Nv == 2) { // apply hard decision on left node
betal[0] = (alpha_l[0]>0) ? -1 : 1;
if (sz == 1) { // apply hard decision on left node
const int tmp = alpha_l[0] <= 0;
betal[0] = tmp * 2 - 1;
node->left->betaInit = true;
#ifdef DEBUG_NEW_IMPL
printf("betal[0] %d (%p)\n",betal[0],&betal[0]);
printf("betal[0] %d (%p)\n", betal[0], &betal[0]);
#endif
output[node->first_leaf_index] = (1 + betal[0]) >> 1;
output[node->first_leaf_index] = tmp;
#ifdef DEBUG_NEW_IMPL
printf("Setting bit %d to %d (LLR %d)\n",node->first_leaf_index,(betal[0]+1)>>1,alpha_l[0]);
printf("Setting bit %d to %d (LLR %d)\n", node->first_leaf_index, (betal[0] + 1) >> 1, alpha_l[0]);
#endif
}
}
}
static void applyGtoright(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output)
static inline void applyGtoright(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output)
{
int16_t *alpha_v=node->alpha;
int16_t *alpha_r=node->right->alpha;
int16_t *betal = node->left->beta;
int16_t *betar = node->right->beta;
int16_t *alpha_v = treeAlpha(node);
int16_t *alpha_r = treeAlpha(node->right);
int8_t *betal = treeBeta(node->left);
int8_t *betar = treeBeta(node->right);
#ifdef DEBUG_NEW_IMPL
printf("applyGtoright %d, Nv %d (level %d), (leaf %d, AF %d)\n",node->first_leaf_index,node->Nv,node->level,node->right->leaf,node->right->all_frozen);
printf("applyGtoright %d, Nv %d (level %d), (leaf %d, AF %d)\n",
node->first_leaf_index,
node->Nv,
node->level,
node->right->leaf,
node->right->all_frozen);
#endif
if (node->right->all_frozen == 0) {
int avx2mod = (node->Nv/2)&15;
if (avx2mod == 0) {
int avx2len = node->Nv/2/16;
for (int i=0;i<avx2len;i++) {
((simde__m256i *)alpha_r)[i] =
simde_mm256_subs_epi16(((simde__m256i *)alpha_v)[i + avx2len],
simde_mm256_sign_epi16(((simde__m256i *)alpha_v)[i], ((simde__m256i *)betal)[i]));
assert(node->level);
const int sz = 1 << (node->level - 1);
if (node->right->all_frozen == 0) {
if (!node->left->betaInit) {
for (int i = 0; i < sz; i++) {
int temp_alpha_r = alpha_v[i + sz] + alpha_v[i];
if (temp_alpha_r > SHRT_MAX) {
alpha_r[i] = SHRT_MAX;
} else if (temp_alpha_r < -SHRT_MAX) {
alpha_r[i] = -SHRT_MAX;
} else {
alpha_r[i] = temp_alpha_r;
}
}
} else {
int avx2mod = sz & 15;
if (avx2mod == 0) {
int avx2len = sz / 16;
for (int i = 0; i < avx2len; i++) {
simde__m256i tmp =
simde_mm256_sign_epi16(((simde__m256i *)alpha_v)[i], simde_mm256_cvtepi8_epi16(((simde__m128i *)betal)[i]));
((simde__m256i *)alpha_r)[i] = simde_mm256_subs_epi16(((simde__m256i *)alpha_v)[i + avx2len], tmp);
}
} else if (avx2mod == 8) {
simde__m128i tmp = simde_mm_sign_epi16(((simde__m128i *)alpha_v)[0], simde_mm_cvtepi8_epi16(((simde__m128i *)betal)[0]));
((simde__m128i *)alpha_r)[0] = simde_mm_subs_epi16(((simde__m128i *)alpha_v)[1], tmp);
} else {
simde__m128i tmp = simde_mm_sign_epi16(*(simde__m128i *)alpha_v, simde_mm_cvtepi8_epi16(*(simde__m128i *)betal));
simde__m128i tmp2 = simde_mm_loadu_si128((simde__m128i *)(alpha_v + sz));
simde__m128i res = simde_mm_subs_epi16(tmp2, tmp);
simde_mm_storeu_si128(alpha_r, res);
}
}
else if (avx2mod == 8) {
((simde__m128i *)alpha_r)[0] = simde_mm_subs_epi16(((simde__m128i *)alpha_v)[1],simde_mm_sign_epi16(((simde__m128i *)alpha_v)[0],((simde__m128i *)betal)[0]));
}
else if (avx2mod == 4) {
((simde__m64 *)alpha_r)[0] = simde_mm_subs_pi16(((simde__m64 *)alpha_v)[1],simde_mm_sign_pi16(((simde__m64 *)alpha_v)[0],((simde__m64 *)betal)[0]));
}
else
{
int temp_alpha_r;
for (int i = 0; i < node->Nv / 2; i++) {
temp_alpha_r = alpha_v[i + (node->Nv / 2)] - (betal[i] * alpha_v[i]);
if (temp_alpha_r > SHRT_MAX) {
alpha_r[i] = SHRT_MAX;
} else if (temp_alpha_r < -SHRT_MAX) {
alpha_r[i] = -SHRT_MAX;
} else {
alpha_r[i] = temp_alpha_r;
}
}
}
if (node->Nv == 2) { // apply hard decision on right node
betar[0] = (alpha_r[0]>0) ? -1 : 1;
output[node->first_leaf_index + 1] = (1 + betar[0]) >> 1;
if (sz == 1) { // apply hard decision on right node
int tmp = alpha_r[0] <= 0;
betar[0] = tmp * 2 - 1;
node->right->betaInit = true;
output[node->first_leaf_index + 1] = tmp;
#ifdef DEBUG_NEW_IMPL
printf("Setting bit %d to %d (LLR %d)\n",node->first_leaf_index+1,(betar[0]+1)>>1,alpha_r[0]);
printf("Setting bit %d to %d (LLR %d)\n", node->first_leaf_index + 1, (betar[0] + 1) >> 1, alpha_r[0]);
#endif
}
}
}
}
static const int16_t all1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
static const int64_t all11[4] = {-1, -1, -1, -1};
void computeBeta(const t_nrPolar_params *pp,decoder_node_t *node) {
int16_t *betav = node->beta;
int16_t *betal = node->left->beta;
int16_t *betar = node->right->beta;
static inline void computeBeta(decoder_node_t *node)
{
int8_t *betav = treeBeta(node);
int8_t *betal = treeBeta(node->left);
int8_t *betar = treeBeta(node->right);
#ifdef DEBUG_NEW_IMPL
printf("Computing beta @ level %d first_leaf_index %d (all_frozen %d)\n",node->level,node->first_leaf_index,node->left->all_frozen);
printf("Computing beta @ level %d first_leaf_index %d (all_frozen %d)\n",
node->level,
node->first_leaf_index,
node->left->all_frozen);
#endif
if (node->left->all_frozen==0) { // if left node is not aggregation of frozen bits
int avx2mod = (node->Nv/2)&15;
register simde__m256i allones=*((simde__m256i*)all1);
assert(node->level);
const int sz = 1 << (node->level - 1);
if (node->left->all_frozen == 0) { // if left node is not aggregation of frozen bits
if (!node->left->betaInit) {
memset(betal, -1, sz);
node->left->betaInit = true;
}
if (!node->right->betaInit) {
memset(betar, -1, sz);
node->right->betaInit = true;
}
int avx2mod = sz & 31;
if (avx2mod == 0) {
int avx2len = node->Nv/2/16;
for (int i=0;i<avx2len;i++) {
((simde__m256i*)betav)[i] = simde_mm256_or_si256(simde_mm256_cmpeq_epi16(((simde__m256i*)betar)[i],
((simde__m256i*)betal)[i]),allones);
int avx2len = sz / 16;
for (int i = 0; i < avx2len; i++) {
((simde__m256i *)betav)[i] =
simde_mm256_xor_si256(simde_mm256_xor_si256(((simde__m256i *)betar)[i], ((simde__m256i *)betal)[i]),
*(simde__m256i *)all11);
}
} else {
((simde__m128i *)betav)[0] =
simde_mm_xor_si128(simde_mm_xor_si128(((simde__m128i *)betar)[0], ((simde__m128i *)betal)[0]), *((simde__m128i *)all11));
}
else if (avx2mod == 8) {
((simde__m128i*)betav)[0] = simde_mm_or_si128(simde_mm_cmpeq_epi16(((simde__m128i*)betar)[0],
((simde__m128i*)betal)[0]),*((simde__m128i*)all1));
}
else if (avx2mod == 4) {
((simde__m64*)betav)[0] = simde_mm_or_si64(simde_mm_cmpeq_pi16(((simde__m64*)betar)[0],
((simde__m64*)betal)[0]),*((simde__m64*)all1));
}
else
{
for (int i=0;i<node->Nv/2;i++) {
betav[i] = (betal[i] != betar[i]) ? 1 : -1;
}
}
} else {
assert(node->right->betaInit);
memcpy(betav, betar, sz * sizeof(*betav));
node->betaInit = true;
}
else memcpy((void*)&betav[0],betar,(node->Nv/2)*sizeof(int16_t));
memcpy((void*)&betav[node->Nv/2],betar,(node->Nv/2)*sizeof(int16_t));
assert(node->right->betaInit);
memcpy(&betav[sz], betar, sz * sizeof(*betav));
node->betaInit = true;
}
void generic_polar_decoder(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U)
void generic_polar_decoder_recursive(t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U)
{
// Apply F to left
applyFtoleft(pp, node, nr_polar_U);
int iter = pp->tree_linearization.iter++;
pp->tree_linearization.op_list[iter].op_code = POLAR_OP_CODE_LEFT;
pp->tree_linearization.op_list[iter].node = node;
// if left is not a leaf recurse down to the left
if (node->left->leaf==0)
generic_polar_decoder(pp, node->left, nr_polar_U);
if (node->left->leaf == 0)
generic_polar_decoder_recursive(pp, node->left, nr_polar_U);
applyGtoright(pp, node, nr_polar_U);
if (node->right->leaf == 0)
generic_polar_decoder(pp, node->right, nr_polar_U);
iter = pp->tree_linearization.iter++;
pp->tree_linearization.op_list[iter].op_code = POLAR_OP_CODE_RIGHT;
pp->tree_linearization.op_list[iter].node = node;
computeBeta(pp, node);
if (node->right->leaf == 0)
generic_polar_decoder_recursive(pp, node->right, nr_polar_U);
computeBeta(node);
iter = pp->tree_linearization.iter++;
pp->tree_linearization.op_list[iter].op_code = POLAR_OP_CODE_BETA;
pp->tree_linearization.op_list[iter].node = node;
}
void generic_polar_decoder(t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U)
{
if (pp->tree_linearization.is_initialized == false) {
pp->tree_linearization.iter = 0;
generic_polar_decoder_recursive(pp, node, nr_polar_U);
pp->tree_linearization.is_initialized = true;
AssertFatal(pp->tree_linearization.iter < sizeofArray(pp->tree_linearization.op_list),
"Arbitrary size %lu is too small, number of operations is %d",
sizeofArray(pp->tree_linearization.op_list),
pp->tree_linearization.iter);
} else {
for (int i = 0; i < pp->tree_linearization.iter; i++) {
decoder_node_t *n = pp->tree_linearization.op_list[i].node;
switch (pp->tree_linearization.op_list[i].op_code) {
case POLAR_OP_CODE_LEFT:
applyFtoleft(pp, n, nr_polar_U);
break;
case POLAR_OP_CODE_RIGHT:
applyGtoright(pp, n, nr_polar_U);
break;
case POLAR_OP_CODE_BETA:
computeBeta(n);
}
}
}
}
+128 -123
View File
@@ -28,7 +28,7 @@
* \email raymond.knopp@eurecom.fr, turker.yilmaz@eurecom.fr
* \note
* \warning
*/
*/
#ifndef __NR_POLAR_DEFS__H__
#define __NR_POLAR_DEFS__H__
@@ -43,42 +43,47 @@
#include "PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "PHY/CODING/coding_defs.h"
//#include "SIMULATION/TOOLS/sim.h"
// #include "SIMULATION/TOOLS/sim.h"
#define NR_POLAR_DECODER_LISTSIZE 8 //uint8_t
#define NR_POLAR_DECODER_LISTSIZE 8 // uint8_t
#define NR_POLAR_AGGREGATION_LEVEL_1_PRIME 149 //uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_2_PRIME 151 //uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_4_PRIME 157 //uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_8_PRIME 163 //uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_16_PRIME 167 //uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_1_PRIME 149 // uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_2_PRIME 151 // uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_4_PRIME 157 // uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_8_PRIME 163 // uint16_t
#define NR_POLAR_AGGREGATION_LEVEL_16_PRIME 167 // uint16_t
static const uint8_t nr_polar_subblock_interleaver_pattern[32] = {0,1,2,4,3,5,6,7,8,16,9,17,10,18,11,19,12,20,13,21,14,22,15,23,24,25,26,28,27,29,30,31};
static const uint8_t nr_polar_subblock_interleaver_pattern[32] = {0, 1, 2, 4, 3, 5, 6, 7, 8, 16, 9, 17, 10, 18, 11, 19,
12, 20, 13, 21, 14, 22, 15, 23, 24, 25, 26, 28, 27, 29, 30, 31};
#define Nmax 1024
#define nmax 10
#define uint128_t __uint128_t
#define POLAR_OP_CODE_LEFT 0
#define POLAR_OP_CODE_RIGHT 1
#define POLAR_OP_CODE_BETA 2
typedef struct decoder_node_t_s {
struct decoder_node_t_s *left;
struct decoder_node_t_s *right;
int level;
int leaf;
int Nv;
int first_leaf_index;
int all_frozen;
int16_t *alpha;
int16_t *beta;
uint64_t level: 16;
uint64_t leaf: 16;
uint64_t first_leaf_index: 16;
uint64_t all_frozen: 1;
uint64_t betaInit: 1;
uint32_t alpha;
uint32_t beta;
} decoder_node_t;
typedef struct decoder_tree_t_s {
decoder_node_t *root;
int num_nodes;
simde__m256i buffer[1024]; // seems enough but to be refined
} decoder_tree_t;
typedef struct nrPolar_params {
//messageType: 0=PBCH, 1=DCI, -1=UCI
// messageType: 0=PBCH, 1=DCI, -1=UCI
struct nrPolar_params *nextPtr __attribute__((aligned(16)));
bool busy;
@@ -100,6 +105,7 @@ typedef struct nrPolar_params {
uint16_t *interleaving_pattern;
uint16_t *rate_matching_pattern;
uint16_t *i_bil_pattern;
const uint16_t *Q_0_Nminus1;
int16_t *Q_I_N;
int16_t *Q_F_N;
@@ -110,20 +116,20 @@ typedef struct nrPolar_params {
const uint8_t **G_N;
int groupsize;
int *rm_tab;
uint64_t cprime_tab0[32][256];
uint64_t cprime_tab1[32][256];
uint64_t B_tab0[32][256];
uint64_t B_tab1[32][256];
// lowercase: bits, Uppercase: Bits stored in bytes
// polar_encoder vectors
decoder_tree_t tree;
uint64_t cprime_tab0[16][256];
uint64_t cprime_tab1[16][256];
decoder_tree_t decoder;
struct {
int iter;
bool is_initialized;
struct {
int op_code;
decoder_node_t *node;
} op_list[600];
} tree_linearization;
} t_nrPolar_params;
void polar_encoder(uint32_t *input,
uint32_t *output,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level);
void polar_encoder(uint32_t *input, uint32_t *output, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level);
void polar_encoder_dci(uint32_t *in,
uint32_t *out,
@@ -162,23 +168,26 @@ int8_t polar_decoder_dci(double *input,
uint16_t messageLength,
uint8_t aggregation_level);
void generic_polar_decoder(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U);
void generic_polar_decoder(t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U);
void computeBeta(const t_nrPolar_params *pp,
decoder_node_t *node);
static inline int16_t *treeAlpha(decoder_node_t *node)
{
return (int16_t *)((uint8_t *)node + node->alpha);
}
static inline int8_t *treeBeta(decoder_node_t *node)
{
return (int8_t *)node + node->beta;
}
void build_decoder_tree(t_nrPolar_params *pp);
void build_polar_tables(t_nrPolar_params *polarParams);
void init_polar_deinterleaver_table(t_nrPolar_params *polarParams);
void nr_polar_print_polarParams(void);
t_nrPolar_params *nr_polar_params (int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level,
int decoder_flag);
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level);
uint16_t nr_polar_aggregation_prime (uint8_t aggregation_level);
uint16_t nr_polar_aggregation_prime(uint8_t aggregation_level);
const uint8_t **nr_polar_kronecker_power_matrices(uint8_t n);
@@ -189,35 +198,13 @@ const uint16_t *nr_polar_sequence_pattern(uint8_t n);
* @param K Number of bits to encode (=payloadBits+crcParityBits)
* @param E
* @param n_max */
uint32_t nr_polar_output_length(uint16_t K,
uint16_t E,
uint8_t n_max);
uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max);
void nr_polar_rate_matching_pattern(uint16_t *rmp,
uint16_t *J,
const uint8_t *P_i_,
uint16_t K,
uint16_t N,
uint16_t E);
void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, const uint8_t *P_i_, uint16_t K, uint16_t N, uint16_t E);
void nr_polar_rate_matching(double *input,
double *output,
uint16_t *rmp,
uint16_t K,
uint16_t N,
uint16_t E);
void nr_polar_rate_matching(double *input, double *output, uint16_t *rmp, uint16_t K, uint16_t N, uint16_t E);
void nr_polar_rate_matching_int16(int16_t *input,
int16_t *output,
const uint16_t *rmp,
const uint16_t K,
const uint16_t N,
const uint16_t E,
const uint8_t i_bil);
void nr_polar_interleaving_pattern(uint16_t K,
uint8_t I_IL,
uint16_t *PI_k_);
void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_);
void nr_polar_info_bit_pattern(uint8_t *ibp,
uint8_t *pcbp,
@@ -232,18 +219,11 @@ void nr_polar_info_bit_pattern(uint8_t *ibp,
const uint8_t n_PC,
const uint8_t n_pc_wm);
void nr_polar_info_bit_extraction(uint8_t *input,
uint8_t *output,
uint8_t *pattern,
uint16_t size);
void nr_polar_info_bit_extraction(uint8_t *input, uint8_t *output, uint8_t *pattern, uint16_t size);
void nr_bit2byte_uint32_8(uint32_t *in,
uint16_t arraySize,
uint8_t *out);
void nr_bit2byte_uint32_8(uint32_t *in, uint16_t arraySize, uint8_t *out);
void nr_byte2bit_uint8_32(uint8_t *in,
uint16_t arraySize,
uint32_t *out);
void nr_byte2bit_uint8_32(uint8_t *in, uint16_t arraySize, uint32_t *out);
const uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits);
@@ -254,22 +234,9 @@ void nr_polar_generate_u(uint64_t *u,
uint16_t N,
uint8_t n_pc);
void nr_polar_uxG(uint8_t const* u, size_t N, uint8_t* D);
void nr_polar_uxG(uint8_t const *u, size_t N, uint8_t *D);
void nr_polar_info_extraction_from_u(uint64_t *Cprime,
const uint8_t *u,
const uint8_t *information_bit_pattern,
const uint8_t *parity_check_bit_pattern,
uint16_t N,
uint8_t n_pc);
void nr_polar_bit_insertion(uint8_t *input,
uint8_t *output,
uint16_t N,
uint16_t K,
int16_t *Q_I_N,
int16_t *Q_PC_N,
uint8_t n_PC);
void nr_polar_bit_insertion(uint8_t *input, uint8_t *output, uint16_t N, uint16_t K, int16_t *Q_I_N, int16_t *Q_PC_N, uint8_t n_PC);
void nr_matrix_multiplication_uint8_1D_uint8_2D(const uint8_t *matrix1,
const uint8_t **matrix2,
@@ -277,46 +244,39 @@ void nr_matrix_multiplication_uint8_1D_uint8_2D(const uint8_t *matrix1,
uint16_t row,
uint16_t col);
void nr_sort_asc_double_1D_array_ind(double *matrix,
uint8_t *ind,
uint8_t len);
void nr_sort_asc_double_1D_array_ind(double *matrix, uint8_t *ind, uint8_t len);
void nr_free_double_2D_array(double **input, uint16_t xlen);
#ifndef __cplusplus
void updateLLR(uint8_t listSize,
uint16_t row,
uint16_t col,
uint16_t xlen,
uint8_t ylen,
int zlen,
double llr[xlen][ylen][zlen],
uint8_t llrU[xlen][ylen],
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen]
);
uint16_t row,
uint16_t col,
uint16_t xlen,
uint8_t ylen,
int zlen,
double llr[xlen][ylen][zlen],
uint8_t llrU[xlen][ylen],
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen]);
void updatePathMetric(double *pathMetric,
uint8_t listSize,
uint8_t bitValue,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen]
);
uint8_t listSize,
uint8_t bitValue,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen]);
void updatePathMetric2(double *pathMetric,
uint8_t listSize,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen]);
uint8_t listSize,
uint16_t row,
int xlen,
int ylen,
int zlen,
double llr[xlen][ylen][zlen]);
#endif
//Also nr_polar_rate_matcher
static inline void nr_polar_interleaver(uint8_t *input,
uint8_t *output,
uint16_t *pattern,
uint16_t size)
// Also nr_polar_rate_matcher
static inline void nr_polar_interleaver(uint8_t *input, uint8_t *output, uint16_t *pattern, uint16_t size)
{
for (int i = 0; i < size; i++)
output[i] = input[pattern[i]];
@@ -328,7 +288,52 @@ static inline void nr_polar_deinterleaver(uint8_t *input, uint8_t *output, uint1
output[pattern[i]] = input[i];
}
void delete_decoder_tree(t_nrPolar_params *);
/*
* De-interleaving of coded bits implementation
* TS 138.212: Section 5.4.1.3 - Interleaving of coded bits
*/
static inline void nr_polar_rm_deinterleaving_lut(uint16_t *out, const uint E)
{
int16_t in[E];
for (int i = 0; i < E; i++)
in[i] = i;
int T = ceil((sqrt(8 * E + 1) - 1) / 2);
int v_tab[T][T];
memset(v_tab, 0, sizeof(v_tab));
int k = 0;
for (int i = 0; i < T; i++) {
for (int j = 0; j < T - i; j++) {
if (k < E) {
v_tab[i][j] = k + 1;
}
k++;
}
}
int v[T][T];
k = 0;
for (int j = 0; j < T; j++) {
for (int i = 0; i < T - j; i++) {
if (k < E && v_tab[i][j] != 0) {
v[i][j] = in[k];
k++;
} else {
v[i][j] = INT_MAX;
}
}
}
k = 0;
memset(out, 0, E * sizeof(*out));
for (int i = 0; i < T; i++) {
for (int j = 0; j < T - i; j++) {
if (v[i][j] != INT_MAX) {
out[k] = v[i][j];
k++;
}
}
}
}
extern pthread_mutex_t PolarListMutex;
static inline void polarReturn(t_nrPolar_params *polarParams)
@@ -30,24 +30,21 @@
* \warning
*/
//#define DEBUG_POLAR_ENCODER
//#define DEBUG_POLAR_ENCODER_DCI
//#define DEBUG_POLAR_MATLAB
//#define POLAR_CODING_DEBUG
// #define DEBUG_POLAR_ENCODER
// #define DEBUG_POLAR_ENCODER_DCI
// #define DEBUG_POLAR_MATLAB
// #define POLAR_CODING_DEBUG
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include "assertions.h"
#include <stdint.h>
//input [a_31 a_30 ... a_0]
//output [f_31 f_30 ... f_0] [f_63 f_62 ... f_32] ...
// input [a_31 a_30 ... a_0]
// output [f_31 f_30 ... f_0] [f_63 f_62 ... f_32] ...
void polar_encoder(uint32_t *in,
uint32_t *out,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level) {
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false);
void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level)
{
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);
/*
@@ -83,21 +80,21 @@ void polar_encoder(uint32_t *in,
printf("b[%d]=%d\n", i, nr_polar_B[i]);
#endif
//Interleaving (c to c')
// Interleaving (c to c')
uint8_t nr_polar_CPrime[polarParams->K];
nr_polar_interleaver(nr_polar_B, nr_polar_CPrime, polarParams->interleaving_pattern, polarParams->K);
#ifdef DEBUG_POLAR_ENCODER
uint64_t Cprime=0;
uint64_t Cprime = 0;
for (int i = 0; i<polarParams->K; i++) {
for (int i = 0; i < polarParams->K; i++) {
Cprime = Cprime | ((uint64_t)nr_polar_CPrime[i] << i);
if (nr_polar_CPrime[i] == 1)
printf("pos %d : %lx\n", i, Cprime);
}
printf("polar_Cprime %lx\n",Cprime);
printf("polar_Cprime %lx\n", Cprime);
#endif
//Bit insertion (c' to u)
// Bit insertion (c' to u)
uint8_t nr_polar_U[polarParams->N];
nr_polar_bit_insertion(nr_polar_CPrime,
nr_polar_U,
@@ -119,11 +116,10 @@ void polar_encoder(uint32_t *in,
for (int i = 0; i < polarParams->N; i++)
D[i / 64] |= ((uint64_t)nr_polar_D[i]) << (i & 63);
printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n",
D[0],D[1],D[2],D[3],D[4],D[5],D[6],D[7]);
printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7]);
#endif
//Rate matching
//Sub-block interleaving (d to y) and Bit selection (y to e)
// Rate matching
// Sub-block interleaving (d to y) and Bit selection (y to e)
uint8_t nr_polar_E[polarParams->encoderLength];
nr_polar_interleaver(nr_polar_D, nr_polar_E, polarParams->rate_matching_pattern, polarParams->encoderLength);
/*
@@ -145,8 +141,9 @@ void polar_encoder_dci(uint32_t *in,
uint16_t n_RNTI,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level) {
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false);
uint8_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
#ifdef DEBUG_POLAR_ENCODER_DCI
printf("[polar_encoder_dci] in: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", in[0], in[1], in[2], in[3]);
@@ -176,10 +173,11 @@ void polar_encoder_dci(uint32_t *in,
printf("\n");
printf("[polar_encoder_dci] GP: ");
for (int i=0; i<polarParams->crcParityBits; i++) printf("%d-", polarParams->crc_generator_matrix[0][i]);
for (int i = 0; i < polarParams->crcParityBits; i++)
printf("%d-", polarParams->crc_generator_matrix[0][i]);
printf("\n");
#endif
//Calculate CRC.
// Calculate CRC.
uint8_t nr_polar_crc[polarParams->crcParityBits];
nr_matrix_multiplication_uint8_1D_uint8_2D(nr_polar_APrime,
polarParams->crc_generator_matrix,
@@ -197,14 +195,14 @@ void polar_encoder_dci(uint32_t *in,
printf("\n");
#endif
uint8_t nr_polar_B[polarParams->payloadBits + 8 + 16];
//Attach CRC to the Transport Block. (a to b)
// 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];
//Scrambling (b to c)
for (int i=0; i<16; i++)
// Scrambling (b to c)
for (int i = 0; i < 16; i++)
nr_polar_B[polarParams->payloadBits + 8 + i] = (nr_polar_B[polarParams->payloadBits + 8 + i] + ((n_RNTI >> (15 - i)) & 1)) % 2;
#ifdef DEBUG_POLAR_ENCODER_DCI
@@ -213,10 +211,10 @@ void polar_encoder_dci(uint32_t *in,
printf("%d-", nr_polar_B[i]);
printf("\n");
#endif
//Interleaving (c to c')
// Interleaving (c to c')
uint8_t nr_polar_CPrime[polarParams->K];
nr_polar_interleaver(nr_polar_B, nr_polar_CPrime, polarParams->interleaving_pattern, polarParams->K);
//Bit insertion (c' to u)
// Bit insertion (c' to u)
uint8_t nr_polar_U[polarParams->N];
nr_polar_bit_insertion(nr_polar_CPrime,
nr_polar_U,
@@ -225,14 +223,14 @@ void polar_encoder_dci(uint32_t *in,
polarParams->Q_I_N,
polarParams->Q_PC_N,
polarParams->n_pc);
//Encoding (u to d)
// Encoding (u to d)
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++)
nr_polar_D[i] %= 2;
//Rate matching
//Sub-block interleaving (d to y) and Bit selection (y to e)
// Rate matching
// Sub-block interleaving (d to y) and Bit selection (y to e)
uint8_t nr_polar_E[polarParams->encoderLength];
nr_polar_interleaver(nr_polar_D, nr_polar_E, polarParams->rate_matching_pattern, polarParams->encoderLength);
/*
@@ -294,44 +292,50 @@ __attribute__((always_inline)) static inline void polar_rate_matching(const t_nr
{
// handle rate matching with a single 128 bit word using bit shuffling
// can be done with SIMD intrisics if needed
if (polarParams->groupsize < 8) {
AssertFatal(polarParams->encoderLength<=512,"Need to handle groupsize(%d)<8 and N(%d)>512\n",polarParams->groupsize,polarParams->encoderLength);
uint128_t *out128=(uint128_t*)out;
uint128_t *in128=(uint128_t*)in;
for (int i=0;i<polarParams->encoderLength>>7;i++)
if (polarParams->groupsize < 8) {
AssertFatal(polarParams->encoderLength <= 512,
"Need to handle groupsize(%d)<8 and N(%d)>512\n",
polarParams->groupsize,
polarParams->encoderLength);
uint128_t *out128 = (uint128_t *)out;
uint128_t *in128 = (uint128_t *)in;
for (int i = 0; i < polarParams->encoderLength >> 7; i++)
out128[i] = 0;
#ifdef DEBUG_POLAR_ENCODER
uint128_t tmp1;
#endif
for (int i=0; i<polarParams->encoderLength; i++) {
for (int i = 0; i < polarParams->encoderLength; i++) {
#ifdef DEBUG_POLAR_ENCODER
printf("%d<-%u : %llx.%llx =>",i,polarParams->rate_matching_pattern[i],((uint64_t *)out)[1],((uint64_t *)out)[0]);
printf("%d<-%u : %llx.%llx =>", i, polarParams->rate_matching_pattern[i], ((uint64_t *)out)[1], ((uint64_t *)out)[0]);
#endif
uint8_t pi=polarParams->rate_matching_pattern[i];
uint8_t pi7=pi>>7;
uint8_t pimod128=pi&127;
uint8_t imod128=i&127;
uint8_t i7=i>>7;
uint8_t pi = polarParams->rate_matching_pattern[i];
uint8_t pi7 = pi >> 7;
uint8_t pimod128 = pi & 127;
uint8_t imod128 = i & 127;
uint8_t i7 = i >> 7;
uint128_t tmp0 = (in128[pi7] & (((uint128_t)1) << (pimod128)));
if (tmp0!=0) {
out128[i7] = out128[i7] | ((uint128_t)1)<<imod128;
if (tmp0 != 0) {
out128[i7] = out128[i7] | ((uint128_t)1) << imod128;
#ifdef DEBUG_POLAR_ENCODER
printf("%llx.%llx<->%llx.%llx => %llx.%llx\n",
((uint64_t *)&tmp0)[1],((uint64_t *)&tmp0)[0],
((uint64_t *)&tmp1)[1],((uint64_t *)&tmp1)[0],
((uint64_t *)out)[1],((uint64_t *)out)[0]);
((uint64_t *)&tmp0)[1],
((uint64_t *)&tmp0)[0],
((uint64_t *)&tmp1)[1],
((uint64_t *)&tmp1)[0],
((uint64_t *)out)[1],
((uint64_t *)out)[0]);
#endif
}
}
}
}
// These are based on LUTs for byte and short word groups
else if (polarParams->groupsize == 8)
for (int i = 0; i < polarParams->encoderLength >> 3; i++)
((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
else // groupsize==16
for (int i=0; i<polarParams->encoderLength>>4; i++) {
for (int i = 0; i < polarParams->encoderLength >> 4; i++) {
((uint16_t *)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]];
}
@@ -340,19 +344,20 @@ __attribute__((always_inline)) static inline void polar_rate_matching(const t_nr
}
}
void build_polar_tables(t_nrPolar_params *polarParams) {
void build_polar_tables(t_nrPolar_params *polarParams)
{
// build table b -> c'
AssertFatal(polarParams->K > 17, "K = %d < 18, is not possible\n",polarParams->K);
AssertFatal(polarParams->K > 17, "K = %d < 18, is not possible\n", polarParams->K);
AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n", polarParams->K);
const int numbytes = (polarParams->K+7)/8;
const int residue = polarParams->K&7;
const int numbytes = (polarParams->K + 7) / 8;
const int residue = polarParams->K & 7;
uint deinterleaving_pattern[polarParams->K];
for (int i = 0; i < polarParams->K; i++)
deinterleaving_pattern[polarParams->interleaving_pattern[i]] = i;
for (int byte=0; byte<numbytes; byte++) {
int numbits = byte<(polarParams->K>>3) ? 8 : residue;
for (int byte = 0; byte < numbytes; byte++) {
int numbits = byte < (polarParams->K >> 3) ? 8 : residue;
for (uint64_t val = 0; val < 256LU; val++) {
// uint16_t * tmp=polarParams->deinterleaving_pattern+polarParams->K - 1 - 8 * byte;
union {
@@ -360,10 +365,10 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
uint64_t pieces[2];
} tab = {0};
uint *tmp = deinterleaving_pattern + polarParams->K - 8 * byte - 1;
for (int i=0; i<numbits; i++) {
for (int i = 0; i < numbits; i++) {
// flip bit endian of B bitstring
const int ip = *tmp--;
AssertFatal(ip<128,"ip = %d\n",ip);
AssertFatal(ip < 128, "ip = %d\n", ip);
const uint128_t bit_i = (val >> i) & 1;
tab.full |= bit_i << ip;
}
@@ -372,50 +377,57 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
}
}
AssertFatal(polarParams->N == 512 || polarParams->N == 256 || polarParams->N == 128 || polarParams->N == 64, "N = %d, not done yet\n", polarParams->N);
AssertFatal(polarParams->N == 512 || polarParams->N == 256 || polarParams->N == 128 || polarParams->N == 64,
"N = %d, not done yet\n",
polarParams->N);
// rate matching table
int iplast=polarParams->rate_matching_pattern[0];
int ccnt=0;
int iplast = polarParams->rate_matching_pattern[0];
int ccnt = 0;
#ifdef DEBUG_POLAR_ENCODER
int groupcnt=0;
int firstingroup_out=0;
int firstingroup_in=iplast;
int groupcnt = 0;
int firstingroup_out = 0;
int firstingroup_in = iplast;
#endif
int mingroupsize = 1024;
// compute minimum group size of rate-matching pattern
for (int outpos=1; outpos<polarParams->encoderLength; outpos++) {
for (int outpos = 1; outpos < polarParams->encoderLength; outpos++) {
int ip = polarParams->rate_matching_pattern[outpos];
#ifdef DEBUG_POLAR_ENCODER
printf("rm: outpos %d, inpos %d\n",outpos,ip);
printf("rm: outpos %d, inpos %d\n", outpos, ip);
#endif
if ((ip - iplast) == 1)
ccnt++;
else {
#ifdef DEBUG_POLAR_ENCODER
groupcnt++;
printf("group %d (size %d): (%d:%d) => (%d:%d)\n",groupcnt,ccnt+1,
firstingroup_in,firstingroup_in+ccnt,
firstingroup_out,firstingroup_out+ccnt);
printf("group %d (size %d): (%d:%d) => (%d:%d)\n",
groupcnt,
ccnt + 1,
firstingroup_in,
firstingroup_in + ccnt,
firstingroup_out,
firstingroup_out + ccnt);
#endif
if ((ccnt + 1) < mingroupsize)
mingroupsize = ccnt + 1;
ccnt=0;
ccnt = 0;
#ifdef DEBUG_POLAR_ENCODER
firstingroup_out=outpos;
firstingroup_in=ip;
firstingroup_out = outpos;
firstingroup_in = ip;
#endif
}
iplast=ip;
iplast = ip;
}
#ifdef DEBUG_POLAR_ENCODER
groupcnt++;
#endif
if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
if ((ccnt + 1) < mingroupsize)
mingroupsize = ccnt + 1;
#ifdef DEBUG_POLAR_ENCODER
printf("group %d (size %d): (%d:%d) => (%d:%d)\n",
groupcnt,
@@ -452,8 +464,9 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
// rerun again to create groups
for (int outpos = 0, tcnt = 0; outpos < polarParams->encoderLength; outpos += mingroupsize, tcnt++)
polarParams->rm_tab[tcnt] = polarParams->rate_matching_pattern[outpos] >> shift;
}
build_decoder_tree(polarParams);
}
void polar_encoder_fast(uint64_t *A,
void *out,
@@ -463,7 +476,7 @@ void polar_encoder_fast(uint64_t *A,
uint16_t messageLength,
uint8_t aggregation_level)
{
t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false);
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
#ifdef POLAR_CODING_DEBUG
printf("polarParams->payloadBits = %i\n", polarParams->payloadBits);
@@ -480,27 +493,27 @@ void polar_encoder_fast(uint64_t *A,
#endif
// AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K);
AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K);
AssertFatal(polarParams->payloadBits < 65, "payload bits = %d > 64, is not supported yet\n",polarParams->payloadBits);
AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n", polarParams->K);
AssertFatal(polarParams->payloadBits < 65, "payload bits = %d > 64, is not supported yet\n", polarParams->payloadBits);
int bitlen = polarParams->payloadBits;
// append crc
AssertFatal(bitlen<129,"support for payloads <= 128 bits\n");
AssertFatal(bitlen < 129, "support for payloads <= 128 bits\n");
// AssertFatal(polarParams->crcParityBits == 24,"support for 24-bit crc only for now\n");
//int bitlen0=bitlen;
// int bitlen0=bitlen;
#ifdef POLAR_CODING_DEBUG
printf("\nTX\n");
printf("a: ");
for (int n = (bitlen + 63)/64 ; n >=0; n--) {
if (n % 4 == 0)
printf(" ");
if (n < bitlen)
printf("%lu", (A[n/64] >> (n%64)) & 1);
for (int n = (bitlen + 63) / 64; n >= 0; n--) {
if (n % 4 == 0)
printf(" ");
if (n < bitlen)
printf("%lu", (A[n / 64] >> (n % 64)) & 1);
}
printf("\n");
#endif
uint64_t tcrc=0;
uint64_t tcrc = 0;
uint offset = 0;
// appending 24 ones before a0 for DCI as stated in 38.212 7.3.2
@@ -511,76 +524,76 @@ void polar_encoder_fast(uint64_t *A,
//???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];
// 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);
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);
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];
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];
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;
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];
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];
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;
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;
tcrc = (uint64_t)((crcmask ^ (crc11(A128_flip, bitlen) >> 21))) & 0x7ff;
}
// this is number of quadwords in the bit string
int quadwlen = (polarParams->K+63)/64;
int quadwlen = (polarParams->K + 63) / 64;
// Create the B bit string as
// 0, 0, ..., 0, a'_0, a'_1, ..., a'_A-1, p_0, p_1, ..., p_{N_parity-1}
//??? 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};
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));
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));
B[n] = (A[n - 1] >> (64 - polarParams->crcParityBits));
#ifdef POLAR_CODING_DEBUG
int bitlen_B = bitlen + polarParams->crcParityBits;
@@ -600,17 +613,13 @@ void polar_encoder_fast(uint64_t *A,
// 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};
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]];
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]];
@@ -620,7 +629,8 @@ void polar_encoder_fast(uint64_t *A,
#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]));
for (int i = 0; i < quadwlen; i++)
printf("[polar_encoder_fast]C'[%d]= 0x%llx\n", i, (unsigned long long)(Cprime[i]));
#endif
#ifdef POLAR_CODING_DEBUG
@@ -675,8 +685,8 @@ void polar_encoder_fast(uint64_t *A,
fflush(stdout);
#endif
memset((void*)out,0,polarParams->encoderLength>>3);
polar_rate_matching(polarParams,(void *)D, out);
memset((void *)out, 0, polarParams->encoderLength >> 3);
polar_rate_matching(polarParams, (void *)D, out);
#ifdef POLAR_CODING_DEBUG
uint64_t *out64 = (uint64_t *)out;
@@ -30,25 +30,26 @@
* \warning
*/
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include "nr_polar_defs.h"
#include "nr_polar_psbch_defs.h"
#include "PHY/NR_TRANSPORT/nr_dci.h"
#include "nrPolar_tools/nr_polar_psbch_defs.h"
#define PolarKey ((messageType<<24)|(messageLength<<8)|aggregation_level)
static t_nrPolar_params * PolarList=NULL;
pthread_mutex_t PolarListMutex=PTHREAD_MUTEX_INITIALIZER;
#define PolarKey ((messageType << 24) | (messageLength << 8) | aggregation_level)
static t_nrPolar_params *PolarList = NULL;
pthread_mutex_t PolarListMutex = PTHREAD_MUTEX_INITIALIZER;
static int intcmp(const void *p1,const void *p2) {
return(*(int16_t *)p1 > *(int16_t *)p2);
static int intcmp(const void *p1, const void *p2)
{
return (*(int16_t *)p1 > *(int16_t *)p2);
}
static void nr_polar_delete_list(t_nrPolar_params * polarParams) {
static void nr_polar_delete_list(t_nrPolar_params *polarParams)
{
if (!polarParams)
return;
if (polarParams->nextPtr)
nr_polar_delete_list(polarParams->nextPtr);
delete_decoder_tree(polarParams);
// From build_polar_tables()
free(polarParams->rm_tab);
if (polarParams->crc_generator_matrix)
@@ -58,55 +59,55 @@ static void nr_polar_delete_list(t_nrPolar_params * polarParams) {
free(polarParams->rate_matching_pattern);
free(polarParams->information_bit_pattern);
free(polarParams->parity_check_bit_pattern);
free(polarParams->i_bil_pattern);
free(polarParams->Q_I_N);
free(polarParams->Q_F_N);
free(polarParams->Q_PC_N);
free(polarParams);
}
static void nr_polar_delete(void) {
static void nr_polar_delete(void)
{
pthread_mutex_lock(&PolarListMutex);
nr_polar_delete_list(PolarList);
PolarList=NULL;
pthread_mutex_unlock(&PolarListMutex);
PolarList = NULL;
pthread_mutex_unlock(&PolarListMutex);
}
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level, int decoder_flag)
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level)
{
// The lock is weak, because we never delete in the list, only at exit time
// therefore, returning t_nrPolar_params * from the list is safe for future usage
pthread_mutex_lock(&PolarListMutex);
if(!PolarList)
if (!PolarList)
atexit(nr_polar_delete);
t_nrPolar_params *currentPtr = PolarList;
//Parse the list. If the node is already created, return without initialization.
// Parse the list. If the node is already created, return without initialization.
while (currentPtr != NULL) {
//printf("currentPtr->idx %d, (%d,%d)\n",currentPtr->idx,currentPtr->payloadBits,currentPtr->encoderLength);
//LOG_D(PHY,"Looking for index %d\n",(messageType * messageLength * aggregation_prime));
if (currentPtr->busy == false && currentPtr->idx == PolarKey ) {
currentPtr->busy=true;
// printf("currentPtr->idx %d, (%d,%d)\n",currentPtr->idx,currentPtr->payloadBits,currentPtr->encoderLength);
// LOG_D(PHY,"Looking for index %d\n",(messageType * messageLength * aggregation_prime));
if (currentPtr->busy == false && currentPtr->idx == PolarKey) {
currentPtr->busy = true;
pthread_mutex_unlock(&PolarListMutex);
if (decoder_flag && !currentPtr->tree.root)
build_decoder_tree(currentPtr);
return currentPtr ;
}
else
return currentPtr;
} else
currentPtr = currentPtr->nextPtr;
}
// printf("currentPtr %p (polarParams %p)\n",currentPtr,polarParams);
//Else, initialize and add node to the end of the linked list.
t_nrPolar_params *newPolarInitNode = calloc(sizeof(t_nrPolar_params),1);
// Else, initialize and add node to the end of the linked list.
t_nrPolar_params *newPolarInitNode = malloc(sizeof(t_nrPolar_params));
AssertFatal(newPolarInitNode, "[nr_polar_init] New t_nrPolar_params * could not be created");
newPolarInitNode->busy = true;
newPolarInitNode->nextPtr = NULL;
newPolarInitNode->nextPtr = PolarList;
*newPolarInitNode = (t_nrPolar_params){.busy = true, .nextPtr = PolarList, .tree_linearization.is_initialized = false};
PolarList = newPolarInitNode;
pthread_mutex_unlock(&PolarListMutex);
// LOG_D(PHY,"Setting new polarParams index %d, messageType %d, messageLength %d, aggregation_prime %d\n",(messageType * messageLength * aggregation_prime),messageType,messageLength,aggregation_prime);
// LOG_D(PHY,"Setting new polarParams index %d, messageType %d, messageLength %d, aggregation_prime %d\n",(messageType *
// messageLength * aggregation_prime),messageType,messageLength,aggregation_prime);
newPolarInitNode->idx = PolarKey;
//printf("newPolarInitNode->idx %d, (%d,%d,%d:%d)\n",newPolarInitNode->idx,messageType,messageLength,aggregation_prime,aggregation_level);
// printf("newPolarInitNode->idx %d,
// (%d,%d,%d:%d)\n",newPolarInitNode->idx,messageType,messageLength,aggregation_prime,aggregation_level);
if (messageType == NR_POLAR_PBCH_MESSAGE_TYPE) {
newPolarInitNode->n_max = NR_POLAR_PBCH_N_MAX;
@@ -120,7 +121,8 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
newPolarInitNode->encoderLength = NR_POLAR_PBCH_E;
newPolarInitNode->crcCorrectionBits = NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS;
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits); // G_P
//printf("Initializing polar parameters for PBCH (K %d, E %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength);
// printf("Initializing polar parameters for PBCH (K %d, E
// %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength);
} else if (messageType == NR_POLAR_DCI_MESSAGE_TYPE) {
newPolarInitNode->n_max = NR_POLAR_DCI_N_MAX;
@@ -133,11 +135,15 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
newPolarInitNode->payloadBits = messageLength;
newPolarInitNode->encoderLength = aggregation_level * 108;
newPolarInitNode->crcCorrectionBits = NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS;
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits); // G_P
//printf("Initializing polar parameters for DCI (K %d, E %d, L %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level);
newPolarInitNode->crc_generator_matrix =
crc24c_generator_matrix(newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits); // G_P
// printf("Initializing polar parameters for DCI (K %d, E %d, L
// %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level);
} else if (messageType == NR_POLAR_UCI_PUCCH_MESSAGE_TYPE) {
AssertFatal(aggregation_level > 2, "Aggregation level (%d) for PUCCH 2 encoding is NPRB and should be > 2\n", aggregation_level);
AssertFatal(aggregation_level > 2,
"Aggregation level (%d) for PUCCH 2 encoding is NPRB and should be > 2\n",
aggregation_level);
AssertFatal(messageLength > 11, "Message length %d is too short for polar encoding of UCI\n", messageLength);
// TS 38.212 - Section 6.3.1.2.1 UCI encoded by Polar code
@@ -178,7 +184,7 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
newPolarInitNode->i_bil = NR_POLAR_PUCCH_I_BIL;
newPolarInitNode->payloadBits = messageLength;
newPolarInitNode->crcCorrectionBits = NR_POLAR_PUCCH_CRC_ERROR_CORRECTION_BITS;
//LOG_D(PHY,"New polar node, encoderLength %d, aggregation_level %d\n",newPolarInitNode->encoderLength,aggregation_level);
// LOG_D(PHY,"New polar node, encoderLength %d, aggregation_level %d\n",newPolarInitNode->encoderLength,aggregation_level);
} else if (messageType == SL_NR_POLAR_PSBCH_MESSAGE_TYPE) { // PSBCH
newPolarInitNode->n_max = SL_NR_POLAR_PSBCH_N_MAX;
newPolarInitNode->i_il = SL_NR_POLAR_PSBCH_I_IL;
@@ -200,17 +206,13 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
}
newPolarInitNode->K = newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits; // Number of bits to encode.
newPolarInitNode->N = nr_polar_output_length(newPolarInitNode->K,
newPolarInitNode->encoderLength,
newPolarInitNode->n_max);
newPolarInitNode->N = nr_polar_output_length(newPolarInitNode->K, newPolarInitNode->encoderLength, newPolarInitNode->n_max);
newPolarInitNode->n = log2(newPolarInitNode->N);
newPolarInitNode->G_N = nr_polar_kronecker_power_matrices(newPolarInitNode->n);
// polar_encoder vectors:
newPolarInitNode->Q_0_Nminus1 = nr_polar_sequence_pattern(newPolarInitNode->n);
newPolarInitNode->interleaving_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->K);
nr_polar_interleaving_pattern(newPolarInitNode->K,
newPolarInitNode->i_il,
newPolarInitNode->interleaving_pattern);
nr_polar_interleaving_pattern(newPolarInitNode->K, newPolarInitNode->i_il, newPolarInitNode->interleaving_pattern);
newPolarInitNode->rate_matching_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength);
uint16_t J[newPolarInitNode->N];
@@ -220,11 +222,16 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
newPolarInitNode->K,
newPolarInitNode->N,
newPolarInitNode->encoderLength);
if (newPolarInitNode->i_bil) {
newPolarInitNode->i_bil_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength);
nr_polar_rm_deinterleaving_lut(newPolarInitNode->i_bil_pattern, newPolarInitNode->encoderLength);
}
newPolarInitNode->information_bit_pattern = malloc(sizeof(uint8_t) * newPolarInitNode->N);
newPolarInitNode->parity_check_bit_pattern = malloc(sizeof(uint8_t) * newPolarInitNode->N);
newPolarInitNode->Q_I_N = malloc(sizeof(int16_t) * (newPolarInitNode->K + newPolarInitNode->n_pc));
newPolarInitNode->Q_F_N = malloc( sizeof(int16_t) * (newPolarInitNode->N + 1)); // Last element shows the final array index assigned a value.
newPolarInitNode->Q_PC_N = malloc( sizeof(int16_t) * (newPolarInitNode->n_pc));
newPolarInitNode->Q_F_N =
malloc(sizeof(int16_t) * (newPolarInitNode->N + 1)); // Last element shows the final array index assigned a value.
newPolarInitNode->Q_PC_N = malloc(sizeof(int16_t) * (newPolarInitNode->n_pc));
for (int i = 0; i <= newPolarInitNode->N; i++)
newPolarInitNode->Q_F_N[i] = -1; // Empty array.
@@ -243,26 +250,26 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
newPolarInitNode->n_pc_wm);
// sort the Q_I_N array in ascending order (first K positions)
qsort((void *)newPolarInitNode->Q_I_N,newPolarInitNode->K,sizeof(int16_t),intcmp);
qsort((void *)newPolarInitNode->Q_I_N, newPolarInitNode->K, sizeof(int16_t), intcmp);
if (decoder_flag == 1)
build_decoder_tree(newPolarInitNode);
build_polar_tables(newPolarInitNode);
init_polar_deinterleaver_table(newPolarInitNode);
return newPolarInitNode;
}
void nr_polar_print_polarParams() {
void nr_polar_print_polarParams()
{
uint8_t i = 0;
if (PolarList == NULL) {
printf("polarParams is empty.\n");
} else {
t_nrPolar_params * polarParams=PolarList;
t_nrPolar_params *polarParams = PolarList;
while (polarParams != NULL) {
printf("polarParams[%d] = %d, %d, %d\n", i,
polarParams->idx>>24, (polarParams->idx>>8)&0xFFFF, polarParams->idx&0xFF);
printf("polarParams[%d] = %d, %d, %d\n",
i,
polarParams->idx >> 24,
(polarParams->idx >> 8) & 0xFFFF,
polarParams->idx & 0xFF);
polarParams = polarParams->nextPtr;
i++;
}
@@ -271,11 +278,18 @@ void nr_polar_print_polarParams() {
return;
}
uint16_t nr_polar_aggregation_prime (uint8_t aggregation_level) {
if (aggregation_level == 0) return 0;
else if (aggregation_level == 1) return NR_POLAR_AGGREGATION_LEVEL_1_PRIME;
else if (aggregation_level == 2) return NR_POLAR_AGGREGATION_LEVEL_2_PRIME;
else if (aggregation_level == 4) return NR_POLAR_AGGREGATION_LEVEL_4_PRIME;
else if (aggregation_level == 8) return NR_POLAR_AGGREGATION_LEVEL_8_PRIME;
else return NR_POLAR_AGGREGATION_LEVEL_16_PRIME; //aggregation_level == 16
uint16_t nr_polar_aggregation_prime(uint8_t aggregation_level)
{
if (aggregation_level == 0)
return 0;
else if (aggregation_level == 1)
return NR_POLAR_AGGREGATION_LEVEL_1_PRIME;
else if (aggregation_level == 2)
return NR_POLAR_AGGREGATION_LEVEL_2_PRIME;
else if (aggregation_level == 4)
return NR_POLAR_AGGREGATION_LEVEL_4_PRIME;
else if (aggregation_level == 8)
return NR_POLAR_AGGREGATION_LEVEL_8_PRIME;
else
return NR_POLAR_AGGREGATION_LEVEL_16_PRIME; // aggregation_level == 16
}
@@ -28,12 +28,13 @@
* \email turker.yilmaz@eurecom.fr
* \note
* \warning
*/
*/
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_){
uint K_IL_max = 164, k = 0;
void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_)
{
uint K_IL_max = 164;
uint8_t interleaving_pattern_table[164] = {
0, 2, 4, 7, 9, 14, 19, 20, 24, 25, 26, 28, 31, 34, 42, 45, 49, 50, 51, 53, 54, 56, 58, 59,
61, 62, 65, 66, 67, 69, 70, 71, 72, 76, 77, 81, 82, 83, 87, 88, 89, 91, 93, 95, 98, 101, 104, 106,
@@ -44,10 +45,10 @@ void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_){
40, 146, 41, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163};
if (I_IL == 0) {
for (; k <= K - 1; k++)
for (int k = 0; k < K; k++)
PI_k_[k] = k;
} else {
for (int m = 0; m <= (K_IL_max - 1); m++) {
for (int m = 0, k = 0; m < K_IL_max; m++) {
if (interleaving_pattern_table[m] >= (K_IL_max - K)) {
PI_k_[k] = interleaving_pattern_table[m] - (K_IL_max - K);
k++;
@@ -7,53 +7,48 @@
void nr_polar_kernal_operation(uint8_t *u, uint8_t *d, uint16_t N)
{
// Martino's algorithm to avoid multiplication for the generating matrix of polar codes
uint32_t i,j;
// Martino's algorithm to avoid multiplication for the generating matrix of polar codes
simde__m256i A,B,C,D,E,U,zerosOnly, OUT;
simde__m256i inc;
uint32_t dTest[8];
uint32_t uArray[8];
uint32_t k;
uint32_t incArray[8];
//initialisation
for(k=0; k<8; k++)
incArray[k]=k;
inc=simde_mm256_loadu_si256((simde__m256i const*)incArray); // 0, 1, ..., 7 to increase
zerosOnly=simde_mm256_setzero_si256(); // for comparison
uint32_t i, j;
for(i=0; i<N; i+=8)
{
B=simde_mm256_set1_epi32((int)i); // i, ..., i
B=simde_mm256_add_epi32(B, inc); // i, i+1, ..., i+7
OUT=simde_mm256_setzero_si256(); // it will contain the result of all the XORs for the d(i)s
for(j=0; j<N; j++)
{
A=simde_mm256_set1_epi32((int)(j)); //j, j, ..., j
A=simde_mm256_sub_epi32(A, B); //(j-i), (j-(i+1)), ... (j-(i+7))
U=simde_mm256_set1_epi32((int)u[j]);
simde_mm256_storeu_si256((simde__m256i*)uArray, U); //u(j) ... u(j) for the maskload
simde__m256i A, B, C, D, E, U, zerosOnly, OUT;
simde__m256i inc;
uint32_t dTest[8];
uint32_t uArray[8];
uint32_t k;
uint32_t incArray[8];
C=simde_mm256_and_si256(A, B); //(j-i)&i -> If zero, then XOR with the u(j)
D=simde_mm256_cmpeq_epi32(C, zerosOnly); // compare with zero and use the result as mask
E=simde_mm256_maskload_epi32((int const*)uArray, D); // load only some u(j)s for the XOR
OUT=simde_mm256_xor_si256(OUT, E); //32 bit x 8
// initialisation
for (k = 0; k < 8; k++)
incArray[k] = k;
inc = simde_mm256_loadu_si256((simde__m256i const *)incArray); // 0, 1, ..., 7 to increase
}
simde_mm256_storeu_si256((simde__m256i*)dTest, OUT);
zerosOnly = simde_mm256_setzero_si256(); // for comparison
for(k=0; k<8; k++) // Conversion from 32 bits to 8 bits
{
d[i+k]=(uint8_t)dTest[k]; // With AVX512 there is an intrinsic to do it
}
for (i = 0; i < N; i += 8) {
B = simde_mm256_set1_epi32((int)i); // i, ..., i
B = simde_mm256_add_epi32(B, inc); // i, i+1, ..., i+7
}
OUT = simde_mm256_setzero_si256(); // it will contain the result of all the XORs for the d(i)s
for (j = 0; j < N; j++) {
A = simde_mm256_set1_epi32((int)(j)); // j, j, ..., j
A = simde_mm256_sub_epi32(A, B); //(j-i), (j-(i+1)), ... (j-(i+7))
U = simde_mm256_set1_epi32((int)u[j]);
simde_mm256_storeu_si256((simde__m256i *)uArray, U); // u(j) ... u(j) for the maskload
C = simde_mm256_and_si256(A, B); //(j-i)&i -> If zero, then XOR with the u(j)
D = simde_mm256_cmpeq_epi32(C, zerosOnly); // compare with zero and use the result as mask
E = simde_mm256_maskload_epi32((int const *)uArray, D); // load only some u(j)s for the XOR
OUT = simde_mm256_xor_si256(OUT, E); // 32 bit x 8
}
simde_mm256_storeu_si256((simde__m256i *)dTest, OUT);
for (k = 0; k < 8; k++) // Conversion from 32 bits to 8 bits
{
d[i + k] = (uint8_t)dTest[k]; // With AVX512 there is an intrinsic to do it
}
}
}
@@ -28,7 +28,7 @@
* \email turker.yilmaz@eurecom.fr
* \note
* \warning
*/
*/
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
@@ -47,7 +47,8 @@ void nr_matrix_multiplication_uint8_1D_uint8_2D(const uint8_t *matrix1,
}
// Modified Bubble Sort.
void nr_sort_asc_double_1D_array_ind(double *matrix, uint8_t *ind, uint8_t len) {
void nr_sort_asc_double_1D_array_ind(double *matrix, uint8_t *ind, uint8_t len)
{
for (int i = 0; i < len; i++) {
int swaps = 0;
for (int j = 0; j < (len - i) - 1; j++) {
@@ -28,46 +28,70 @@
* \email turker.yilmaz@eurecom.fr
* \note
* \warning
*/
*/
#ifndef __NR_POLAR_PBCH_DEFS__H__
#define __NR_POLAR_PBCH_DEFS__H__
#define NR_POLAR_PBCH_AGGREGATION_LEVEL 0 //uint8_t
#define NR_POLAR_PBCH_MESSAGE_TYPE 0 //int8_t
#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 //int8_t
#define NR_POLAR_PBCH_PAYLOAD_BITS 32 //uint16_t
#define NR_POLAR_PBCH_AGGREGATION_LEVEL 0 // uint8_t
#define NR_POLAR_PBCH_MESSAGE_TYPE 0 // int8_t
#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 // int8_t
#define NR_POLAR_PBCH_PAYLOAD_BITS 32 // uint16_t
#define NR_POLAR_PBCH_CRC_PARITY_BITS 24
#define NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS 3
//Assumed 3 by 3GPP when NR_POLAR_PBCH_L>8 to meet false alarm rate requirements.
// Assumed 3 by 3GPP when NR_POLAR_PBCH_L>8 to meet false alarm rate requirements.
//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_SEG 0 //uint8_t
#define NR_POLAR_PBCH_N_PC 0 //uint8_t
#define NR_POLAR_PBCH_N_PC_WM 0 //uint8_t
//#define NR_POLAR_PBCH_N 512 //uint16_t
// 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_SEG 0 // uint8_t
#define NR_POLAR_PBCH_N_PC 0 // uint8_t
#define NR_POLAR_PBCH_N_PC_WM 0 // uint8_t
// #define NR_POLAR_PBCH_N 512 //uint16_t
//Sec. 7.1.5: Rate Matching
#define NR_POLAR_PBCH_I_BIL 0 //uint8_t
#define NR_POLAR_PBCH_E 864 //uint16_t
// Sec. 7.1.5: Rate Matching
#define NR_POLAR_PBCH_I_BIL 0 // uint8_t
#define NR_POLAR_PBCH_E 864 // uint16_t
#define NR_POLAR_PBCH_E_DWORD 27 // NR_POLAR_PBCH_E/32
#define NR_POLAR_PSBCH_E 1792 //uint16_t
#define NR_POLAR_PSBCH_E 1792 // uint16_t
#define NR_POLAR_PSBCH_E_DWORD 56 // NR_POLAR_PSBCH_E/32
/*
* TEST CODE
*/
//#define DEBUG_POLAR
// Usage in code:
//#ifdef DEBUG_POLAR
// #define DEBUG_POLAR
// Usage in code:
// #ifdef DEBUG_POLAR
//...
//#endif
// #endif
//unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0;
//unsigned int testPayload2=0xa5a5a5a5; //testPayload3=0xb3f02c82;
// unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0;
// unsigned int testPayload2=0xa5a5a5a5; //testPayload3=0xb3f02c82;
//double testReceivedPayload3[NR_POLAR_PBCH_E] = {-1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1};
// double testReceivedPayload3[NR_POLAR_PBCH_E] = {-1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1,
// -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1,
// -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1,
// -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1,
// -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1,
// -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1,
// -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1,
// -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1,
// 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1,
// -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1,
// -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1,
// -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1,
// -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1,
// -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1,
// -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1,
// 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1,
// -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1,
// -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1,
// -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
// 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1,
// -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1,
// -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1,
// -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1,
// 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1,
// 1, -1, -1};
#endif
@@ -89,42 +89,7 @@ void nr_polar_generate_u(uint64_t *u,
}
}
void nr_polar_info_extraction_from_u(uint64_t *Cprime,
const uint8_t *u,
const uint8_t *information_bit_pattern,
const uint8_t *parity_check_bit_pattern,
uint16_t N,
uint8_t n_pc)
{
int k = 0;
if (n_pc > 0) {
for (int n = 0; n < N; n++) {
if (information_bit_pattern[n] == 1) {
if (parity_check_bit_pattern[n] == 0) {
int k1 = k >> 6;
int k2 = k - (k1 << 6);
Cprime[k1] |= (uint64_t)u[n] << k2;
k++;
}
}
}
} else {
for (int n = 0; n < N; n++) {
if (information_bit_pattern[n] == 1) {
int k1 = k >> 6;
int k2 = k - (k1 << 6);
Cprime[k1] |= (uint64_t)u[n] << k2;
k++;
}
}
}
}
static
void encode_packed_byte(uint8_t* in_out)
static void encode_packed_byte(uint8_t *in_out)
{
// *in_out ^= 0xAA & (*in_out << 1);
// *in_out ^= 0xCC & (*in_out << 2);
@@ -135,36 +100,33 @@ void encode_packed_byte(uint8_t* in_out)
*in_out ^= *in_out >> 4;
}
static
void polar_encode_bits(uint8_t* in_out, size_t N)
static void polar_encode_bits(uint8_t *in_out, size_t N)
{
size_t const num_bytes_per_block = N >> 3;
for(size_t i = 0; i < num_bytes_per_block; ++i){
for (size_t i = 0; i < num_bytes_per_block; ++i) {
encode_packed_byte(&in_out[i]);
}
}
static
uint32_t log2_floor(uint32_t x)
static uint32_t log2_floor(uint32_t x)
{
if(x == 0)
return 0;
if (x == 0)
return 0;
uint32_t clz = __builtin_clz(x);
return 31U - clz;
}
static
void polar_encode_bytes(uint8_t* in_out, size_t N)
static void polar_encode_bytes(uint8_t *in_out, size_t N)
{
size_t brnch_sz = 1;
size_t n_brnch = N >> 4;
size_t const blck_pwr = log2_floor(N);
size_t const blck_pwr = log2_floor(N);
for (size_t stage = 3; stage < blck_pwr; ++stage) {
for (size_t brnch = 0; brnch < n_brnch; ++brnch) {
for(size_t byte = 0; byte < brnch_sz; ++byte){
size_t const dst = 2*brnch_sz*brnch + byte;
in_out[dst] ^= in_out[dst + brnch_sz];
}
for (size_t byte = 0; byte < brnch_sz; ++byte) {
size_t const dst = 2 * brnch_sz * brnch + byte;
in_out[dst] ^= in_out[dst + brnch_sz];
}
}
n_brnch >>= 1;
brnch_sz <<= 1;
@@ -173,12 +135,12 @@ void polar_encode_bytes(uint8_t* in_out, size_t N)
void nr_polar_uxG(uint8_t const *u, size_t N, uint8_t *D2)
{
assert(N > 7);
uint8_t tmp[N/8];
for(int i = 0; i < N/8; ++i)
tmp[i] = u[N/8 - 1 - i];
assert(N > 7);
uint8_t tmp[N / 8];
for (int i = 0; i < N / 8; ++i)
tmp[i] = u[N / 8 - 1 - i];
reverse_bits_u8(tmp, N/8, D2);
reverse_bits_u8(tmp, N / 8, D2);
// Do the encoding/xor for the bottom 3 levels of the tree.
// Thus, data remaining to encode, is in 2^3 type.
@@ -187,49 +149,40 @@ void nr_polar_uxG(uint8_t const *u, size_t N, uint8_t *D2)
polar_encode_bytes(D2, N);
}
void nr_polar_bit_insertion(uint8_t *input,
uint8_t *output,
uint16_t N,
uint16_t K,
int16_t *Q_I_N,
int16_t *Q_PC_N,
uint8_t n_PC)
void nr_polar_bit_insertion(uint8_t *input, uint8_t *output, uint16_t N, uint16_t K, int16_t *Q_I_N, int16_t *Q_PC_N, uint8_t n_PC)
{
int k = 0;
if (n_PC>0) {
if (n_PC > 0) {
/*
*
*/
} else {
for (int n=0; n<=N-1; n++) {
for (int n = 0; n <= N - 1; n++) {
output[n] = 0;
for (int m=0; m<=(K+n_PC)-1; m++) {
if ( n == Q_I_N[m]) {
for (int m = 0; m <= (K + n_PC) - 1; m++) {
if (n == Q_I_N[m]) {
output[n] = input[k];
k++;
break;
}
}
}
}
}
}
uint32_t nr_polar_output_length(uint16_t K,
uint16_t E,
uint8_t n_max)
uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max)
{
int n_1, n_2, n_min = 5;
double R_min=1.0/8;
if ( (E <= (9.0/8)*pow(2,ceil(log2(E))-1)) && (K/E < 9.0/16) ) {
n_1 = ceil(log2(E))-1;
double R_min = 1.0 / 8;
if ((E <= (9.0 / 8) * pow(2, ceil(log2(E)) - 1)) && (K / E < 9.0 / 16)) {
n_1 = ceil(log2(E)) - 1;
} else {
n_1 = ceil(log2(E));
}
n_2 = ceil(log2(K/R_min));
n_2 = ceil(log2(K / R_min));
int n = n_max;
if (n > n_1)
@@ -240,9 +193,9 @@ uint32_t nr_polar_output_length(uint16_t K,
n = n_min;
/*printf("nr_polar_output_length: K %d, E %d, n %d (n_max %d,n_min %d, n_1 %d,n_2 %d)\n",
K,E,n,n_max,n_min,n_1,n_2);
exit(-1);*/
return ((uint32_t) pow(2.0,n)); //=polar_code_output_length
K,E,n,n_max,n_min,n_1,n_2);
exit(-1);*/
return ((uint32_t)pow(2.0, n)); //=polar_code_output_length
}
void nr_polar_info_bit_pattern(uint8_t *ibp,
@@ -303,7 +256,7 @@ void nr_polar_info_bit_pattern(uint8_t *ibp,
const int end = Q_Ftmp_N[N];
int m;
for (m = 0; m <= end; m++) {
AssertFatal(m < N+1, "Buffer boundary overflow");
AssertFatal(m < N + 1, "Buffer boundary overflow");
if (Q_0_Nminus1[n] == Q_Ftmp_N[m]) {
break;
}
@@ -343,7 +296,6 @@ void nr_polar_info_bit_pattern(uint8_t *ibp,
// Information and Parity Chack Bit Pattern
for (int n = 0; n <= N - 1; n++) {
ibp[n] = 0;
for (int m = 0; m <= (K + n_PC) - 1; m++) {
if (n == Q_I_N[m]) {
@@ -362,11 +314,7 @@ void nr_polar_info_bit_pattern(uint8_t *ibp,
}
}
void nr_polar_info_bit_extraction(uint8_t *input,
uint8_t *output,
uint8_t *pattern,
uint16_t size)
void nr_polar_info_bit_extraction(uint8_t *input, uint8_t *output, uint8_t *pattern, uint16_t size)
{
uint16_t j = 0;
for (int i = 0; i < size; i++) {
@@ -377,13 +325,7 @@ void nr_polar_info_bit_extraction(uint8_t *input,
}
}
void nr_polar_rate_matching_pattern(uint16_t *rmp,
uint16_t *J,
const uint8_t *P_i_,
uint16_t K,
uint16_t N,
uint16_t E)
void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, const uint8_t *P_i_, uint16_t K, uint16_t N, uint16_t E)
{
uint16_t d[N];
for (int m = 0; m < N; m++)
@@ -391,127 +333,49 @@ void nr_polar_rate_matching_pattern(uint16_t *rmp,
uint16_t y[N];
memset(y, 0, sizeof(y));
for (int m=0; m<=N-1; m++){
for (int m = 0; m <= N - 1; m++) {
int i = floor((32 * m) / N);
J[m] = (P_i_[i]*(N/32)) + (m%(N/32));
J[m] = (P_i_[i] * (N / 32)) + (m % (N / 32));
y[m] = d[J[m]];
}
if (E>=N) { //repetition
for (int k=0; k<=E-1; k++) {
if (E >= N) { // repetition
for (int k = 0; k <= E - 1; k++) {
int ind = (k % N);
rmp[k]=y[ind];
rmp[k] = y[ind];
}
} else {
if ( (K/(double)E) <= (7.0/16) ) { //puncturing
for (int k=0; k<=E-1; k++) {
rmp[k]=y[k+N-E];
if ((K / (double)E) <= (7.0 / 16)) { // puncturing
for (int k = 0; k <= E - 1; k++) {
rmp[k] = y[k + N - E];
}
} else { //shortening
for (int k=0; k<=E-1; k++) {
rmp[k]=y[k];
} else { // shortening
for (int k = 0; k <= E - 1; k++) {
rmp[k] = y[k];
}
}
}
}
void nr_polar_rate_matching(double *input,
double *output,
uint16_t *rmp,
uint16_t K,
uint16_t N,
uint16_t E)
void nr_polar_rate_matching(double *input, double *output, uint16_t *rmp, uint16_t K, uint16_t N, uint16_t E)
{
if (E>=N) { //repetition
for (int i=0; i<=N-1; i++) output[i]=0;
for (int i=0; i<=E-1; i++){
output[rmp[i]]+=input[i];
if (E >= N) { // repetition
for (int i = 0; i <= N - 1; i++)
output[i] = 0;
for (int i = 0; i <= E - 1; i++) {
output[rmp[i]] += input[i];
}
} else {
if ( (K/(double)E) <= (7.0/16) ) { //puncturing
if ((K / (double)E) <= (7.0 / 16)) { // puncturing
for (int i = 0; i <= N - 1; i++)
output[i] = 0;
} else { //shortening
} else { // shortening
for (int i = 0; i <= N - 1; i++)
output[i] = INFINITY;
}
for (int i=0; i<=E-1; i++){
output[rmp[i]]=input[i];
}
}
}
/*
* De-interleaving of coded bits implementation
* TS 138.212: Section 5.4.1.3 - Interleaving of coded bits
*/
void nr_polar_rm_deinterleaving_cb(const int16_t *in, int16_t *out, const uint16_t E)
{
int T = ceil((sqrt(8 * E + 1) - 1) / 2);
int v_tab[T][T];
memset(v_tab, 0, sizeof(v_tab));
int k = 0;
for (int i = 0; i < T; i++) {
for (int j = 0; j < T - i; j++) {
if (k < E) {
v_tab[i][j] = k + 1;
}
k++;
}
}
int v[T][T];
k = 0;
for (int j = 0; j < T; j++) {
for (int i = 0; i < T - j; i++) {
if (k < E && v_tab[i][j] != 0) {
v[i][j] = in[k];
k++;
} else {
v[i][j] = INT_MAX;
}
}
}
k = 0;
memset(out, 0, E * sizeof(*out));
for (int i = 0; i < T; i++) {
for (int j = 0; j < T - i; j++) {
if (v[i][j] != INT_MAX) {
out[k] = v[i][j];
k++;
}
}
}
}
void nr_polar_rate_matching_int16(int16_t *input,
int16_t *output,
const uint16_t *rmp,
const uint16_t K,
const uint16_t N,
const uint16_t E,
const uint8_t i_bil)
{
if (i_bil == 1) {
nr_polar_rm_deinterleaving_cb(input, input, E);
}
if (E >= N) { // repetition
memset(output, 0, N * sizeof(*output));
for (int i = 0; i <= E - 1; i++)
output[rmp[i]] += input[i];
} else {
if ((K / (double)E) <= (7.0 / 16))
memset(output, 0, N * sizeof(*output)); // puncturing
else { // shortening
for (int i = 0; i <= N - 1; i++)
output[i] = 32767; // instead of INFINITY, to prevent [-Woverflow]
}
for (int i = 0; i <= E - 1; i++)
for (int i = 0; i <= E - 1; i++) {
output[rmp[i]] = input[i];
}
}
}
@@ -7,22 +7,21 @@
#define NR_POLAR_PUCCH_PAYLOAD_BITS 16
//Ref. 38-212 v15.0.1
#define NR_POLAR_PUCCH_N_MAX 10 //uint8_t <------
#define NR_POLAR_PUCCH_I_IL 1 //uint8_t <--- interleaving: if 0 no interleaving
#define NR_POLAR_PUCCH_N_PC 3 //uint8_t <-- or zero ??
#define NR_POLAR_PUCCH_N_PC_WM 0 //uint8_t
//#define NR_POLAR_PUCCH_N 512 //uint16_t
//Ref. 38-212 v15.0.1, Section 7.1.5: Rate Matching
#define NR_POLAR_PUCCH_I_BIL 0 //uint8_t
#define NR_POLAR_PUCCH_E 864 //uint16_t
// Ref. 38-212 v15.0.1
#define NR_POLAR_PUCCH_N_MAX 10 // uint8_t <------
#define NR_POLAR_PUCCH_I_IL 1 // uint8_t <--- interleaving: if 0 no interleaving
#define NR_POLAR_PUCCH_N_PC 3 // uint8_t <-- or zero ??
#define NR_POLAR_PUCCH_N_PC_WM 0 // uint8_t
// #define NR_POLAR_PUCCH_N 512 //uint16_t
// Ref. 38-212 v15.0.1, Section 7.1.5: Rate Matching
#define NR_POLAR_PUCCH_I_BIL 0 // uint8_t
#define NR_POLAR_PUCCH_E 864 // uint16_t
/*
* TEST CODE
*/
//unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0;
//unsigned int testPayload2=0xa5a5a5a5, testPayload3=0xb3f02c82;
// unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0;
// unsigned int testPayload2=0xa5a5a5a5, testPayload3=0xb3f02c82;
#endif
@@ -22,7 +22,8 @@
#include <math.h>
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, const uint8_t *P_i_, uint16_t K, uint16_t N, uint16_t E){
void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, const uint8_t *P_i_, uint16_t K, uint16_t N, uint16_t E)
{
int d[N];
int y[N];
@@ -53,8 +54,8 @@ void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, const uint8_t *P
}
}
void nr_polar_rate_matching(double *input, double *output, uint16_t *rmp, uint16_t K, uint16_t N, uint16_t E){
void nr_polar_rate_matching(double *input, double *output, uint16_t *rmp, uint16_t K, uint16_t N, uint16_t E)
{
if (E >= N) { // repetition
for (int i = 0; i <= N - 1; i++)
output[i] = 0;
File diff suppressed because one or more lines are too long
@@ -20,32 +20,32 @@
*/
/*! \file PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h
* \brief Defines the constant variables for polar coding of the UCI from 38-212, V15.1.1 2018-04.
* \author
* \date 2018
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
* \brief Defines the constant variables for polar coding of the UCI from 38-212, V15.1.1 2018-04.
* \author
* \date 2018
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
#ifndef __NR_POLAR_UCI_DEFS__H__
#define __NR_POLAR_UCI_DEFS__H__
#define NR_POLAR_UCI_PUCCH_MESSAGE_TYPE 2 //int8_t
#define NR_POLAR_UCI_PUCCH_MESSAGE_TYPE 2 // int8_t
#define NR_POLAR_PUCCH_CRC_ERROR_CORRECTION_BITS 3
#define NR_POLAR_PUCCH_PAYLOAD_BITS 32
#define NR_POLAR_PUCCH_E 32
//Ref. 38-212, Section 6.3.1.2.1
// Ref. 38-212, Section 6.3.1.2.1
#define NR_POLAR_PUCCH_CRC_PARITY_BITS_SHORT 6
#define NR_POLAR_PUCCH_CRC_PARITY_BITS_LONG 11
#define NR_POLAR_PUCCH_I_SEG_LONG 1
#define NR_POLAR_PUCCH_I_SEG_SHORT 0
//Ref. 38-212, Section 6.3.1.3.1
// Ref. 38-212, Section 6.3.1.3.1
#define NR_POLAR_PUCCH_N_MAX 10
#define NR_POLAR_PUCCH_I_IL 0
#define NR_POLAR_PUCCH_N_PC_SHORT 3
@@ -53,9 +53,7 @@
#define NR_POLAR_PUCCH_N_PC_WM_LONG 0
#define NR_POLAR_PUCCH_N_PC_WM_SHORT 1
//Ref. 38-212, Section 6.3.1.4.1
// Ref. 38-212, Section 6.3.1.4.1
#define NR_POLAR_PUCCH_I_BIL 1
#endif