mirror of https://github.com/PentHertz/srsLTE.git
Integrated RM lut in sch.c
This commit is contained in:
parent
784aea119b
commit
df9ef48d53
|
@ -59,11 +59,6 @@ typedef struct SRSLTE_API {
|
|||
* The encoder produces parity bits only and rate matching will interleave them
|
||||
* with the systematic bits
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t parity1[SRSLTE_TCOD_MAX_LEN_CB_BYTES];
|
||||
uint8_t parity2[SRSLTE_TCOD_MAX_LEN_CB_BYTES];
|
||||
uint8_t tail[12]; // this bits are unpacked
|
||||
} srslte_tcod_out_t;
|
||||
|
||||
SRSLTE_API int srslte_tcod_init(srslte_tcod_t *h,
|
||||
uint32_t max_long_cb);
|
||||
|
@ -77,13 +72,8 @@ SRSLTE_API int srslte_tcod_encode(srslte_tcod_t *h,
|
|||
|
||||
SRSLTE_API int srslte_tcod_encode_lut(srslte_tcod_t *h,
|
||||
uint8_t *input,
|
||||
srslte_tcod_out_t *output,
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tcod_output_to_array(uint8_t *input_bytes,
|
||||
srslte_tcod_out_t *output,
|
||||
uint8_t *array,
|
||||
uint32_t long_cb);
|
||||
uint8_t *parity,
|
||||
uint32_t cblen_idx);
|
||||
|
||||
SRSLTE_API void srslte_tcod_gentable();
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ typedef struct SRSLTE_API {
|
|||
uint8_t *cb_temp;
|
||||
void *cb_out;
|
||||
void *e;
|
||||
srslte_tcod_out_t cb_tcod_out;
|
||||
|
||||
srslte_tcod_t encoder;
|
||||
srslte_tdec_t decoder;
|
||||
|
|
|
@ -48,7 +48,7 @@ static uint8_t RM_PERM_TC[NCOLS] = { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26,
|
|||
static uint32_t interleaver_systematic_bits[SRSLTE_NOF_TC_CB_SIZES][6148]; // 4 tail bits
|
||||
static uint32_t interleaver_parity_bits[SRSLTE_NOF_TC_CB_SIZES][2*6148];
|
||||
static uint32_t k0_vec[SRSLTE_NOF_TC_CB_SIZES][4][2];
|
||||
|
||||
static bool rm_turbo_tables_generated = false;
|
||||
|
||||
|
||||
void srslte_rm_turbo_gentable_systematic(uint32_t *table_bits, uint32_t k0_vec[4][2], uint32_t nrows, int ndummy) {
|
||||
|
@ -121,24 +121,27 @@ void srslte_rm_turbo_gentable_parity(uint32_t *table_parity, uint32_t k0_vec[4][
|
|||
}
|
||||
|
||||
void srslte_rm_turbo_gentables() {
|
||||
for (int cb_idx=0;cb_idx<SRSLTE_NOF_TC_CB_SIZES;cb_idx++) {
|
||||
int cb_len=srslte_cbsegm_cbsize(cb_idx);
|
||||
int in_len=3*cb_len+12;
|
||||
|
||||
int nrows = (in_len / 3 - 1) / NCOLS + 1;
|
||||
int K_p = nrows * NCOLS;
|
||||
int ndummy = K_p - in_len / 3;
|
||||
if (ndummy < 0) {
|
||||
ndummy = 0;
|
||||
}
|
||||
if (!rm_turbo_tables_generated) {
|
||||
rm_turbo_tables_generated = true;
|
||||
for (int cb_idx=0;cb_idx<SRSLTE_NOF_TC_CB_SIZES;cb_idx++) {
|
||||
int cb_len=srslte_cbsegm_cbsize(cb_idx);
|
||||
int in_len=3*cb_len+12;
|
||||
|
||||
int nrows = (in_len / 3 - 1) / NCOLS + 1;
|
||||
int K_p = nrows * NCOLS;
|
||||
int ndummy = K_p - in_len / 3;
|
||||
if (ndummy < 0) {
|
||||
ndummy = 0;
|
||||
}
|
||||
|
||||
for (int i=0;i<4;i++) {
|
||||
k0_vec[cb_idx][i][0] = nrows * (2 * (uint32_t) ceilf((float) (3*K_p) / (float) (8 * nrows)) * i + 2);
|
||||
k0_vec[cb_idx][i][1] = -1;
|
||||
for (int i=0;i<4;i++) {
|
||||
k0_vec[cb_idx][i][0] = nrows * (2 * (uint32_t) ceilf((float) (3*K_p) / (float) (8 * nrows)) * i + 2);
|
||||
k0_vec[cb_idx][i][1] = -1;
|
||||
}
|
||||
srslte_rm_turbo_gentable_systematic(interleaver_systematic_bits[cb_idx], k0_vec[cb_idx], nrows, ndummy);
|
||||
srslte_rm_turbo_gentable_parity(interleaver_parity_bits[cb_idx], k0_vec[cb_idx], in_len/3, nrows, ndummy);
|
||||
}
|
||||
srslte_rm_turbo_gentable_systematic(interleaver_systematic_bits[cb_idx], k0_vec[cb_idx], nrows, ndummy);
|
||||
srslte_rm_turbo_gentable_parity(interleaver_parity_bits[cb_idx], k0_vec[cb_idx], in_len/3, nrows, ndummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_rm_turbo_tx_lut(uint8_t *w_buff, uint8_t *systematic, uint8_t *parity, uint8_t *output, uint32_t cb_idx, uint32_t out_len, uint32_t rv_idx) {
|
||||
|
|
|
@ -184,99 +184,102 @@ int srslte_tcod_encode(srslte_tcod_t *h, uint8_t *input, uint8_t *output, uint32
|
|||
}
|
||||
|
||||
/* Expects bytes and produces bytes. The systematic and parity bits are interlaced in the output */
|
||||
int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, srslte_tcod_out_t *output, uint32_t long_cb)
|
||||
int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, uint8_t *parity, uint32_t cblen_idx)
|
||||
{
|
||||
if (long_cb % 8) {
|
||||
fprintf(stderr, "Turbo coder LUT implementation long_cb must be multiple of 8\n");
|
||||
if (cblen_idx < 188) {
|
||||
uint32_t long_cb = srslte_cbsegm_cbsize(cblen_idx);
|
||||
|
||||
if (long_cb % 8) {
|
||||
fprintf(stderr, "Turbo coder LUT implementation long_cb must be multiple of 8\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parity bits for the 1st constituent encoders */
|
||||
uint8_t state0 = 0;
|
||||
for (uint32_t i=0;i<long_cb/8;i++) {
|
||||
parity[i] = tcod_lut_output[cblen_idx][state0][input[i]];
|
||||
state0 = tcod_lut_next_state[cblen_idx][state0][input[i]] % 8;
|
||||
}
|
||||
|
||||
/* Interleave input */
|
||||
srslte_bit_interleave(input, h->temp, tcod_per_fw[cblen_idx], long_cb);
|
||||
|
||||
/* Parity bits for the 2nd constituent encoders */
|
||||
uint8_t state1 = 0;
|
||||
for (uint32_t i=0;i<long_cb/8;i++) {
|
||||
parity[long_cb/8+i] = tcod_lut_output[cblen_idx][state1][h->temp[i]];
|
||||
state1 = tcod_lut_next_state[cblen_idx][state1][h->temp[i]] % 8;
|
||||
}
|
||||
|
||||
/* Tail bits */
|
||||
uint8_t reg1_0, reg1_1, reg1_2, reg2_0, reg2_1, reg2_2;
|
||||
uint8_t bit, in, out;
|
||||
uint8_t k=0;
|
||||
uint8_t tail[12];
|
||||
|
||||
reg2_0 = (state1&4)>>2;
|
||||
reg2_1 = (state1&2)>>1;
|
||||
reg2_2 = state1&1;
|
||||
|
||||
reg1_0 = (state0&4)>>2;
|
||||
reg1_1 = (state0&2)>>1;
|
||||
reg1_2 = state0&1;
|
||||
|
||||
/* TAILING CODER #1 */
|
||||
for (uint32_t j = 0; j < NOF_REGS; j++) {
|
||||
bit = reg1_2 ^ reg1_1;
|
||||
|
||||
tail[k] = bit;
|
||||
k++;
|
||||
|
||||
in = bit ^ (reg1_2 ^ reg1_1);
|
||||
out = reg1_2 ^ (reg1_0 ^ in);
|
||||
|
||||
reg1_2 = reg1_1;
|
||||
reg1_1 = reg1_0;
|
||||
reg1_0 = in;
|
||||
|
||||
tail[k] = out;
|
||||
k++;
|
||||
}
|
||||
|
||||
/* TAILING CODER #2 */
|
||||
for (uint32_t j = 0; j < NOF_REGS; j++) {
|
||||
bit = reg2_2 ^ reg2_1;
|
||||
|
||||
tail[k] = bit;
|
||||
k++;
|
||||
|
||||
in = bit ^ (reg2_2 ^ reg2_1);
|
||||
out = reg2_2 ^ (reg2_0 ^ in);
|
||||
|
||||
reg2_2 = reg2_1;
|
||||
reg2_1 = reg2_0;
|
||||
reg2_0 = in;
|
||||
|
||||
tail[k] = out;
|
||||
k++;
|
||||
}
|
||||
|
||||
uint8_t tailv[3][4];
|
||||
for (int i=0;i<4;i++) {
|
||||
for (int j=0;j<3;j++) {
|
||||
tailv[j][i] = tail[3*i+j];
|
||||
}
|
||||
}
|
||||
uint8_t *x = tailv[0];
|
||||
input[long_cb/8] = srslte_bit_pack(&x, 4);
|
||||
x = tailv[1];
|
||||
parity[long_cb/8] = srslte_bit_pack(&x, 4);
|
||||
x = tailv[2];
|
||||
parity[2*long_cb/8] = srslte_bit_pack(&x, 4);
|
||||
|
||||
return 3*long_cb+TOTALTAIL;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = srslte_cbsegm_cbindex(long_cb);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t len_idx = (uint8_t) ret;
|
||||
|
||||
/* Parity bits for the 1st constituent encoders */
|
||||
uint8_t state0 = 0;
|
||||
for (uint32_t i=0;i<long_cb/8;i++) {
|
||||
output->parity1[i] = tcod_lut_output[len_idx][state0][input[i]];
|
||||
state0 = tcod_lut_next_state[len_idx][state0][input[i]] % 8;
|
||||
}
|
||||
|
||||
/* Interleave input */
|
||||
srslte_bit_interleave(input, h->temp, tcod_per_fw[len_idx], long_cb);
|
||||
|
||||
/* Parity bits for the 2nd constituent encoders */
|
||||
uint8_t state1 = 0;
|
||||
for (uint32_t i=0;i<long_cb/8;i++) {
|
||||
output->parity2[i] = tcod_lut_output[len_idx][state1][h->temp[i]];
|
||||
state1 = tcod_lut_next_state[len_idx][state1][h->temp[i]] % 8;
|
||||
}
|
||||
|
||||
/* Tail bits */
|
||||
uint8_t reg1_0, reg1_1, reg1_2, reg2_0, reg2_1, reg2_2;
|
||||
uint8_t bit, in, out;
|
||||
uint8_t k=0;
|
||||
|
||||
reg2_0 = (state1&4)>>2;
|
||||
reg2_1 = (state1&2)>>1;
|
||||
reg2_2 = state1&1;
|
||||
|
||||
reg1_0 = (state0&4)>>2;
|
||||
reg1_1 = (state0&2)>>1;
|
||||
reg1_2 = state0&1;
|
||||
|
||||
/* TAILING CODER #1 */
|
||||
for (uint32_t j = 0; j < NOF_REGS; j++) {
|
||||
bit = reg1_2 ^ reg1_1;
|
||||
|
||||
output->tail[k] = bit;
|
||||
k++;
|
||||
|
||||
in = bit ^ (reg1_2 ^ reg1_1);
|
||||
out = reg1_2 ^ (reg1_0 ^ in);
|
||||
|
||||
reg1_2 = reg1_1;
|
||||
reg1_1 = reg1_0;
|
||||
reg1_0 = in;
|
||||
|
||||
output->tail[k] = out;
|
||||
k++;
|
||||
}
|
||||
|
||||
/* TAILING CODER #2 */
|
||||
for (uint32_t j = 0; j < NOF_REGS; j++) {
|
||||
bit = reg2_2 ^ reg2_1;
|
||||
|
||||
output->tail[k] = bit;
|
||||
k++;
|
||||
|
||||
in = bit ^ (reg2_2 ^ reg2_1);
|
||||
out = reg2_2 ^ (reg2_0 ^ in);
|
||||
|
||||
reg2_2 = reg2_1;
|
||||
reg2_1 = reg2_0;
|
||||
reg2_0 = in;
|
||||
|
||||
output->tail[k] = out;
|
||||
k++;
|
||||
}
|
||||
|
||||
return 2*long_cb+TOTALTAIL;
|
||||
}
|
||||
|
||||
void srslte_tcod_output_to_array(uint8_t *input_bytes, srslte_tcod_out_t *output, uint8_t *array, uint32_t long_cb)
|
||||
{
|
||||
for (int i=0;i<long_cb;i++) {
|
||||
array[3*i] = input_bytes[i/8] & (1<<(7-i%8))?1:0;
|
||||
array[3*i+1] = output->parity1[i/8] & (1<<(7-i%8))?1:0;
|
||||
array[3*i+2] = output->parity2[i/8] & (1<<(7-i%8))?1:0;
|
||||
}
|
||||
memcpy(&array[3*long_cb], output->tail, 12);
|
||||
}
|
||||
|
||||
|
||||
void srslte_tcod_gentable() {
|
||||
srslte_tc_interl_t interl;
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ void parse_args(int argc, char **argv) {
|
|||
|
||||
uint8_t input_bytes[6144/8];
|
||||
uint8_t input_bits[6144];
|
||||
uint8_t parity[3*6144+12];
|
||||
uint8_t output_bits[3*6144+12];
|
||||
uint8_t output_bits2[3*6144+12];
|
||||
srslte_tcod_out_t tcod_output;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
@ -99,9 +99,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
srslte_tcod_encode(&tcod, input_bits, output_bits, long_cb);
|
||||
srslte_tcod_encode_lut(&tcod, input_bytes, &tcod_output, long_cb);
|
||||
|
||||
srslte_tcod_output_to_array(input_bytes, &tcod_output, output_bits2, long_cb);
|
||||
srslte_tcod_encode_lut(&tcod, input_bytes, parity, long_cb);
|
||||
|
||||
if (SRSLTE_VERBOSE_ISINFO()) {
|
||||
printf("1st encoder\n");
|
||||
|
|
|
@ -106,6 +106,8 @@ int srslte_sch_init(srslte_sch_t *q) {
|
|||
goto clean;
|
||||
}
|
||||
|
||||
srslte_rm_turbo_gentables();
|
||||
|
||||
// Allocate floats for reception (LLRs)
|
||||
q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB);
|
||||
if (!q->cb_in) {
|
||||
|
@ -171,7 +173,7 @@ static int encode_tb(srslte_sch_t *q,
|
|||
uint8_t parity[3] = {0, 0, 0};
|
||||
uint32_t par;
|
||||
uint32_t i;
|
||||
uint32_t cb_len, rp, wp, rlen, F, n_e;
|
||||
uint32_t cb_len, rp, wp, rlen, n_e;
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
|
@ -180,6 +182,11 @@ static int encode_tb(srslte_sch_t *q,
|
|||
soft_buffer != NULL)
|
||||
{
|
||||
|
||||
if (cb_segm->F) {
|
||||
fprintf(stderr, "Error filler bits are not supported. Use standard TBS\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
uint32_t Gp = nof_e_bits / Qm;
|
||||
|
||||
uint32_t gamma = Gp;
|
||||
|
@ -220,40 +227,37 @@ static int encode_tb(srslte_sch_t *q,
|
|||
} else {
|
||||
rlen = cb_len;
|
||||
}
|
||||
if (i == 0) {
|
||||
F = cb_segm->F;
|
||||
} else {
|
||||
F = 0;
|
||||
}
|
||||
if (i <= cb_segm->C - gamma - 1) {
|
||||
n_e = Qm * (Gp/cb_segm->C);
|
||||
} else {
|
||||
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
|
||||
}
|
||||
|
||||
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
|
||||
cb_len, rlen - F, wp, rp, F, n_e);
|
||||
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, E: %d\n", i,
|
||||
cb_len, rlen, wp, rp, n_e);
|
||||
|
||||
int ret = srslte_cbsegm_cbindex(cb_len);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error invalid CBLEN=%d\n", cb_len);
|
||||
return -1;
|
||||
}
|
||||
uint8_t cblen_idx = (uint8_t) ret;
|
||||
|
||||
if (data) {
|
||||
|
||||
/* Copy data to another buffer, making space for the Codeblock CRC */
|
||||
if (i < cb_segm->C - 1) {
|
||||
// Copy data
|
||||
memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - F) * sizeof(uint8_t)/8);
|
||||
memcpy(q->cb_in, &data[rp/8], rlen * sizeof(uint8_t)/8);
|
||||
} else {
|
||||
INFO("Last CB, appending parity: %d from %d and 24 to %d\n",
|
||||
rlen - F - 24, rp, rlen - 24);
|
||||
rlen - 24, rp, rlen - 24);
|
||||
|
||||
/* Append Transport Block parity bits to the last CB */
|
||||
memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - 24 - F) * sizeof(uint8_t)/8);
|
||||
memcpy(q->cb_in, &data[rp/8], (rlen - 24) * sizeof(uint8_t)/8);
|
||||
memcpy(&q->cb_in[(rlen - 24)/8], parity, 3 * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
/* Filler bits are treated like zeros for the CB CRC calculation */
|
||||
for (int j = 0; j < F/8; j++) {
|
||||
q->cb_in[j] = 0;
|
||||
}
|
||||
|
||||
/* Attach Codeblock CRC */
|
||||
if (cb_segm->C > 1) {
|
||||
srslte_crc_attach_byte(&q->crc_cb, q->cb_in, rlen);
|
||||
|
@ -265,8 +269,7 @@ static int encode_tb(srslte_sch_t *q,
|
|||
}
|
||||
|
||||
/* Turbo Encoding */
|
||||
srslte_tcod_encode_lut(&q->encoder, q->cb_in, &q->cb_tcod_out, cb_len);
|
||||
srslte_tcod_output_to_array(q->cb_in, &q->cb_tcod_out, q->cb_out, cb_len);
|
||||
srslte_tcod_encode_lut(&q->encoder, q->cb_in, (uint8_t*) q->cb_out, cblen_idx);
|
||||
|
||||
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||||
DEBUG("CB#%d encoded: ", i);
|
||||
|
@ -275,16 +278,14 @@ static int encode_tb(srslte_sch_t *q,
|
|||
}
|
||||
|
||||
/* Rate matching */
|
||||
if (srslte_rm_turbo_tx(soft_buffer->buffer_b[i], soft_buffer->buff_size,
|
||||
(uint8_t*) q->cb_out, 3 * cb_len + 12,
|
||||
&e_bits[wp], n_e, rv))
|
||||
if (srslte_rm_turbo_tx_lut(soft_buffer->buffer_b[i], q->cb_in, (uint8_t*) q->cb_out, &e_bits[wp], cblen_idx, n_e, rv))
|
||||
{
|
||||
fprintf(stderr, "Error in rate matching\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* Set read/write pointers */
|
||||
rp += (rlen - F);
|
||||
rp += rlen;
|
||||
wp += n_e;
|
||||
}
|
||||
INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
|
||||
|
|
|
@ -167,9 +167,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
srslte_uci_data_t uci_data;
|
||||
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
||||
uci_data.uci_cqi_len = 20;
|
||||
uci_data.uci_cqi_len = 0;
|
||||
uci_data.uci_ri_len = 0;
|
||||
uci_data.uci_ack_len = 1;
|
||||
uci_data.uci_ack_len = 0;
|
||||
|
||||
for (uint32_t i=0;i<20;i++) {
|
||||
uci_data.uci_cqi [i] = 1;
|
||||
|
@ -198,7 +198,7 @@ int main(int argc, char **argv) {
|
|||
goto quit;
|
||||
}
|
||||
|
||||
for (uint32_t i=0;i<cfg.grant.mcs.tbs;i++) {
|
||||
for (uint32_t i=0;i<cfg.grant.mcs.tbs/8;i++) {
|
||||
data[i] = 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue