diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index 7757ed698..c0818c662 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -72,8 +72,8 @@ typedef struct SRSLTE_API { float *csi[SRSLTE_MAX_CODEWORDS]; /* Channel Strengh Indicator */ /* tx & rx objects */ - srslte_modem_table_t mod[4]; - + srslte_modem_table_t mod[5]; + // This is to generate the scrambling seq for multiple CRNTIs srslte_pdsch_user_t **users; diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index e1d82fc05..3a11295dc 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -103,6 +103,8 @@ SRSLTE_API int srslte_ra_tbs_idx_from_mcs(uint32_t mcs, bool is_ul); SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs); +SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs2(uint32_t mcs); + SRSLTE_API srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs); SRSLTE_API int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul); diff --git a/lib/include/srslte/phy/phch/ra_dl.h b/lib/include/srslte/phy/phch/ra_dl.h index fb311505e..4144d993b 100644 --- a/lib/include/srslte/phy/phch/ra_dl.h +++ b/lib/include/srslte/phy/phch/ra_dl.h @@ -44,10 +44,11 @@ **************************************************/ /** Functions to generate a grant from a received DCI */ -SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell, - srslte_dl_sf_cfg_t* sf, - srslte_tm_t tm, - srslte_dci_dl_t* dci, +SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell, + srslte_dl_sf_cfg_t* sf, + srslte_tm_t tm, + bool pdsch_use_tbs_index_alt, + srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant); SRSLTE_API int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci, @@ -60,7 +61,7 @@ SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t* cell, uint32_t nof SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant); /** Others */ -SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb); +SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb, bool pdsch_use_tbs_index_alt); SRSLTE_API void srslte_ra_dl_compute_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant); diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index ac1777056..6e74107dd 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -121,6 +121,7 @@ typedef struct SRSLTE_API { srslte_dci_cfg_t dci_cfg; uint32_t last_ri; float snr_to_cqi_offset; + bool pdsch_use_tbs_index_alt; } srslte_ue_dl_cfg_t; typedef struct { diff --git a/lib/src/phy/common/sequence.c b/lib/src/phy/common/sequence.c index ac333c137..ee4884123 100644 --- a/lib/src/phy/common/sequence.c +++ b/lib/src/phy/common/sequence.c @@ -31,7 +31,7 @@ #define Nc 1600 -#define MAX_SEQ_LEN (128*1024) +#define MAX_SEQ_LEN (256 * 1024) #define static_memory diff --git a/lib/src/phy/fec/softbuffer.c b/lib/src/phy/fec/softbuffer.c index d7703d489..9d0ba07e4 100644 --- a/lib/src/phy/fec/softbuffer.c +++ b/lib/src/phy/fec/softbuffer.c @@ -43,8 +43,8 @@ int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, uint32_t nof_prb) { if (q != NULL) { bzero(q, sizeof(srslte_softbuffer_rx_t)); - - ret = srslte_ra_tbs_from_idx(26, nof_prb); + + ret = srslte_ra_tbs_from_idx(33, nof_prb); if (ret != SRSLTE_ERROR) { q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; ret = SRSLTE_ERROR; @@ -154,8 +154,8 @@ int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, uint32_t nof_prb) { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_softbuffer_tx_t)); - - ret = srslte_ra_tbs_from_idx(26, nof_prb); + + ret = srslte_ra_tbs_from_idx(33, nof_prb); if (ret != SRSLTE_ERROR) { q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 06ab8b99f..2d4810d71 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -46,8 +46,8 @@ const static float pdsch_cfg_cell_specific_ratio_table[2][4] = { /* One antenna port */ {1.0f / 1.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f}, /* Two or more antenna port */ {5.0f / 4.0f, 1.0f / 1.0f, 3.0f / 4.0f, 1.0f / 2.0f}}; -const static srslte_mod_t modulations[4] = - { SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM }; +const static srslte_mod_t modulations[5] = { + SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM, SRSLTE_MOD_256QAM}; typedef struct { /* Thread identifier: they must set before thread creation */ @@ -247,7 +247,7 @@ static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 5; i++) { if (srslte_modem_table_lte(&q->mod[i], modulations[i])) { goto clean; } @@ -261,7 +261,7 @@ static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { // Allocate int16_t for reception (LLRs) - q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); + q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM)); if (!q->e[i]) { goto clean; } @@ -297,7 +297,7 @@ static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t goto clean; } - if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM))) { goto clean; } @@ -439,7 +439,7 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { srslte_sequence_free(&q->tmp_seq); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 5; i++) { srslte_modem_table_free(&q->mod[i]); } @@ -485,7 +485,7 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { j, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM))) { ERROR("Error initializing PDSCH scrambling sequence\n"); srslte_pdsch_free_rnti(q, rnti); return SRSLTE_ERROR; @@ -589,6 +589,9 @@ static void csi_correction(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, uint32_t case SRSLTE_MOD_64QAM: qm = 6; break; + case SRSLTE_MOD_256QAM: + qm = 8; + break; default: ERROR("No modulation"); } @@ -612,7 +615,7 @@ static void csi_correction(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, uint32_t } else { int i = 0; -#ifdef LV_HAVE_SSE +#ifndef LV_HAVE_SSE __m128 _csi_scale = _mm_set1_ps(INT16_MAX / csi_max); __m64* _e = (__m64*)e; @@ -656,6 +659,16 @@ static void csi_correction(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, uint32_t break; case SRSLTE_MOD_BPSK: break; + case SRSLTE_MOD_256QAM: + for (; i < cfg->grant.tb[tb_idx].nof_bits - 7; i += 8) { + __m128 _csi = _mm_set1_ps(*(csi_v++)); + + _csi = _mm_mul_ps(_csi, _csi_scale); + + _e[0] = _mm_mulhi_pi16(_e[0], _mm_cvtps_pi16(_csi)); + _e += 1; + } + break; } i /= qm; diff --git a/lib/src/phy/phch/pmch.c b/lib/src/phy/phch/pmch.c index 75e788aa0..a046d4965 100644 --- a/lib/src/phy/phch/pmch.c +++ b/lib/src/phy/phch/pmch.c @@ -397,8 +397,10 @@ void srslte_configure_pmch(srslte_pmch_cfg_t* pmch_cfg, srslte_cell_t* cell, srs pmch_cfg->pdsch_cfg.grant.tb[0].enabled = mbsfn_cfg->enable; pmch_cfg->pdsch_cfg.grant.tb[0].rv = SRSLTE_PMCH_RV; pmch_cfg->pdsch_cfg.grant.last_tbs[0] = 0; - srslte_dl_fill_ra_mcs( - &pmch_cfg->pdsch_cfg.grant.tb[0], pmch_cfg->pdsch_cfg.grant.last_tbs[0], pmch_cfg->pdsch_cfg.grant.nof_prb); + srslte_dl_fill_ra_mcs(&pmch_cfg->pdsch_cfg.grant.tb[0], + pmch_cfg->pdsch_cfg.grant.last_tbs[0], + pmch_cfg->pdsch_cfg.grant.nof_prb, + false); pmch_cfg->pdsch_cfg.grant.nof_tb = 1; pmch_cfg->pdsch_cfg.grant.nof_layers = 1; for (int i = 0; i < 2; i++) { diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 848a8ecd6..353d9fdea 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -129,6 +129,15 @@ static int srslte_ra_dl_tbs_idx_from_mcs(uint32_t mcs) } } +static int srslte_ra_dl_tbs_idx_from_mcs2(uint32_t mcs) +{ + if (mcs < 28) { + return dl_mcs_tbs_idx_table2[mcs]; + } else { + return SRSLTE_ERROR; + } +} + static int srslte_ra_ul_tbs_idx_from_mcs(uint32_t mcs) { if (mcs < 29) { @@ -151,7 +160,20 @@ srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs) return SRSLTE_MOD_16QAM; } else { return SRSLTE_MOD_64QAM; - } + } +} + +srslte_mod_t srslte_ra_dl_mod_from_mcs2(uint32_t mcs) +{ + if (mcs <= 4 || mcs == 28) { + return SRSLTE_MOD_QPSK; + } else if (mcs <= 10 || mcs == 29) { + return SRSLTE_MOD_16QAM; + } else if (mcs <= 19 || mcs == 30) { + return SRSLTE_MOD_64QAM; + } else { + return SRSLTE_MOD_256QAM; + } } srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs) @@ -178,6 +200,16 @@ static int srslte_ra_dl_mcs_from_tbs_idx(uint32_t tbs_idx) return SRSLTE_ERROR; } +static int srslte_ra_dl_mcs_from_tbs_idx2(uint32_t tbs_idx) +{ + for (int i = 0; i < 28; i++) { + if (tbs_idx == dl_mcs_tbs_idx_table2[i]) { + return i; + } + } + return SRSLTE_ERROR; +} + static int srslte_ra_ul_mcs_from_tbs_idx(uint32_t tbs_idx) { for (int i = 0; i < 29; i++) { @@ -196,7 +228,7 @@ int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul) /* Table 7.1.7.2.1-1: Transport block size table on 36.213 */ int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) { - if (tbs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) { + if (tbs_idx < 34 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) { return tbs_table[tbs_idx][n_prb - 1]; } else { return SRSLTE_ERROR; diff --git a/lib/src/phy/phch/ra_dl.c b/lib/src/phy/phch/ra_dl.c index 85db4a69e..444c5db3c 100644 --- a/lib/src/phy/phch/ra_dl.c +++ b/lib/src/phy/phch/ra_dl.c @@ -26,6 +26,7 @@ #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" #include "srslte/srslte.h" +#include "tbs_tables.h" #include #include #include @@ -316,27 +317,46 @@ int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci, srslte_pdsc return SRSLTE_SUCCESS; } -int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb) +int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb, bool pdsch_use_tbs_index_alt) { int i_tbs = 0; - if (tb->mcs_idx < 10) { - tb->mod = SRSLTE_MOD_QPSK; - i_tbs = tb->mcs_idx; - } else if (tb->mcs_idx < 17) { - tb->mod = SRSLTE_MOD_16QAM; - i_tbs = tb->mcs_idx - 1; - } else if (tb->mcs_idx < 29) { - tb->mod = SRSLTE_MOD_64QAM; - i_tbs = tb->mcs_idx - 2; - } else if (tb->mcs_idx == 29) { - tb->mod = SRSLTE_MOD_QPSK; - i_tbs = -1; - } else if (tb->mcs_idx == 30) { - tb->mod = SRSLTE_MOD_16QAM; - i_tbs = -1; - } else if (tb->mcs_idx == 31) { - tb->mod = SRSLTE_MOD_64QAM; - i_tbs = -1; + if (!pdsch_use_tbs_index_alt) { + // Implements 3GPP 36.211 Table 3.56.35-431 + if (tb->mcs_idx < 10) { + tb->mod = SRSLTE_MOD_QPSK; + i_tbs = tb->mcs_idx; + } else if (tb->mcs_idx < 17) { + tb->mod = SRSLTE_MOD_16QAM; + i_tbs = tb->mcs_idx - 1; + } else if (tb->mcs_idx < 29) { + tb->mod = SRSLTE_MOD_64QAM; + i_tbs = tb->mcs_idx - 2; + } else if (tb->mcs_idx == 29) { + tb->mod = SRSLTE_MOD_QPSK; + i_tbs = -1; + } else if (tb->mcs_idx == 30) { + tb->mod = SRSLTE_MOD_16QAM; + i_tbs = -1; + } else if (tb->mcs_idx == 31) { + tb->mod = SRSLTE_MOD_64QAM; + i_tbs = -1; + } + } else { + if (tb->mcs_idx < 28) { + i_tbs = dl_mcs_tbs_idx_table2[tb->mcs_idx]; + } else { + i_tbs = SRSLTE_ERROR; + } + + if (tb->mcs_idx < 5 || tb->mcs_idx == 28) { + tb->mod = SRSLTE_MOD_QPSK; + } else if (tb->mcs_idx < 11 || tb->mcs_idx == 29) { + tb->mod = SRSLTE_MOD_16QAM; + } else if (tb->mcs_idx < 20 || tb->mcs_idx == 30) { + tb->mod = SRSLTE_MOD_64QAM; + } else { + tb->mod = SRSLTE_MOD_256QAM; + } } // If i_tbs = -1, TBS is determined from the latest PDCCH for this TB (7.1.7.2 36.213) @@ -353,7 +373,7 @@ int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb) /* Modulation order and transport block size determination 7.1.7 in 36.213 * */ -static int dl_dci_compute_tb(srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) +static int dl_dci_compute_tb(bool pdsch_use_tbs_index_alt, srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) { uint32_t n_prb = 0; int tbs = -1; @@ -408,7 +428,7 @@ static int dl_dci_compute_tb(srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) } for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant->tb[i].enabled) { - grant->tb[i].tbs = srslte_dl_fill_ra_mcs(&grant->tb[i], grant->last_tbs[i], n_prb); + grant->tb[i].tbs = srslte_dl_fill_ra_mcs(&grant->tb[i], grant->last_tbs[i], n_prb, pdsch_use_tbs_index_alt); if (grant->tb[i].tbs < 0) { ERROR("Computing TBS from MCS=%d, n_prb=%d\n", grant->tb[i].mcs_idx, n_prb); return SRSLTE_ERROR; @@ -606,8 +626,12 @@ static int config_mimo(srslte_cell_t* cell, srslte_tm_t tm, srslte_dci_dl_t* dci **********/ /** Compute the DL grant parameters */ -int srslte_ra_dl_dci_to_grant( - srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_tm_t tm, srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) +int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell, + srslte_dl_sf_cfg_t* sf, + srslte_tm_t tm, + bool pdsch_use_tbs_index_alt, + srslte_dci_dl_t* dci, + srslte_pdsch_grant_t* grant) { bzero(grant, sizeof(srslte_pdsch_grant_t)); @@ -615,7 +639,7 @@ int srslte_ra_dl_dci_to_grant( int ret = srslte_ra_dl_grant_to_grant_prb_allocation(dci, grant, cell->nof_prb); if (ret == SRSLTE_SUCCESS) { // Compute MCS - ret = dl_dci_compute_tb(dci, grant); + ret = dl_dci_compute_tb(pdsch_use_tbs_index_alt, dci, grant); if (ret == SRSLTE_SUCCESS) { // Compute number of RE and number of ack_value in grant srslte_ra_dl_compute_nof_re(cell, sf, grant); diff --git a/lib/src/phy/phch/tbs_tables.h b/lib/src/phy/phch/tbs_tables.h index 98f0c8de0..a0743195f 100644 --- a/lib/src/phy/phch/tbs_tables.h +++ b/lib/src/phy/phch/tbs_tables.h @@ -20,281 +20,248 @@ */ /* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */ -const int dl_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, - 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; +static const int dl_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, + 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; -/* Modulation and TBS index table for PUSCH from 3GPP TS 36.213 v10.3.0 table 8.6.1-1 */ -const int ul_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26}; +/* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v12.13.0 table 7.1.7.1-1A */ +static const int dl_mcs_tbs_idx_table2[28] = {0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33}; -/* Transport Block Size from 3GPP TS 36.213 v10.3.0 table 7.1.7.2.1-1 */ -const int tbs_table[27][110] = {{ 16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, - 328, 344, 376, 392, 424, 456, 488, 504, 536, 568, 600, - 616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904, - 936, 968, 1000, 1032, 1032, 1064, 1096, 1128, 1160, 1192, 1224, - 1256, 1256, 1288, 1320, 1352, 1384, 1416, 1416, 1480, 1480, 1544, - 1544, 1608, 1608, 1608, 1672, 1672, 1736, 1736, 1800, 1800, 1800, - 1864, 1864, 1928, 1928, 1992, 1992, 2024, 2088, 2088, 2088, 2152, - 2152, 2216, 2216, 2280, 2280, 2280, 2344, 2344, 2408, 2408, 2472, - 2472, 2536, 2536, 2536, 2600, 2600, 2664, 2664, 2728, 2728, 2728, - 2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 2984, 2984, 3112}, - { 24, 56, 88, 144, 176, 208, 224, 256, 328, 344, 376, - 424, 456, 488, 520, 568, 600, 632, 680, 712, 744, 776, - 808, 872, 904, 936, 968, 1000, 1032, 1064, 1128, 1160, 1192, - 1224, 1256, 1288, 1352, 1384, 1416, 1416, 1480, 1544, 1544, 1608, - 1608, 1672, 1736, 1736, 1800, 1800, 1864, 1864, 1928, 1992, 1992, - 2024, 2088, 2088, 2152, 2152, 2216, 2280, 2280, 2344, 2344, 2408, - 2472, 2472, 2536, 2536, 2600, 2600, 2664, 2728, 2728, 2792, 2792, - 2856, 2856, 2856, 2984, 2984, 2984, 3112, 3112, 3112, 3240, 3240, - 3240, 3240, 3368, 3368, 3368, 3496, 3496, 3496, 3496, 3624, 3624, - 3624, 3752, 3752, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008}, - { 32, 72, 144, 176, 208, 256, 296, 328, 376, 424, 472, - 520, 568, 616, 648, 696, 744, 776, 840, 872, 936, 968, - 1000, 1064, 1096, 1160, 1192, 1256, 1288, 1320, 1384, 1416, 1480, - 1544, 1544, 1608, 1672, 1672, 1736, 1800, 1800, 1864, 1928, 1992, - 2024, 2088, 2088, 2152, 2216, 2216, 2280, 2344, 2344, 2408, 2472, - 2536, 2536, 2600, 2664, 2664, 2728, 2792, 2856, 2856, 2856, 2984, - 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3368, 3496, - 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 3880, 4008, - 4008, 4008, 4136, 4136, 4136, 4264, 4264, 4264, 4392, 4392, 4392, - 4584, 4584, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968}, - { 40, 104, 176, 208, 256, 328, 392, 440, 504, 568, 616, - 680, 744, 808, 872, 904, 968, 1032, 1096, 1160, 1224, 1256, - 1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, - 1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2536, - 2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240, - 3240, 3368, 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, - 3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4392, 4584, - 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 4968, 5160, 5160, - 5160, 5352, 5352, 5352, 5352, 5544, 5544, 5544, 5736, 5736, 5736, - 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6200, 6456, 6456}, - { 56, 120, 208, 256, 328, 408, 488, 552, 632, 696, 776, - 840, 904, 1000, 1064, 1128, 1192, 1288, 1352, 1416, 1480, 1544, - 1608, 1736, 1800, 1864, 1928, 1992, 2088, 2152, 2216, 2280, 2344, - 2408, 2472, 2600, 2664, 2728, 2792, 2856, 2984, 2984, 3112, 3112, - 3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008, - 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776, - 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5544, 5544, - 5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, - 6456, 6456, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 6968, - 7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992}, - { 72, 144, 224, 328, 424, 504, 600, 680, 776, 872, 968, - 1032, 1128, 1224, 1320, 1384, 1480, 1544, 1672, 1736, 1864, 1928, - 2024, 2088, 2216, 2280, 2344, 2472, 2536, 2664, 2728, 2792, 2856, - 2984, 3112, 3112, 3240, 3368, 3496, 3496, 3624, 3752, 3752, 3880, - 4008, 4008, 4136, 4264, 4392, 4392, 4584, 4584, 4776, 4776, 4776, - 4968, 4968, 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736, - 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6712, 6712, 6712, - 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7736, 7736, - 7736, 7992, 7992, 7992, 8248, 8248, 8248, 8504, 8504, 8760, 8760, - 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9528}, - { 328, 176, 256, 392, 504, 600, 712, 808, 936, 1032, 1128, - 1224, 1352, 1480, 1544, 1672, 1736, 1864, 1992, 2088, 2216, 2280, - 2408, 2472, 2600, 2728, 2792, 2984, 2984, 3112, 3240, 3368, 3496, - 3496, 3624, 3752, 3880, 4008, 4136, 4136, 4264, 4392, 4584, 4584, - 4776, 4776, 4968, 4968, 5160, 5160, 5352, 5352, 5544, 5736, 5736, - 5992, 5992, 5992, 6200, 6200, 6456, 6456, 6456, 6712, 6712, 6968, - 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992, - 8248, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, - 9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912,10296,10296,10296, - 10296,10680,10680,10680,10680,11064,11064,11064,11448,11448,11448}, - { 104, 224, 328, 472, 584, 712, 840, 968, 1096, 1224, 1320, - 1480, 1608, 1672, 1800, 1928, 2088, 2216, 2344, 2472, 2536, 2664, - 2792, 2984, 3112, 3240, 3368, 3368, 3496, 3624, 3752, 3880, 4008, - 4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352, - 5544, 5736, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6712, - 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, - 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528, - 9528, 9528, 9912, 9912, 9912,10296,10296,10296,10680,10680,10680, - 11064,11064,11064,11448,11448,11448,11448,11832,11832,11832,12216, - 12216,12216,12576,12576,12576,12960,12960,12960,12960,13536,13536}, - { 120, 256, 392, 536, 680, 808, 968, 1096, 1256, 1384, 1544, - 1672, 1800, 1928, 2088, 2216, 2344, 2536, 2664, 2792, 2984, 3112, - 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4264, 4392, 4584, 4584, - 4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200, - 6200, 6456, 6456, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, - 7736, 7992, 7992, 8248, 8504, 8504, 8760, 8760, 9144, 9144, 9144, - 9528, 9528, 9528, 9912, 9912, 9912,10296,10296,10680,10680,10680, - 11064,11064,11064,11448,11448,11448,11832,11832,12216,12216,12216, - 12576,12576,12576,12960,12960,12960,13536,13536,13536,13536,14112, - 14112,14112,14112,14688,14688,14688,14688,15264,15264,15264,15264}, - { 136, 296, 456, 616, 776, 936, 1096, 1256, 1416, 1544, 1736, - 1864, 2024, 2216, 2344, 2536, 2664, 2856, 2984, 3112, 3368, 3496, - 3624, 3752, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160, 5160, - 5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, - 6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8248, 8504, 8760, - 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912,10296,10296,10296, - 10680,10680,11064,11064,11064,11448,11448,11832,11832,11832,12216, - 12216,12576,12576,12960,12960,12960,13536,13536,13536,13536,14112, - 14112,14112,14112,14688,14688,14688,15264,15264,15264,15264,15840, - 15840,15840,16416,16416,16416,16416,16992,16992,16992,16992,17568}, - { 144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928, - 2088, 2280, 2472, 2664, 2792, 2984, 3112, 3368, 3496, 3752, 3880, - 4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, 5736, - 5992, 6200, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736, - 7992, 7992, 8248, 8504, 8504, 8760, 9144, 9144, 9144, 9528, 9528, - 9912, 9912,10296,10296,10680,10680,11064,11064,11448,11448,11448, - 11832,11832,12216,12216,12576,12576,12960,12960,12960,13536,13536, - 13536,14112,14112,14112,14688,14688,14688,14688,15264,15264,15264, - 15840,15840,15840,16416,16416,16416,16992,16992,16992,16992,17568, - 17568,17568,18336,18336,18336,18336,18336,19080,19080,19080,19080}, - { 176, 376, 584, 776, 1000, 1192, 1384, 1608, 1800, 2024, 2216, - 2408, 2600, 2792, 2984, 3240, 3496, 3624, 3880, 4008, 4264, 4392, - 4584, 4776, 4968, 5352, 5544, 5736, 5992, 5992, 6200, 6456, 6712, - 6968, 6968, 7224, 7480, 7736, 7736, 7992, 8248, 8504, 8760, 8760, - 9144, 9144, 9528, 9528, 9912, 9912,10296,10680,10680,11064,11064, - 11448,11448,11832,11832,12216,12216,12576,12576,12960,12960,13536, - 13536,13536,14112,14112,14112,14688,14688,14688,15264,15264,15840, - 15840,15840,16416,16416,16416,16992,16992,16992,17568,17568,17568, - 18336,18336,18336,18336,19080,19080,19080,19080,19848,19848,19848, - 19848,20616,20616,20616,21384,21384,21384,21384,22152,22152,22152}, - { 208, 440, 680, 904, 1128, 1352, 1608, 1800, 2024, 2280, 2472, - 2728, 2984, 3240, 3368, 3624, 3880, 4136, 4392, 4584, 4776, 4968, - 5352, 5544, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224, 7480, - 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9528, 9528, 9912, 9912, - 10296,10680,10680,11064,11064,11448,11832,11832,12216,12216,12576, - 12576,12960,12960,13536,13536,14112,14112,14112,14688,14688,15264, - 15264,15264,15840,15840,16416,16416,16416,16992,16992,17568,17568, - 17568,18336,18336,18336,19080,19080,19080,19080,19848,19848,19848, - 20616,20616,20616,21384,21384,21384,21384,22152,22152,22152,22920, - 22920,22920,23688,23688,23688,23688,24496,24496,24496,24496,25456}, - { 224, 488, 744, 1000, 1256, 1544, 1800, 2024, 2280, 2536, 2856, - 3112, 3368, 3624, 3880, 4136, 4392, 4584, 4968, 5160, 5352, 5736, - 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504, - 8760, 9144, 9144, 9528, 9912, 9912,10296,10680,10680,11064,11448, - 11448,11832,12216,12216,12576,12960,12960,13536,13536,14112,14112, - 14688,14688,14688,15264,15264,15840,15840,16416,16416,16992,16992, - 16992,17568,17568,18336,18336,18336,19080,19080,19080,19848,19848, - 19848,20616,20616,20616,21384,21384,21384,22152,22152,22152,22920, - 22920,22920,23688,23688,23688,24496,24496,24496,25456,25456,25456, - 25456,26416,26416,26416,26416,27376,27376,27376,27376,28336,28336}, - { 256, 552, 840, 1128, 1416, 1736, 1992, 2280, 2600, 2856, 3112, - 3496, 3752, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 5992, 6200, - 6456, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9528, - 9912, 9912,10296,10680,11064,11064,11448,11832,12216,12216,12576, - 12960,12960,13536,13536,14112,14112,14688,14688,15264,15264,15840, - 15840,16416,16416,16992,16992,17568,17568,18336,18336,18336,19080, - 19080,19848,19848,19848,20616,20616,20616,21384,21384,22152,22152, - 22152,22920,22920,22920,23688,23688,24496,24496,24496,25456,25456, - 25456,25456,26416,26416,26416,27376,27376,27376,28336,28336,28336, - 28336,29296,29296,29296,29296,30576,30576,30576,30576,31704,31704}, - { 280, 600, 904, 1224, 1544, 1800, 2152, 2472, 2728, 3112, 3368, - 3624, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 6200, 6456, 6712, - 6968, 7224, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912,10296, - 10296,10680,11064,11448,11832,11832,12216,12576,12960,12960,13536, - 13536,14112,14688,14688,15264,15264,15840,15840,16416,16416,16992, - 16992,17568,17568,18336,18336,18336,19080,19080,19848,19848,20616, - 20616,20616,21384,21384,22152,22152,22152,22920,22920,23688,23688, - 23688,24496,24496,24496,25456,25456,25456,26416,26416,26416,27376, - 27376,27376,28336,28336,28336,29296,29296,29296,29296,30576,30576, - 30576,30576,31704,31704,31704,31704,32856,32856,32856,34008,34008}, - { 328, 632, 968, 1288, 1608, 1928, 2280, 2600, 2984, 3240, 3624, - 3880, 4264, 4584, 4968, 5160, 5544, 5992, 6200, 6456, 6712, 7224, - 7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 9912,10296,10680, - 11064,11448,11832,12216,12216,12576,12960,13536,13536,14112,14112, - 14688,14688,15264,15840,15840,16416,16416,16992,16992,17568,17568, - 18336,18336,19080,19080,19848,19848,19848,20616,20616,21384,21384, - 22152,22152,22152,22920,22920,23688,23688,24496,24496,24496,25456, - 25456,25456,26416,26416,26416,27376,27376,27376,28336,28336,28336, - 29296,29296,29296,30576,30576,30576,30576,31704,31704,31704,31704, - 32856,32856,32856,34008,34008,34008,34008,35160,35160,35160,35160}, - { 336, 696, 1064, 1416, 1800, 2152, 2536, 2856, 3240, 3624, 4008, - 4392, 4776, 5160, 5352, 5736, 6200, 6456, 6712, 7224, 7480, 7992, - 8248, 8760, 9144, 9528, 9912,10296,10296,10680,11064,11448,11832, - 12216,12576,12960,13536,13536,14112,14688,14688,15264,15264,15840, - 16416,16416,16992,17568,17568,18336,18336,19080,19080,19848,19848, - 20616,20616,20616,21384,21384,22152,22152,22920,22920,23688,23688, - 24496,24496,24496,25456,25456,26416,26416,26416,27376,27376,27376, - 28336,28336,29296,29296,29296,30576,30576,30576,30576,31704,31704, - 31704,32856,32856,32856,34008,34008,34008,35160,35160,35160,35160, - 36696,36696,36696,36696,37888,37888,37888,39232,39232,39232,39232}, - { 376, 776, 1160, 1544, 1992, 2344, 2792, 3112, 3624, 4008, 4392, - 4776, 5160, 5544, 5992, 6200, 6712, 7224, 7480, 7992, 8248, 8760, - 9144, 9528, 9912,10296,10680,11064,11448,11832,12216,12576,12960, - 13536,14112,14112,14688,15264,15264,15840,16416,16416,16992,17568, - 17568,18336,18336,19080,19080,19848,19848,20616,21384,21384,22152, - 22152,22920,22920,23688,23688,24496,24496,24496,25456,25456,26416, - 26416,27376,27376,27376,28336,28336,29296,29296,29296,30576,30576, - 30576,31704,31704,31704,32856,32856,32856,34008,34008,34008,35160, - 35160,35160,36696,36696,36696,37888,37888,37888,37888,39232,39232, - 39232,40576,40576,40576,40576,42368,42368,42368,42368,43816,43816}, - { 408, 840, 1288, 1736, 2152, 2600, 2984, 3496, 3880, 4264, 4776, - 5160, 5544, 5992, 6456, 6968, 7224, 7736, 8248, 8504, 9144, 9528, - 9912,10296,10680,11064,11448,12216,12576,12960,13536,13536,14112, - 14688,15264,15264,15840,16416,16992,16992,17568,18336,18336,19080, - 19080,19848,20616,20616,21384,21384,22152,22152,22920,22920,23688, - 24496,24496,25456,25456,25456,26416,26416,27376,27376,28336,28336, - 29296,29296,29296,30576,30576,30576,31704,31704,32856,32856,32856, - 34008,34008,34008,35160,35160,35160,36696,36696,36696,37888,37888, - 37888,39232,39232,39232,40576,40576,40576,40576,42368,42368,42368, - 43816,43816,43816,43816,45352,45352,45352,46888,46888,46888,46888}, - { 440, 904, 1384, 1864, 2344, 2792, 3240, 3752, 4136, 4584, 5160, - 5544, 5992, 6456, 6968, 7480, 7992, 8248, 8760, 9144, 9912,10296, - 10680,11064,11448,12216,12576,12960,13536,14112,14688,14688,15264, - 15840,16416,16992,16992,17568,18336,18336,19080,19848,19848,20616, - 20616,21384,22152,22152,22920,22920,23688,24496,24496,25456,25456, - 26416,26416,27376,27376,28336,28336,29296,29296,29296,30576,30576, - 31704,31704,31704,32856,32856,34008,34008,34008,35160,35160,35160, - 36696,36696,36696,37888,37888,39232,39232,39232,40576,40576,40576, - 42368,42368,42368,42368,43816,43816,43816,45352,45352,45352,46888, - 46888,46888,46888,48936,48936,48936,48936,48936,51024,51024,51024}, - { 488, 1000, 1480, 1992, 2472, 2984, 3496, 4008, 4584, 4968, 5544, - 5992, 6456, 6968, 7480, 7992, 8504, 9144, 9528, 9912,10680,11064, - 11448,12216,12576,12960,13536,14112,14688,15264,15840,15840,16416, - 16992,17568,18336,18336,19080,19848,19848,20616,21384,21384,22152, - 22920,22920,23688,24496,24496,25456,25456,26416,26416,27376,27376, - 28336,28336,29296,29296,30576,30576,31704,31704,31704,32856,32856, - 34008,34008,35160,35160,35160,36696,36696,36696,37888,37888,39232, - 39232,39232,40576,40576,40576,42368,42368,42368,43816,43816,43816, - 45352,45352,45352,46888,46888,46888,46888,48936,48936,48936,48936, - 51024,51024,51024,51024,52752,52752,52752,52752,55056,55056,55056}, - { 520, 1064, 1608, 2152, 2664, 3240, 3752, 4264, 4776, 5352, 5992, - 6456, 6968, 7480, 7992, 8504, 9144, 9528,10296,10680,11448,11832, - 12576,12960,13536,14112,14688,15264,15840,16416,16992,16992,17568, - 18336,19080,19080,19848,20616,21384,21384,22152,22920,22920,23688, - 24496,24496,25456,25456,26416,27376,27376,28336,28336,29296,29296, - 30576,30576,31704,31704,32856,32856,34008,34008,34008,35160,35160, - 36696,36696,36696,37888,37888,39232,39232,40576,40576,40576,42368, - 42368,42368,43816,43816,43816,45352,45352,45352,46888,46888,46888, - 48936,48936,48936,48936,51024,51024,51024,51024,52752,52752,52752, - 55056,55056,55056,55056,57336,57336,57336,57336,59256,59256,59256}, - { 552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200, - 6968, 7480, 7992, 8504, 9144, 9912,10296,11064,11448,12216,12576, - 12960,13536,14112,14688,15264,15840,16416,16992,17568,18336,19080, - 19848,19848,20616,21384,22152,22152,22920,23688,24496,24496,25456, - 25456,26416,27376,27376,28336,28336,29296,29296,30576,30576,31704, - 31704,32856,32856,34008,34008,35160,35160,36696,36696,37888,37888, - 37888,39232,39232,40576,40576,40576,42368,42368,43816,43816,43816, - 45352,45352,45352,46888,46888,46888,48936,48936,48936,51024,51024, - 51024,51024,52752,52752,52752,55056,55056,55056,55056,57336,57336, - 57336,57336,59256,59256,59256,59256,61664,61664,61664,61664,63776}, - { 584, 1192, 1800, 2408, 2984, 3624, 4264, 4968, 5544, 5992, 6712, - 7224, 7992, 8504, 9144, 9912,10296,11064,11448,12216,12960,13536, - 14112,14688,15264,15840,16416,16992,17568,18336,19080,19848,19848, - 20616,21384,22152,22920,22920,23688,24496,25456,25456,26416,26416, - 27376,28336,28336,29296,29296,30576,31704,31704,32856,32856,34008, - 34008,35160,35160,36696,36696,36696,37888,37888,39232,39232,40576, - 40576,42368,42368,42368,43816,43816,45352,45352,45352,46888,46888, - 46888,48936,48936,48936,51024,51024,51024,52752,52752,52752,52752, - 55056,55056,55056,57336,57336,57336,57336,59256,59256,59256,61664, - 61664,61664,61664,63776,63776,63776,63776,66592,66592,66592,66592}, - { 616, 1256, 1864, 2536, 3112, 3752, 4392, 5160, 5736, 6200, 6968, - 7480, 8248, 8760, 9528,10296,10680,11448,12216,12576,13536,14112, - 14688,15264,15840,16416,16992,17568,18336,19080,19848,20616,20616, - 21384,22152,22920,23688,24496,24496,25456,26416,26416,27376,28336, - 28336,29296,29296,30576,31704,31704,32856,32856,34008,34008,35160, - 35160,36696,36696,37888,37888,39232,39232,40576,40576,40576,42368, - 42368,43816,43816,43816,45352,45352,46888,46888,46888,48936,48936, - 48936,51024,51024,51024,52752,52752,52752,55056,55056,55056,55056, - 57336,57336,57336,59256,59256,59256,61664,61664,61664,61664,63776, - 63776,63776,63776,66592,66592,66592,66592,68808,68808,68808,71112}, - { 712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248, - 8760, 9528,10296,11064,11832,12576,13536,14112,14688,15264,16416, - 16992,17568,18336,19080,19848,20616,21384,22152,22920,23688,24496, - 25456,25456,26416,27376,28336,29296,29296,30576,30576,31704,32856, - 32856,34008,35160,35160,36696,36696,37888,37888,39232,40576,40576, - 40576,42368,42368,43816,43816,45352,45352,46888,46888,48936,48936, - 48936,51024,51024,52752,52752,52752,55056,55056,55056,55056,57336, - 57336,57336,59256,59256,59256,61664,61664,61664,63776,63776,63776, - 66592,66592,66592,68808,68808,68808,71112,71112,71112,73712,73712, - 75376,75376,75376,75376,75376,75376,75376,75376,75376,75376,75376}}; +/* Modulation and TBS index table for PUSCH from 3GPP TS 36.213 v10.3.0 table 8.6.1-1A */ +static const int ul_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26}; + +/* Transport Block Size from 3GPP TS 36.213 v12.13.0 table 7.1.7.2.1-1 */ +static const int tbs_table[34][110] = { + {16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, 328, 344, 376, 392, 424, 456, 488, 504, + 536, 568, 600, 616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904, 936, 968, 1000, 1032, 1032, + 1064, 1096, 1128, 1160, 1192, 1224, 1256, 1256, 1288, 1320, 1352, 1384, 1416, 1416, 1480, 1480, 1544, 1544, 1608, + 1608, 1608, 1672, 1672, 1736, 1736, 1800, 1800, 1800, 1864, 1864, 1928, 1928, 1992, 1992, 2024, 2088, 2088, 2088, + 2152, 2152, 2216, 2216, 2280, 2280, 2280, 2344, 2344, 2408, 2408, 2472, 2472, 2536, 2536, 2536, 2600, 2600, 2664, + 2664, 2728, 2728, 2728, 2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 2984, 2984, 3112}, + {24, 56, 88, 144, 176, 208, 224, 256, 328, 344, 376, 424, 456, 488, 520, 568, 600, 632, 680, + 712, 744, 776, 808, 872, 904, 936, 968, 1000, 1032, 1064, 1128, 1160, 1192, 1224, 1256, 1288, 1352, 1384, + 1416, 1416, 1480, 1544, 1544, 1608, 1608, 1672, 1736, 1736, 1800, 1800, 1864, 1864, 1928, 1992, 1992, 2024, 2088, + 2088, 2152, 2152, 2216, 2280, 2280, 2344, 2344, 2408, 2472, 2472, 2536, 2536, 2600, 2600, 2664, 2728, 2728, 2792, + 2792, 2856, 2856, 2856, 2984, 2984, 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3240, 3368, 3368, 3368, 3496, 3496, + 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008}, + {32, 72, 144, 176, 208, 256, 296, 328, 376, 424, 472, 520, 568, 616, 648, 696, 744, 776, 840, + 872, 936, 968, 1000, 1064, 1096, 1160, 1192, 1256, 1288, 1320, 1384, 1416, 1480, 1544, 1544, 1608, 1672, 1672, + 1736, 1800, 1800, 1864, 1928, 1992, 2024, 2088, 2088, 2152, 2216, 2216, 2280, 2344, 2344, 2408, 2472, 2536, 2536, + 2600, 2664, 2664, 2728, 2792, 2856, 2856, 2856, 2984, 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3368, + 3496, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008, 4136, 4136, 4136, 4264, 4264, + 4264, 4392, 4392, 4392, 4584, 4584, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968}, + {40, 104, 176, 208, 256, 328, 392, 440, 504, 568, 616, 680, 744, 808, 872, 904, 968, 1032, 1096, + 1160, 1224, 1256, 1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 1992, 2024, 2088, 2152, 2216, + 2280, 2344, 2408, 2472, 2536, 2536, 2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3368, + 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4392, + 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5352, 5352, 5544, 5544, + 5544, 5736, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6200, 6456, 6456}, + {56, 120, 208, 256, 328, 408, 488, 552, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1192, 1288, 1352, + 1416, 1480, 1544, 1608, 1736, 1800, 1864, 1928, 1992, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2600, 2664, 2728, + 2792, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008, 4008, 4136, + 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5544, + 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6456, 6456, 6712, 6712, 6712, + 6968, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992}, + {72, 144, 224, 328, 424, 504, 600, 680, 776, 872, 968, 1032, 1128, 1224, 1320, 1384, 1480, 1544, 1672, + 1736, 1864, 1928, 2024, 2088, 2216, 2280, 2344, 2472, 2536, 2664, 2728, 2792, 2856, 2984, 3112, 3112, 3240, 3368, + 3496, 3496, 3624, 3752, 3752, 3880, 4008, 4008, 4136, 4264, 4392, 4392, 4584, 4584, 4776, 4776, 4776, 4968, 4968, + 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6712, 6712, + 6712, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 7992, 8248, 8248, 8248, + 8504, 8504, 8760, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9528}, + {328, 176, 256, 392, 504, 600, 712, 808, 936, 1032, 1128, 1224, 1352, 1480, 1544, 1672, + 1736, 1864, 1992, 2088, 2216, 2280, 2408, 2472, 2600, 2728, 2792, 2984, 2984, 3112, 3240, 3368, + 3496, 3496, 3624, 3752, 3880, 4008, 4136, 4136, 4264, 4392, 4584, 4584, 4776, 4776, 4968, 4968, + 5160, 5160, 5352, 5352, 5544, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6456, 6456, 6456, 6712, + 6712, 6968, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 8248, 8248, 8248, + 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912, + 10296, 10296, 10296, 10296, 10680, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448}, + {104, 224, 328, 472, 584, 712, 840, 968, 1096, 1224, 1320, 1480, 1608, 1672, 1800, 1928, + 2088, 2216, 2344, 2472, 2536, 2664, 2792, 2984, 3112, 3240, 3368, 3368, 3496, 3624, 3752, 3880, + 4008, 4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352, 5544, 5736, 5736, 5992, + 5992, 6200, 6200, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, + 7992, 7992, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9528, 9912, + 9912, 9912, 10296, 10296, 10296, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448, 11448, 11832, + 11832, 11832, 12216, 12216, 12216, 12576, 12576, 12576, 12960, 12960, 12960, 12960, 13536, 13536}, + {120, 256, 392, 536, 680, 808, 968, 1096, 1256, 1384, 1544, 1672, 1800, 1928, 2088, 2216, + 2344, 2536, 2664, 2792, 2984, 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4264, 4392, 4584, + 4584, 4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, + 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, 8248, 8504, 8504, 8760, 8760, 9144, + 9144, 9144, 9528, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10680, 10680, 10680, 11064, 11064, 11064, + 11448, 11448, 11448, 11832, 11832, 12216, 12216, 12216, 12576, 12576, 12576, 12960, 12960, 12960, 13536, 13536, + 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15264}, + {136, 296, 456, 616, 776, 936, 1096, 1256, 1416, 1544, 1736, 1864, 2024, 2216, 2344, 2536, + 2664, 2856, 2984, 3112, 3368, 3496, 3624, 3752, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160, + 5160, 5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 6968, 7224, 7480, 7480, + 7736, 7992, 7992, 8248, 8248, 8504, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 10296, + 10296, 10296, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11832, 11832, 11832, 12216, 12216, 12576, 12576, + 12960, 12960, 12960, 13536, 13536, 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 15264, 15264, + 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16416, 16992, 16992, 16992, 16992, 17568}, + {144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928, 2088, 2280, 2472, 2664, 2792, + 2984, 3112, 3368, 3496, 3752, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, + 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8504, + 8504, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 10296, 10296, 10680, 10680, 11064, 11064, 11448, + 11448, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 12960, 13536, 13536, 13536, 14112, 14112, + 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16992, 16992, + 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080}, + {176, 376, 584, 776, 1000, 1192, 1384, 1608, 1800, 2024, 2216, 2408, 2600, 2792, 2984, 3240, + 3496, 3624, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5352, 5544, 5736, 5992, 5992, 6200, 6456, + 6712, 6968, 6968, 7224, 7480, 7736, 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9144, 9528, 9528, + 9912, 9912, 10296, 10680, 10680, 11064, 11064, 11448, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, + 12960, 13536, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 15840, 16416, + 16416, 16416, 16992, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080, + 19848, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 22152, 22152, 22152}, + {208, 440, 680, 904, 1128, 1352, 1608, 1800, 2024, 2280, 2472, 2728, 2984, 3240, 3368, 3624, + 3880, 4136, 4392, 4584, 4776, 4968, 5352, 5544, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224, + 7480, 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9528, 9528, 9912, 9912, 10296, 10680, 10680, 11064, + 11064, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14112, 14688, + 14688, 15264, 15264, 15264, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 17568, 17568, 17568, 18336, 18336, + 18336, 19080, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 22152, + 22152, 22152, 22920, 22920, 22920, 23688, 23688, 23688, 23688, 24496, 24496, 24496, 24496, 25456}, + {224, 488, 744, 1000, 1256, 1544, 1800, 2024, 2280, 2536, 2856, 3112, 3368, 3624, 3880, 4136, + 4392, 4584, 4968, 5160, 5352, 5736, 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248, + 8504, 8760, 9144, 9144, 9528, 9912, 9912, 10296, 10680, 10680, 11064, 11448, 11448, 11832, 12216, 12216, + 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, + 16992, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, + 20616, 21384, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 22920, 23688, 23688, 23688, 24496, 24496, 24496, + 25456, 25456, 25456, 25456, 26416, 26416, 26416, 26416, 27376, 27376, 27376, 27376, 28336, 28336}, + {256, 552, 840, 1128, 1416, 1736, 1992, 2280, 2600, 2856, 3112, 3496, 3752, 4008, 4264, 4584, + 4968, 5160, 5544, 5736, 5992, 6200, 6456, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, + 9528, 9912, 9912, 10296, 10680, 11064, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 12960, 13536, 13536, + 14112, 14112, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, + 18336, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920, + 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, + 28336, 28336, 28336, 28336, 29296, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704}, + {280, 600, 904, 1224, 1544, 1800, 2152, 2472, 2728, 3112, 3368, 3624, 4008, 4264, 4584, 4968, + 5160, 5544, 5736, 6200, 6456, 6712, 6968, 7224, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912, + 10296, 10296, 10680, 11064, 11448, 11832, 11832, 12216, 12576, 12960, 12960, 13536, 13536, 14112, 14688, 14688, + 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19848, + 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 23688, 23688, 23688, 24496, 24496, + 24496, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, + 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008}, + {328, 632, 968, 1288, 1608, 1928, 2280, 2600, 2984, 3240, 3624, 3880, 4264, 4584, 4968, 5160, + 5544, 5992, 6200, 6456, 6712, 7224, 7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 9912, 10296, + 10680, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 15264, 15840, + 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 19848, 20616, 20616, + 21384, 21384, 22152, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 26416, + 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, + 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 34008, 35160, 35160, 35160, 35160}, + {336, 696, 1064, 1416, 1800, 2152, 2536, 2856, 3240, 3624, 4008, 4392, 4776, 5160, 5352, 5736, + 6200, 6456, 6712, 7224, 7480, 7992, 8248, 8760, 9144, 9528, 9912, 10296, 10296, 10680, 11064, 11448, + 11832, 12216, 12576, 12960, 13536, 13536, 14112, 14688, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 17568, + 17568, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22920, 22920, + 23688, 23688, 24496, 24496, 24496, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 29296, + 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, + 35160, 35160, 35160, 36696, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 39232}, + {376, 776, 1160, 1544, 1992, 2344, 2792, 3112, 3624, 4008, 4392, 4776, 5160, 5544, 5992, 6200, + 6712, 7224, 7480, 7992, 8248, 8760, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 11832, 12216, 12576, + 12960, 13536, 14112, 14112, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 17568, 17568, 18336, 18336, 19080, + 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, + 25456, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704, + 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, + 37888, 39232, 39232, 39232, 40576, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816}, + {408, 840, 1288, 1736, 2152, 2600, 2984, 3496, 3880, 4264, 4776, 5160, 5544, 5992, 6456, 6968, + 7224, 7736, 8248, 8504, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 13536, + 14112, 14688, 15264, 15264, 15840, 16416, 16992, 16992, 17568, 18336, 18336, 19080, 19080, 19848, 20616, 20616, + 21384, 21384, 22152, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 25456, 26416, 26416, 27376, 27376, + 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, + 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 40576, + 42368, 42368, 42368, 43816, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888}, + {440, 904, 1384, 1864, 2344, 2792, 3240, 3752, 4136, 4584, 5160, 5544, 5992, 6456, 6968, 7480, + 7992, 8248, 8760, 9144, 9912, 10296, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 14688, + 15264, 15840, 16416, 16992, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 20616, 21384, 22152, 22152, + 22920, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 29296, + 30576, 30576, 31704, 31704, 31704, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, + 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816, 43816, 45352, + 45352, 45352, 46888, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 48936, 51024, 51024, 51024}, + {488, 1000, 1480, 1992, 2472, 2984, 3496, 4008, 4584, 4968, 5544, 5992, 6456, 6968, 7480, 7992, + 8504, 9144, 9528, 9912, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 15840, + 16416, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496, + 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 31704, + 32856, 32856, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 39232, 40576, + 40576, 40576, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888, 48936, + 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056}, + {520, 1064, 1608, 2152, 2664, 3240, 3752, 4264, 4776, 5352, 5992, 6456, 6968, 7480, 7992, 8504, + 9144, 9528, 10296, 10680, 11448, 11832, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 16992, + 17568, 18336, 19080, 19080, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, + 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 34008, + 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 43816, + 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 51024, 51024, 51024, 51024, + 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256}, + {552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200, 6968, 7480, 7992, 8504, 9144, + 9912, 10296, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, + 19080, 19848, 19848, 20616, 21384, 22152, 22152, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 27376, 27376, + 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, + 37888, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, + 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, + 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776}, + {584, 1192, 1800, 2408, 2984, 3624, 4264, 4968, 5544, 5992, 6712, 7224, 7992, 8504, 9144, 9912, + 10296, 11064, 11448, 12216, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, + 19848, 20616, 21384, 22152, 22920, 22920, 23688, 24496, 25456, 25456, 26416, 26416, 27376, 28336, 28336, 29296, + 29296, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, + 39232, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, + 48936, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, + 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592}, + {616, 1256, 1864, 2536, 3112, 3752, 4392, 5160, 5736, 6200, 6968, 7480, 8248, 8760, 9528, 10296, + 10680, 11448, 12216, 12576, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, + 20616, 21384, 22152, 22920, 23688, 24496, 24496, 25456, 26416, 26416, 27376, 28336, 28336, 29296, 29296, 30576, + 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, + 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, + 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, + 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 68808, 71112}, + {712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248, 8760, 9528, 10296, 11064, 11832, + 12576, 13536, 14112, 14688, 15264, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, + 24496, 25456, 25456, 26416, 27376, 28336, 29296, 29296, 30576, 30576, 31704, 32856, 32856, 34008, 35160, 35160, + 36696, 36696, 37888, 37888, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888, + 48936, 48936, 48936, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 59256, + 59256, 59256, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, + 71112, 73712, 73712, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376}, + {648, 1320, 1992, 2664, 3368, 4008, 4584, 5352, 5992, 6712, 7224, 7992, 8504, 9144, 9912, + 10680, 11448, 11832, 12576, 12960, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, + 20616, 21384, 22152, 22920, 22920, 23688, 24496, 25456, 25456, 26416, 27376, 27376, 28336, 29296, 29296, + 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 36696, 37888, 39232, 39232, 40576, 40576, 42368, + 42368, 43816, 43816, 43816, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 52752, + 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664, + 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 71112, 71112, 71112, 71112, 73712}, + {680, 1384, 2088, 2792, 3496, 4264, 4968, 5544, 6200, 6968, 7736, 8504, 9144, 9912, 10680, 11064, + 11832, 12576, 13536, 14112, 14688, 15264, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22152, + 22920, 23668, 24496, 25456, 26416, 26416, 27376, 28336, 29296, 29296, 30576, 31704, 32856, 34008, 34008, 35160, + 35160, 36696, 36696, 37888, 39232, 29232, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 45352, 45352, 46888, + 46888, 46888, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, + 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, + 68808, 71112, 71112, 71112, 73712, 73712, 75376, 75376, 76208, 76208}, + {712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248, 4760, 9528, 10296, 11064, 11832, + 12576, 13536, 14112, 14668, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 61384, 22152, 22920, 23688, + 24496, 25456, 26416, 26416, 27376, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 34008, 34008, 35160, 35160, + 36696, 36696, 37888, 39232, 39232, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 45352, 46888, 46888, + 48936, 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, + 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, + 71112, 73712, 73712, 73712, 75376, 76208, 76208, 76208, 78704, 78704, 78704, 81176, 81176, 81176}, + {776, 1544, 2344, 3112, 3880, 4776, 5544, 3200, 3938, 7736, 8504, 9528, 10296, 11064, 11832, 12576, + 13536, 14112, 14688, 15840, 16416, 16992, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, + 25456, 26416, 27276, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 34008, 34008, 35160, 36696, 36696, 37888, + 37888, 39232, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 51024, + 51024, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776, 63776, + 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 75376, 75376, 76208, + 76208, 78704, 78704, 78704, 81176, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936}, + {808, 1608, 2472, 3240, 4136, 4968, 5736, 6456, 7480, 8248, 9144, 9912, 10680, 11148, 12216, 12960, + 14112, 14688, 15840, 16416, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, + 27376, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 34008, 35160, 35160, 36696, 36696, 37888, 39232, 39232, + 40576, 40576, 42368, 42368, 43816, 45352, 45352, 46888, 46888, 46888, 48396, 48396, 51024, 51024, 52752, 52752, + 52752, 55056, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776, 63776, 63776, 66592, 66592, + 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73715, 73712, 75376, 76208, 76208, 78704, 78704, 78704, + 81176, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936, 87936, 87936, 87936, 90816, 90816}, + {840, 1672, 2536, 3368, 4264, 5160, 5992, 6712, 7736, 8504, 9528, 10296, 11064, 11832, 12960, 13536, + 14688, 15264, 16416, 16992, 17458, 19080, 19848, 20616, 21348, 22152, 22920, 23688, 24496, 25456, 26416, 27376, + 28336, 29296, 29296, 30576, 31704, 32856, 32856, 34008, 35160, 35160, 36696, 37888, 37888, 39232, 39232, 40576, + 40576, 42368, 42368, 43816, 43816, 45352, 46888, 46888, 46888, 48936, 48936, 51024, 51024, 52752, 52752, 52752, + 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, + 66592, 68808, 68808, 71112, 71112, 71112, 71112, 73712, 73712, 73712, 75376, 76208, 76208, 78704, 78704, 78704, + 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 93800, 93800}, + {968, 1992, 2984, 4008, 4968, 5992, 6968, 7992, 8760, 9912, 10680, 11832, 12960, 13536, 14688, 15840, + 16992, 17568, 19080, 19848, 20616, 21384, 22920, 23688, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704, + 32856, 34008, 35160, 35160, 36696, 37888, 39232, 39232, 40576, 40576, 42368, 43816, 43816, 45352, 46888, 46888, + 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776, + 63776, 63776, 66592, 66592, 68808, 68808, 71112, 71112, 71112, 73712, 75376, 76208, 73208, 76208, 78704, 78704, + 81176, 81176, 81176, 81176, 84760, 84760, 84760, 87636, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, + 93800, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896, 97896}}; diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 2730b6049..a2391c6d9 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -123,6 +123,14 @@ add_test(pdsch_test_cdd_50 pdsch_test -x 3 -a 2 -t 0 -n 50) add_test(pdsch_test_cdd_75 pdsch_test -x 3 -a 2 -t 0 -n 75) add_test(pdsch_test_cdd_100 pdsch_test -x 3 -a 2 -t 0 -n 100) +# PDSCH test for CDD transmision mode (2 codeword) and 256QAM +add_test(pdsch_test_cdd_6 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 6 -q) +add_test(pdsch_test_cdd_12 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 12 -q) +add_test(pdsch_test_cdd_25 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 25 -q) +add_test(pdsch_test_cdd_50 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 50 -q) +add_test(pdsch_test_cdd_75 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 75 -q) +add_test(pdsch_test_cdd_100 pdsch_test -x 3 -a 2 -t 0 -m 27 -M 27 -n 100 -q) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword) add_test(pdsch_test_multiplex1cw_p0_6 pdsch_test -x 4 -a 2 -p 0 -n 6) add_test(pdsch_test_multiplex1cw_p0_12 pdsch_test -x 4 -a 2 -p 0 -n 12) diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index 663c930d1..fa78461cb 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -53,7 +53,7 @@ static bool enable_coworker = false; static uint32_t pmi = 0; static char* input_file = NULL; static int M = 1; - +static bool enable_256qam = false; static bool use_8_bit = false; void usage(char *prog) { @@ -76,11 +76,12 @@ void usage(char *prog) { printf("\t-w Swap Transport Blocks\n"); printf("\t-j Enable PDSCH decoder coworker\n"); printf("\t-v [set srslte_verbose to debug, default none]\n"); + printf("\t-q Enable/Disable 256QAM modulation (default %s)\n", enable_256qam ? "enabled" : "disabled"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "fmMcsbrtRFpnawvXxj")) != -1) { + while ((opt = getopt(argc, argv, "fmMcsbrtRFpnqawvXxj")) != -1) { switch(opt) { case 'f': input_file = argv[optind]; @@ -136,6 +137,9 @@ void parse_args(int argc, char **argv) { case 'v': srslte_verbose++; break; + case 'q': + enable_256qam ^= true; + break; default: usage(argv[0]); exit(-1); @@ -143,6 +147,41 @@ void parse_args(int argc, char **argv) { } } +static int check_softbits( + srslte_pdsch_t* pdsch_enb, srslte_pdsch_t* pdsch_ue, srslte_pdsch_cfg_t* pdsch_cfg, uint32_t sf_idx, int tb) +{ + int ret = SRSLTE_SUCCESS; + + // Generate sequence + srslte_sequence_pdsch(&pdsch_ue->tmp_seq, + rnti, + pdsch_cfg->grant.tb[tb].cw_idx, + 2 * (sf_idx % 10), + cell.id, + pdsch_cfg->grant.tb[tb].nof_bits); + + // Scramble + if (pdsch_ue->llr_is_8bit) { + srslte_scrambling_sb_offset(&pdsch_ue->tmp_seq, pdsch_ue->e[tb], 0, pdsch_cfg->grant.tb[tb].nof_bits); + } else { + srslte_scrambling_s_offset(&pdsch_ue->tmp_seq, pdsch_ue->e[tb], 0, pdsch_cfg->grant.tb[tb].nof_bits); + } + int16_t* rx = pdsch_ue->e[tb]; + uint8_t* rx_bytes = pdsch_ue->e[tb]; + for (int i = 0, k = 0; i < pdsch_cfg->grant.tb[tb].nof_bits / 8; i++) { + uint8_t w = 0; + for (int j = 0; j < 8; j++, k++) { + w |= (rx[k] > 0) ? (1 << (7 - j)) : 0; + } + rx_bytes[i] = w; + } + if (memcmp(pdsch_ue->e[tb], pdsch_enb->e[tb], pdsch_cfg->grant.tb[tb].nof_bits / 8) != 0) { + ret = SRSLTE_ERROR; + } + + return ret; +} + int main(int argc, char **argv) { int ret = -1; struct timeval t[3] = {}; @@ -235,7 +274,7 @@ int main(int argc, char **argv) { pdsch_cfg.p_b = (tm > SRSLTE_TM1) ? 1 : 0; // 0 dB /* Generate dci from DCI */ - if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, tm, &dci, &pdsch_cfg.grant)) { + if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, tm, enable_256qam, &dci, &pdsch_cfg.grant)) { ERROR("Error computing resource allocation\n"); return ret; } @@ -470,17 +509,24 @@ int main(int argc, char **argv) { /* Check Tx and Rx bytes */ for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (pdsch_cfg.grant.tb[tb].enabled) { - for (int byte = 0; byte < pdsch_cfg.grant.tb[tb].tbs / 8; byte++) { - if (data_tx[tb][byte] != data_rx[tb][byte]) { - ERROR("Found BYTE (%d) error in TB %d (%02X != %02X), quiting...", - byte, - tb, - data_tx[tb][byte], - data_rx[tb][byte]); - // printf("Tx: "); srslte_vec_fprint_byte(stdout, data_tx[tb], dci.mcs[tb].tbs / 8); - // printf("Rx: "); srslte_vec_fprint_byte(stdout, data_rx[tb], dci.mcs[tb].tbs / 8); - ret = SRSLTE_ERROR; - goto quit; + if (check_softbits(&pdsch_tx, &pdsch_rx, &pdsch_cfg, subframe, tb)) { + printf("TB%d: The received softbits in subframe %d DO NOT match the encoded bits (crc=%d)\n", + tb, + subframe, + pdsch_res[tb].crc); + srslte_vec_fprint_byte(stdout, (uint8_t*)pdsch_tx.e[tb], pdsch_cfg.grant.tb[tb].nof_bits / 8); + srslte_vec_fprint_byte(stdout, (uint8_t*)pdsch_rx.e[tb], pdsch_cfg.grant.tb[tb].nof_bits / 8); + } else { + for (int byte = 0; byte < pdsch_cfg.grant.tb[tb].tbs / 8; byte++) { + if (data_tx[tb][byte] != data_rx[tb][byte]) { + ERROR("Found BYTE (%d) error in TB %d (%02X != %02X), quitting...", + byte, + tb, + data_tx[tb][byte], + data_rx[tb][byte]); + ret = SRSLTE_ERROR; + goto quit; + } } } } diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index fe171a248..10cc77485 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -651,7 +651,7 @@ int srslte_ue_dl_dci_to_pdsch_grant(srslte_ue_dl_t* q, srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) { - return srslte_ra_dl_dci_to_grant(&q->cell, sf, cfg->cfg.tm, dci, grant); + return srslte_ra_dl_dci_to_grant(&q->cell, sf, cfg->cfg.tm, cfg->pdsch_use_tbs_index_alt, dci, grant); } int srslte_ue_dl_decode_pdsch(srslte_ue_dl_t* q, diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index cbe1f5e14..d8ee97f87 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -780,7 +780,7 @@ int sf_worker::encode_pdsch(stack_interface_phy_lte::dl_sched_grant_t* grants, u // Compute DL grant if (srslte_ra_dl_dci_to_grant( - &phy->cell, &dl_sf, ue_db[rnti]->dl_cfg.tm, &grants[i].dci, &ue_db[rnti]->dl_cfg.pdsch.grant)) { + &phy->cell, &dl_sf, ue_db[rnti]->dl_cfg.tm, false, &grants[i].dci, &ue_db[rnti]->dl_cfg.pdsch.grant)) { Error("Computing DL grant\n"); } diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index dac91ee88..ebd03b3f4 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -692,8 +692,8 @@ int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res) srslte_ra_tb_t mcs_data; mcs.mcs_idx = this->sib13.mbsfn_area_info_list_r9[0].mcch_cfg_r9.sig_mcs_r9; mcs_data.mcs_idx = this->mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.data_mcs_r9; - srslte_dl_fill_ra_mcs(&mcs, 0, this->cell_config.cell.nof_prb); - srslte_dl_fill_ra_mcs(&mcs_data, 0, this->cell_config.cell.nof_prb); + srslte_dl_fill_ra_mcs(&mcs, 0, this->cell_config.cell.nof_prb, false); + srslte_dl_fill_ra_mcs(&mcs_data, 0, this->cell_config.cell.nof_prb, false); if (is_mcch) { build_mch_sched(mcs_data.tbs);