Integrated RM lut in sch.c

master
ismagom 9 years ago
parent 784aea119b
commit df9ef48d53

@ -59,11 +59,6 @@ typedef struct SRSLTE_API {
* The encoder produces parity bits only and rate matching will interleave them * The encoder produces parity bits only and rate matching will interleave them
* with the systematic bits * 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, SRSLTE_API int srslte_tcod_init(srslte_tcod_t *h,
uint32_t max_long_cb); 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, SRSLTE_API int srslte_tcod_encode_lut(srslte_tcod_t *h,
uint8_t *input, uint8_t *input,
srslte_tcod_out_t *output, uint8_t *parity,
uint32_t long_cb); uint32_t cblen_idx);
SRSLTE_API void srslte_tcod_output_to_array(uint8_t *input_bytes,
srslte_tcod_out_t *output,
uint8_t *array,
uint32_t long_cb);
SRSLTE_API void srslte_tcod_gentable(); SRSLTE_API void srslte_tcod_gentable();

@ -68,7 +68,6 @@ typedef struct SRSLTE_API {
uint8_t *cb_temp; uint8_t *cb_temp;
void *cb_out; void *cb_out;
void *e; void *e;
srslte_tcod_out_t cb_tcod_out;
srslte_tcod_t encoder; srslte_tcod_t encoder;
srslte_tdec_t decoder; 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_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 interleaver_parity_bits[SRSLTE_NOF_TC_CB_SIZES][2*6148];
static uint32_t k0_vec[SRSLTE_NOF_TC_CB_SIZES][4][2]; 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) { void srslte_rm_turbo_gentable_systematic(uint32_t *table_bits, uint32_t k0_vec[4][2], uint32_t nrows, int ndummy) {
@ -121,6 +121,8 @@ void srslte_rm_turbo_gentable_parity(uint32_t *table_parity, uint32_t k0_vec[4][
} }
void srslte_rm_turbo_gentables() { void srslte_rm_turbo_gentables() {
if (!rm_turbo_tables_generated) {
rm_turbo_tables_generated = true;
for (int cb_idx=0;cb_idx<SRSLTE_NOF_TC_CB_SIZES;cb_idx++) { for (int cb_idx=0;cb_idx<SRSLTE_NOF_TC_CB_SIZES;cb_idx++) {
int cb_len=srslte_cbsegm_cbsize(cb_idx); int cb_len=srslte_cbsegm_cbsize(cb_idx);
int in_len=3*cb_len+12; int in_len=3*cb_len+12;
@ -139,6 +141,7 @@ void srslte_rm_turbo_gentables() {
srslte_rm_turbo_gentable_systematic(interleaver_systematic_bits[cb_idx], k0_vec[cb_idx], 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); 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) { 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,40 +184,38 @@ 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 */ /* 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 (cblen_idx < 188) {
uint32_t long_cb = srslte_cbsegm_cbsize(cblen_idx);
if (long_cb % 8) { if (long_cb % 8) {
fprintf(stderr, "Turbo coder LUT implementation long_cb must be multiple of 8\n"); fprintf(stderr, "Turbo coder LUT implementation long_cb must be multiple of 8\n");
return -1; 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 */ /* Parity bits for the 1st constituent encoders */
uint8_t state0 = 0; uint8_t state0 = 0;
for (uint32_t i=0;i<long_cb/8;i++) { for (uint32_t i=0;i<long_cb/8;i++) {
output->parity1[i] = tcod_lut_output[len_idx][state0][input[i]]; parity[i] = tcod_lut_output[cblen_idx][state0][input[i]];
state0 = tcod_lut_next_state[len_idx][state0][input[i]] % 8; state0 = tcod_lut_next_state[cblen_idx][state0][input[i]] % 8;
} }
/* Interleave input */ /* Interleave input */
srslte_bit_interleave(input, h->temp, tcod_per_fw[len_idx], long_cb); srslte_bit_interleave(input, h->temp, tcod_per_fw[cblen_idx], long_cb);
/* Parity bits for the 2nd constituent encoders */ /* Parity bits for the 2nd constituent encoders */
uint8_t state1 = 0; uint8_t state1 = 0;
for (uint32_t i=0;i<long_cb/8;i++) { for (uint32_t i=0;i<long_cb/8;i++) {
output->parity2[i] = tcod_lut_output[len_idx][state1][h->temp[i]]; parity[long_cb/8+i] = tcod_lut_output[cblen_idx][state1][h->temp[i]];
state1 = tcod_lut_next_state[len_idx][state1][h->temp[i]] % 8; state1 = tcod_lut_next_state[cblen_idx][state1][h->temp[i]] % 8;
} }
/* Tail bits */ /* Tail bits */
uint8_t reg1_0, reg1_1, reg1_2, reg2_0, reg2_1, reg2_2; uint8_t reg1_0, reg1_1, reg1_2, reg2_0, reg2_1, reg2_2;
uint8_t bit, in, out; uint8_t bit, in, out;
uint8_t k=0; uint8_t k=0;
uint8_t tail[12];
reg2_0 = (state1&4)>>2; reg2_0 = (state1&4)>>2;
reg2_1 = (state1&2)>>1; reg2_1 = (state1&2)>>1;
@ -231,7 +229,7 @@ int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, srslte_tcod_out_t *
for (uint32_t j = 0; j < NOF_REGS; j++) { for (uint32_t j = 0; j < NOF_REGS; j++) {
bit = reg1_2 ^ reg1_1; bit = reg1_2 ^ reg1_1;
output->tail[k] = bit; tail[k] = bit;
k++; k++;
in = bit ^ (reg1_2 ^ reg1_1); in = bit ^ (reg1_2 ^ reg1_1);
@ -241,7 +239,7 @@ int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, srslte_tcod_out_t *
reg1_1 = reg1_0; reg1_1 = reg1_0;
reg1_0 = in; reg1_0 = in;
output->tail[k] = out; tail[k] = out;
k++; k++;
} }
@ -249,7 +247,7 @@ int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, srslte_tcod_out_t *
for (uint32_t j = 0; j < NOF_REGS; j++) { for (uint32_t j = 0; j < NOF_REGS; j++) {
bit = reg2_2 ^ reg2_1; bit = reg2_2 ^ reg2_1;
output->tail[k] = bit; tail[k] = bit;
k++; k++;
in = bit ^ (reg2_2 ^ reg2_1); in = bit ^ (reg2_2 ^ reg2_1);
@ -259,24 +257,29 @@ int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, srslte_tcod_out_t *
reg2_1 = reg2_0; reg2_1 = reg2_0;
reg2_0 = in; reg2_0 = in;
output->tail[k] = out; tail[k] = out;
k++; k++;
} }
return 2*long_cb+TOTALTAIL; uint8_t tailv[3][4];
} for (int i=0;i<4;i++) {
for (int j=0;j<3;j++) {
void srslte_tcod_output_to_array(uint8_t *input_bytes, srslte_tcod_out_t *output, uint8_t *array, uint32_t long_cb) tailv[j][i] = tail[3*i+j];
{ }
for (int i=0;i<long_cb;i++) { }
array[3*i] = input_bytes[i/8] & (1<<(7-i%8))?1:0; uint8_t *x = tailv[0];
array[3*i+1] = output->parity1[i/8] & (1<<(7-i%8))?1:0; input[long_cb/8] = srslte_bit_pack(&x, 4);
array[3*i+2] = output->parity2[i/8] & (1<<(7-i%8))?1:0; 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;
} }
memcpy(&array[3*long_cb], output->tail, 12);
} }
void srslte_tcod_gentable() { void srslte_tcod_gentable() {
srslte_tc_interl_t interl; 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_bytes[6144/8];
uint8_t input_bits[6144]; uint8_t input_bits[6144];
uint8_t parity[3*6144+12];
uint8_t output_bits[3*6144+12]; uint8_t output_bits[3*6144+12];
uint8_t output_bits2[3*6144+12]; uint8_t output_bits2[3*6144+12];
srslte_tcod_out_t tcod_output;
int main(int argc, char **argv) { 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(&tcod, input_bits, output_bits, long_cb);
srslte_tcod_encode_lut(&tcod, input_bytes, &tcod_output, long_cb); srslte_tcod_encode_lut(&tcod, input_bytes, parity, long_cb);
srslte_tcod_output_to_array(input_bytes, &tcod_output, output_bits2, long_cb);
if (SRSLTE_VERBOSE_ISINFO()) { if (SRSLTE_VERBOSE_ISINFO()) {
printf("1st encoder\n"); printf("1st encoder\n");

@ -106,6 +106,8 @@ int srslte_sch_init(srslte_sch_t *q) {
goto clean; goto clean;
} }
srslte_rm_turbo_gentables();
// Allocate floats for reception (LLRs) // Allocate floats for reception (LLRs)
q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB); q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB);
if (!q->cb_in) { if (!q->cb_in) {
@ -171,7 +173,7 @@ static int encode_tb(srslte_sch_t *q,
uint8_t parity[3] = {0, 0, 0}; uint8_t parity[3] = {0, 0, 0};
uint32_t par; uint32_t par;
uint32_t i; 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
@ -180,6 +182,11 @@ static int encode_tb(srslte_sch_t *q,
soft_buffer != NULL) 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 Gp = nof_e_bits / Qm;
uint32_t gamma = Gp; uint32_t gamma = Gp;
@ -220,40 +227,37 @@ static int encode_tb(srslte_sch_t *q,
} else { } else {
rlen = cb_len; rlen = cb_len;
} }
if (i == 0) {
F = cb_segm->F;
} else {
F = 0;
}
if (i <= cb_segm->C - gamma - 1) { if (i <= cb_segm->C - gamma - 1) {
n_e = Qm * (Gp/cb_segm->C); n_e = Qm * (Gp/cb_segm->C);
} else { } else {
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C)); 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, INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, E: %d\n", i,
cb_len, rlen - F, wp, rp, F, n_e); 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) { if (data) {
/* Copy data to another buffer, making space for the Codeblock CRC */ /* Copy data to another buffer, making space for the Codeblock CRC */
if (i < cb_segm->C - 1) { if (i < cb_segm->C - 1) {
// Copy data // 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 { } else {
INFO("Last CB, appending parity: %d from %d and 24 to %d\n", 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 */ /* 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)); 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 */ /* Attach Codeblock CRC */
if (cb_segm->C > 1) { if (cb_segm->C > 1) {
srslte_crc_attach_byte(&q->crc_cb, q->cb_in, rlen); 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 */ /* Turbo Encoding */
srslte_tcod_encode_lut(&q->encoder, q->cb_in, &q->cb_tcod_out, cb_len); srslte_tcod_encode_lut(&q->encoder, q->cb_in, (uint8_t*) q->cb_out, cblen_idx);
srslte_tcod_output_to_array(q->cb_in, &q->cb_tcod_out, q->cb_out, cb_len);
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("CB#%d encoded: ", i); DEBUG("CB#%d encoded: ", i);
@ -275,16 +278,14 @@ static int encode_tb(srslte_sch_t *q,
} }
/* Rate matching */ /* Rate matching */
if (srslte_rm_turbo_tx(soft_buffer->buffer_b[i], soft_buffer->buff_size, 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))
(uint8_t*) q->cb_out, 3 * cb_len + 12,
&e_bits[wp], n_e, rv))
{ {
fprintf(stderr, "Error in rate matching\n"); fprintf(stderr, "Error in rate matching\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
/* Set read/write pointers */ /* Set read/write pointers */
rp += (rlen - F); rp += rlen;
wp += n_e; wp += n_e;
} }
INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); 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; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); 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_ri_len = 0;
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 0;
for (uint32_t i=0;i<20;i++) { for (uint32_t i=0;i<20;i++) {
uci_data.uci_cqi [i] = 1; uci_data.uci_cqi [i] = 1;
@ -198,7 +198,7 @@ int main(int argc, char **argv) {
goto quit; 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; data[i] = 1;
} }

Loading…
Cancel
Save