T2: Use 8b packed output of the T2 encoder
- modify retrieve_ldpc_enc_op() to store encoded results in a packed format
- add timing measurements for T2 encoder
- add simde implementation for bit reversal
- Introduce new bit reversal implementation using simde_mm_gf2p8affine_epi64_epi8
instruction, based on https://wunkolo.github.io/post/2020/11/gf2p8affineqb-bit-reversal/.
This implementation requires GFNI and AVX512VL support on the target machine.
This commit is contained in:
committed by
Romain Beurdouche
parent
4d092495bf
commit
b31dd728cb
@@ -37,6 +37,7 @@
|
|||||||
#include "nr_common.h"
|
#include "nr_common.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <simde/x86/gfni.h>
|
||||||
|
|
||||||
#define C_SRS_NUMBER (64)
|
#define C_SRS_NUMBER (64)
|
||||||
#define B_SRS_NUMBER (4)
|
#define B_SRS_NUMBER (4)
|
||||||
@@ -131,8 +132,24 @@ void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out)
|
|||||||
DevAssert(in != NULL);
|
DevAssert(in != NULL);
|
||||||
DevAssert(out != NULL);
|
DevAssert(out != NULL);
|
||||||
|
|
||||||
|
// Bit reversal implementation based on https://wunkolo.github.io/post/2020/11/gf2p8affineqb-bit-reversal/
|
||||||
|
#if defined(__GFNI__) && defined(__AVX512VL__)
|
||||||
|
int simde_sz = 16;
|
||||||
|
int i = 0;
|
||||||
|
int simde_bound = sz - simde_sz;
|
||||||
|
for (; i <= simde_bound; i += simde_sz) {
|
||||||
|
__m128i input = simde_mm_loadu_si128((__m128i *)&in[i]);
|
||||||
|
__m128i reversed = simde_mm_gf2p8affine_epi64_epi8(input, simde_mm_set1_epi64x(0x8040201008040201), 0);
|
||||||
|
simde_mm_storeu_si128((__m128i *)&out[i], reversed);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < sz; ++i) {
|
||||||
|
out[i] = bit_reverse_table_256[in[i]];
|
||||||
|
}
|
||||||
|
#else
|
||||||
for(size_t i = 0; i < sz; ++i)
|
for(size_t i = 0; i < sz; ++i)
|
||||||
out[i] = bit_reverse_table_256[in[i]];
|
out[i] = bit_reverse_table_256[in[i]];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse bits implementation based on http://graphics.stanford.edu/~seander/bithacks.html
|
// Reverse bits implementation based on http://graphics.stanford.edu/~seander/bithacks.html
|
||||||
|
|||||||
@@ -650,25 +650,40 @@ static int
|
|||||||
retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops,
|
retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops,
|
||||||
nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
||||||
{
|
{
|
||||||
|
uint8_t *p_out = NULL;
|
||||||
unsigned int j = 0;
|
unsigned int j = 0;
|
||||||
for (unsigned int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h){
|
for (unsigned int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h){
|
||||||
|
int E_sum = 0;
|
||||||
|
int bit_offset = 0;
|
||||||
|
int byte_offset = 0;
|
||||||
|
p_out = nrLDPC_slot_encoding_parameters->TBs[h].output;
|
||||||
for (unsigned int i = 0; i < nrLDPC_slot_encoding_parameters->TBs[h].C; ++i) {
|
for (unsigned int i = 0; i < nrLDPC_slot_encoding_parameters->TBs[h].C; ++i) {
|
||||||
struct rte_bbdev_op_data *output = &ops[j]->ldpc_enc.output;
|
struct rte_bbdev_op_data *output = &ops[j]->ldpc_enc.output;
|
||||||
struct rte_mbuf *m = output->data;
|
struct rte_mbuf *m = output->data;
|
||||||
uint16_t data_len = rte_pktmbuf_data_len(m) - output->offset;
|
uint16_t data_len = rte_pktmbuf_data_len(m) - output->offset;
|
||||||
uint8_t *out = nrLDPC_slot_encoding_parameters->TBs[h].output;
|
|
||||||
const char *data = m->buf_addr + m->data_off;
|
const char *data = m->buf_addr + m->data_off;
|
||||||
const char *end = data + data_len;
|
if (bit_offset == 0) {
|
||||||
while (data < end) {
|
memcpy(&p_out[byte_offset], data, data_len);
|
||||||
uint8_t byte = *data++; // get the current byte
|
} else {
|
||||||
for (int bit = 7; bit >= 0; --bit) {
|
uint8_t carry = 0;
|
||||||
*out++ = (byte >> bit) & 1; // extract each bit
|
p_out[byte_offset - 1] |= data[0] >> bit_offset;
|
||||||
|
for (size_t i = 0; i < data_len; i++) {
|
||||||
|
uint8_t current = *data++;
|
||||||
|
p_out[byte_offset + i] = (current << (8 - bit_offset));
|
||||||
|
if (i != 0) {
|
||||||
|
carry = current >> bit_offset;
|
||||||
|
p_out[byte_offset + i - 1] |= carry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
E_sum += nrLDPC_slot_encoding_parameters->TBs[h].segments[i].E;
|
||||||
|
byte_offset = (E_sum + 7) / 8;
|
||||||
|
bit_offset = E_sum % 8;
|
||||||
rte_pktmbuf_free(m);
|
rte_pktmbuf_free(m);
|
||||||
rte_pktmbuf_free(ops[j]->ldpc_enc.input.data);
|
rte_pktmbuf_free(ops[j]->ldpc_enc.input.data);
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
|
reverse_bits_u8(p_out, byte_offset, p_out);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -815,6 +830,10 @@ static int pmd_lcore_ldpc_enc(void *arg)
|
|||||||
AssertFatal(ret == 0, "Allocation failed for %d ops", num_segments);
|
AssertFatal(ret == 0, "Allocation failed for %d ops", num_segments);
|
||||||
|
|
||||||
set_ldpc_enc_op(ops_enq, 0, bufs->inputs, bufs->hard_outputs, nrLDPC_slot_encoding_parameters);
|
set_ldpc_enc_op(ops_enq, 0, bufs->inputs, bufs->hard_outputs, nrLDPC_slot_encoding_parameters);
|
||||||
|
if (nrLDPC_slot_encoding_parameters->tprep != NULL)
|
||||||
|
stop_meas(nrLDPC_slot_encoding_parameters->tprep);
|
||||||
|
if (nrLDPC_slot_encoding_parameters->tparity != NULL)
|
||||||
|
start_meas(nrLDPC_slot_encoding_parameters->tparity);
|
||||||
for (enq = 0, deq = 0; enq < num_segments;) {
|
for (enq = 0, deq = 0; enq < num_segments;) {
|
||||||
num_to_enq = num_segments;
|
num_to_enq = num_segments;
|
||||||
if (unlikely(num_segments - enq < num_to_enq))
|
if (unlikely(num_segments - enq < num_to_enq))
|
||||||
@@ -828,10 +847,14 @@ static int pmd_lcore_ldpc_enc(void *arg)
|
|||||||
time_out++;
|
time_out++;
|
||||||
DevAssert(time_out <= TIME_OUT_POLL);
|
DevAssert(time_out <= TIME_OUT_POLL);
|
||||||
}
|
}
|
||||||
|
if (nrLDPC_slot_encoding_parameters->tparity != NULL)
|
||||||
|
stop_meas(nrLDPC_slot_encoding_parameters->tparity);
|
||||||
|
if (nrLDPC_slot_encoding_parameters->toutput != NULL)
|
||||||
|
start_meas(nrLDPC_slot_encoding_parameters->toutput);
|
||||||
ret = retrieve_ldpc_enc_op(ops_deq, nrLDPC_slot_encoding_parameters);
|
ret = retrieve_ldpc_enc_op(ops_deq, nrLDPC_slot_encoding_parameters);
|
||||||
AssertFatal(ret == 0, "Failed to retrieve LDPC encoding op!");
|
AssertFatal(ret == 0, "Failed to retrieve LDPC encoding op!");
|
||||||
|
if (nrLDPC_slot_encoding_parameters->toutput != NULL)
|
||||||
|
stop_meas(nrLDPC_slot_encoding_parameters->toutput);
|
||||||
rte_bbdev_enc_op_free_bulk(ops_enq, num_segments);
|
rte_bbdev_enc_op_free_bulk(ops_enq, num_segments);
|
||||||
rte_free(ops_enq);
|
rte_free(ops_enq);
|
||||||
rte_free(ops_deq);
|
rte_free(ops_deq);
|
||||||
@@ -1074,6 +1097,8 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec
|
|||||||
int32_t nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
int32_t nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&encode_mutex);
|
pthread_mutex_lock(&encode_mutex);
|
||||||
|
if (nrLDPC_slot_encoding_parameters->tprep != NULL)
|
||||||
|
start_meas(nrLDPC_slot_encoding_parameters->tprep);
|
||||||
// hardcoded to use the first found board
|
// hardcoded to use the first found board
|
||||||
struct active_device *ad = active_devs;
|
struct active_device *ad = active_devs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user