diff --git a/bench/Polar/rate_matching/bench.py b/bench/Polar/rate_matching/bench.py index 1ddc8ad3f1d51e321faa13e211a5cea5b7a3fdc7..8286ded69fe297054cccd116b5252a67597b81dc 100755 --- a/bench/Polar/rate_matching/bench.py +++ b/bench/Polar/rate_matching/bench.py @@ -39,13 +39,20 @@ items = [ ] reps = 600000 + for n, e, k in items: - name = "polar_rate_matching_n{}_e{}_k{}".format(n, e, k) - case = { - "name": name, - "args": "{} {} {}".format(n, e, k), - "reps": reps - } - j["cases"].append(case) + cases = [ + { + "name": "polar_rate_matching_n{}_e{}_k{}_i_bil0".format(n, e, k), + "args": "{} {} {} 0".format(n, e, k), + "reps": reps + }, + { + "name": "polar_rate_matching_n{}_e{}_k{}_i_bil1".format(n, e, k), + "args": "{} {} {} 1".format(n, e, k), + "reps": reps + } + ] + j["cases"].extend(cases) print(json.dumps(j)) diff --git a/bench/Polar/rate_matching/main.cpp b/bench/Polar/rate_matching/main.cpp index 29f951a1d2fd15da1c900727e19b33e5e2bea745..60f340fca75e83d91dc2cf5362a14c5fd888fb78 100644 --- a/bench/Polar/rate_matching/main.cpp +++ b/bench/Polar/rate_matching/main.cpp @@ -10,7 +10,9 @@ #include #include -static void run_polar_rate_matching_perf(int n, int e, int k, int num_reps) { +static void run_polar_rate_matching_perf(int n, int e, int k, + armral_polar_ibil_type i_bil, + int num_reps) { assert(n % 32 == 0); std::vector encoded_bits((n + 7) / 8); std::vector matched_bits((e + 7) / 8); @@ -21,28 +23,31 @@ static void run_polar_rate_matching_perf(int n, int e, int k, int num_reps) { #ifdef ARMRAL_BENCH_NOALLOC std::vector buffer((n + e + 7) / 8); for (int i = 0; i < num_reps; ++i) { - armral_polar_rate_matching_noalloc(n, e, k, encoded_bits_ptr, + armral_polar_rate_matching_noalloc(n, e, k, i_bil, encoded_bits_ptr, matched_bits_ptr, buffer.data()); } #else for (int i = 0; i < num_reps; ++i) { - armral_polar_rate_matching(n, e, k, encoded_bits_ptr, matched_bits_ptr); + armral_polar_rate_matching(n, e, k, i_bil, encoded_bits_ptr, + matched_bits_ptr); } #endif } int main(int argc, char **argv) { - if (argc != 5) { + if (argc != 6) { // n = number of bits in code // e = number of transmitted bits // k = the number of information bits to output, ignored for encoding. - fprintf(stderr, "usage: %s n e k nreps\n", argv[0]); + // i_bil = flag to enable/disable the interleaving of coded bits + fprintf(stderr, "usage: %s n e k i_bil nreps\n", argv[0]); exit(EXIT_FAILURE); } int n = atoi(argv[1]); int e = atoi(argv[2]); int k = atoi(argv[3]); - int num_reps = atoi(argv[4]); + armral_polar_ibil_type i_bil = armral_polar_ibil_type(atoi(argv[4])); + int num_reps = atoi(argv[5]); - run_polar_rate_matching_perf(n, e, k, num_reps); + run_polar_rate_matching_perf(n, e, k, i_bil, num_reps); } diff --git a/bench/Polar/rate_recovery/bench.py b/bench/Polar/rate_recovery/bench.py index 4865969c938aa84845f4a569f4114a21e3bbb020..1427393c650826d5ea045e69eb29af3e4d9c5468 100755 --- a/bench/Polar/rate_recovery/bench.py +++ b/bench/Polar/rate_recovery/bench.py @@ -40,12 +40,17 @@ items = [ reps = 600000 for n, e, k in items: - name = "polar_rate_recovery_n{}_e{}_k{}".format(n, e, k) - case = { - "name": name, - "args": "{} {} {}".format(n, e, k), - "reps": reps - } - j["cases"].append(case) - + cases = [ + { + "name": "polar_rate_recovery_n{}_e{}_k{}_i_bil0".format(n, e, k), + "args": "{} {} {} 0".format(n, e, k), + "reps": reps + }, + { + "name": "polar_rate_recovery_n{}_e{}_k{}_i_bil1".format(n, e, k), + "args": "{} {} {} 1".format(n, e, k), + "reps": reps + } + ] + j["cases"].extend(cases) print(json.dumps(j)) diff --git a/bench/Polar/rate_recovery/main.cpp b/bench/Polar/rate_recovery/main.cpp index 19ce77c931c0999040c28be78004fb0edcb0dcea..afd01b71e1f569298ed406b1a0f6a28339c23489 100644 --- a/bench/Polar/rate_recovery/main.cpp +++ b/bench/Polar/rate_recovery/main.cpp @@ -10,7 +10,9 @@ #include #include -static void run_polar_rate_recovery_perf(int n, int e, int k, int num_reps) { +static void run_polar_rate_recovery_perf(int n, int e, int k, + armral_polar_ibil_type i_bil, + int num_reps) { assert(n % 32 == 0); std::vector llrs(e); std::vector recovered_llrs(n); @@ -21,28 +23,30 @@ static void run_polar_rate_recovery_perf(int n, int e, int k, int num_reps) { #ifdef ARMRAL_BENCH_NOALLOC std::vector buffer(n + e); for (int i = 0; i < num_reps; ++i) { - armral_polar_rate_recovery_noalloc(n, e, k, llrs_ptr, recovered_llrs_ptr, - buffer.data()); + armral_polar_rate_recovery_noalloc(n, e, k, i_bil, llrs_ptr, + recovered_llrs_ptr, buffer.data()); } #else for (int i = 0; i < num_reps; ++i) { - armral_polar_rate_recovery(n, e, k, llrs_ptr, recovered_llrs_ptr); + armral_polar_rate_recovery(n, e, k, i_bil, llrs_ptr, recovered_llrs_ptr); } #endif } int main(int argc, char **argv) { - if (argc != 5) { + if (argc != 6) { // n = number of bits in code/number of llrs to recover // e = number of transmitted bits/number of input beliefs (LLRs) // k = the number of information bits to output, ignored for encoding. - fprintf(stderr, "usage: %s n e k nreps\n", argv[0]); + // i_bil = flag to enable/disable the interleaving of coded bits + fprintf(stderr, "usage: %s n e k i_bil nreps\n", argv[0]); exit(EXIT_FAILURE); } int n = atoi(argv[1]); int e = atoi(argv[2]); int k = atoi(argv[3]); - int num_reps = atoi(argv[4]); + armral_polar_ibil_type i_bil = armral_polar_ibil_type(atoi(argv[4])); + int num_reps = atoi(argv[5]); - run_polar_rate_recovery_perf(n, e, k, num_reps); + run_polar_rate_recovery_perf(n, e, k, i_bil, num_reps); } diff --git a/include/armral.h b/include/armral.h index 975fd85e7ee491ef799173e749f2493fc07c6e12..d26fa88eb206aaa0ba9c9cc77817cc9df6237afc 100644 --- a/include/armral.h +++ b/include/armral.h @@ -172,6 +172,14 @@ typedef enum { ARMRAL_POLAR_FROZEN_BIT = 255 ///< Frozen bit (set to zero). } armral_polar_frozen_bit_type; +/** + * Enable or disable the interleaving of coded bits in Polar rate matching. + */ +typedef enum { + ARMRAL_POLAR_IBIL_DISABLE = 0, ///< Downlink direction + ARMRAL_POLAR_IBIL_ENABLE = 1, ///< Uplink direction +} armral_polar_ibil_type; + /** * \brief 16-bit signed integer complex data type. */ @@ -2773,9 +2781,9 @@ armral_status armral_polar_decode_block(uint32_t n, const uint8_t *frozen, /** * Matches the rate of the Polar encoded code block to the rate of the channel - * using sub-block interleaving, bit selection, and channel interleaving. This - * is as described in the 3GPP Technical Specification (TS) 38.212 section - * 5.4.1. + * using sub-block interleaving, bit selection, and channel interleaving based on + * Downlink or Uplink direction. This is as described in the 3GPP Technical + * Specification (TS) 38.212 section 5.4.1. * * The code rate of the code block is defined by the ratio of the rate-matched * length `e` to the number of information bits in the message `k`. It is @@ -2786,6 +2794,7 @@ armral_status armral_polar_decode_block(uint32_t n, const uint8_t *frozen, * @param[in] n The number of bits in the code block. * @param[in] e The number of bits in the rate-matched message. * @param[in] k The number of information bits in the code block. + * @param[in] i_bil Flag to enable/disable the interleaving of coded bits. * @param[in] p_d_seq_in Points to `n` bits representing the Polar encoded * message. * @param[out] p_f_seq_out Points to `e` bits representing the rate-matched @@ -2793,6 +2802,7 @@ armral_status armral_polar_decode_block(uint32_t n, const uint8_t *frozen, * @return An `armral_status` value that indicates success or failure. */ armral_status armral_polar_rate_matching(uint32_t n, uint32_t e, uint32_t k, + armral_polar_ibil_type i_bil, const uint8_t *p_d_seq_in, uint8_t *p_f_seq_out); @@ -2813,11 +2823,15 @@ armral_status armral_polar_rate_matching(uint32_t n, uint32_t e, uint32_t k, * This function takes a pre-allocated buffer (`buffer`) to use internally. * This variant will not call any system memory allocators. * - * The buffer must be at least `((n + e + 7) / 8) * sizeof(uint8_t)` bytes. + * When `i_bil = ARMRAL_POLAR_IBIL_DISABLE` + * the buffer must be at least `((n + 7) / 8) * sizeof(uint8_t)` bytes. + * When `i_bil = ARMRAL_POLAR_IBIL_ENABLE` + * the buffer must be at least `((n + e + 7) / 8) * sizeof(uint8_t)` bytes. * * @param[in] n The number of bits in the code block. * @param[in] e The number of bits in the rate-matched message. * @param[in] k The number of information bits in the code block. + * @param[in] i_bil Flag to enable/disable the interleaving of coded bits. * @param[in] p_d_seq_in Points to `n` bits representing the Polar encoded * message. * @param[out] p_f_seq_out Points to `e` bits representing the rate-matched @@ -2825,11 +2839,9 @@ armral_status armral_polar_rate_matching(uint32_t n, uint32_t e, uint32_t k, * @param[in] buffer Workspace buffer to be used internally. * @return An `armral_status` value that indicates success or failure. */ -armral_status armral_polar_rate_matching_noalloc(uint32_t n, uint32_t e, - uint32_t k, - const uint8_t *p_d_seq_in, - uint8_t *p_f_seq_out, - void *buffer); +armral_status armral_polar_rate_matching_noalloc( + uint32_t n, uint32_t e, uint32_t k, armral_polar_ibil_type i_bil, + const uint8_t *p_d_seq_in, uint8_t *p_f_seq_out, void *buffer); /** * Recovers the log-likelihood ratios (LLRs) from demodulation to match the @@ -2854,6 +2866,8 @@ armral_status armral_polar_rate_matching_noalloc(uint32_t n, uint32_t e, * recover. The ratio of `e/k` is the rate of the * transmitted code block. `e` is assumed to be strictly * greater than `k`. + * @param[in] i_bil Flag to enable/disable the de-interleaving of coded + * bits. * @param[in] p_llr_in Points to `e` 8-bit LLRs, which are assumed to be the * output of demodulation. * @param[out] p_llr_out Points to `n` 8-bit rate-recovered LLRs. This output @@ -2861,6 +2875,7 @@ armral_status armral_polar_rate_matching_noalloc(uint32_t n, uint32_t e, * @return An `armral_status` value that indicates success or failure. */ armral_status armral_polar_rate_recovery(uint32_t n, uint32_t e, uint32_t k, + armral_polar_ibil_type i_bil, const int8_t *p_llr_in, int8_t *p_llr_out); @@ -2893,6 +2908,8 @@ armral_status armral_polar_rate_recovery(uint32_t n, uint32_t e, uint32_t k, * recover. The ratio of `e/k` is the rate of the * transmitted code block. `e` is assumed to be strictly * greater than `k`. + * @param[in] i_bil Flag to enable/disable the de-interleaving of coded + * bits. * @param[in] p_llr_in Points to `e` 8-bit LLRs, which are assumed to be the * output of demodulation. * @param[out] p_llr_out Points to `n` 8-bit rate-recovered LLRs. This output @@ -2900,11 +2917,9 @@ armral_status armral_polar_rate_recovery(uint32_t n, uint32_t e, uint32_t k, * @param[in] buffer Workspace buffer to be used internally. * @return An `armral_status` value that indicates success or failure. */ -armral_status armral_polar_rate_recovery_noalloc(uint32_t n, uint32_t e, - uint32_t k, - const int8_t *p_llr_in, - int8_t *p_llr_out, - void *buffer); +armral_status armral_polar_rate_recovery_noalloc( + uint32_t n, uint32_t e, uint32_t k, armral_polar_ibil_type i_bil, + const int8_t *p_llr_in, int8_t *p_llr_out, void *buffer); /** * Performs the Cyclic Redundancy Check (CRC) attachment described in diff --git a/simulation/README.md b/simulation/README.md index bd8dec63a6cce0990d9f3c0034a3a58ab5a7dd79..90432aa2f8e1d4aaa6a9d1a979a2e961e6476234 100644 --- a/simulation/README.md +++ b/simulation/README.md @@ -200,7 +200,7 @@ You can run the `polar` coding Additive White Gaussian Noise (AWGN) simulation with the following parameters: polar_awgn -k num_info_bits -e num_trans_bits - -m mod_type [-u demod_ulp] [-l list_size] + -m mod_type -i i_bil [-u demod_ulp] [-l list_size] For each value of the `Eb / N0` ratio used, a JSON record is written to stdout. The JSON record contains the following fields: @@ -211,6 +211,7 @@ The JSON record contains the following fields: "k": , "l": , "mod_type": , + "i_bil": "ulp": , "Eb/N0": , "snr": , diff --git a/simulation/polar_awgn/polar_awgn.cpp b/simulation/polar_awgn/polar_awgn.cpp index 044e137c5db5c4c491ebd2be348178285a60611b..2ad955cea0b8f1d30db33dd43c3b8007de75177d 100644 --- a/simulation/polar_awgn/polar_awgn.cpp +++ b/simulation/polar_awgn/polar_awgn.cpp @@ -46,7 +46,7 @@ std::string print_valid_l() { void usage(const char *exe_name) { std::cout << "Usage: " << exe_name << " -k num_info_bits -e num_trans_bits\n" - << " -m mod_type [-u demod_ulp] [-l list_size]\n\n" + << " -m mod_type -i i_bil [-u demod_ulp] [-l list_size]\n\n" << "The arguments required by " << exe_name << " are:\n\n" << " Number of information bits in the encoded\n" << " message.\n" @@ -57,6 +57,9 @@ void usage(const char *exe_name) { << " than or equal to .\n" << " Type of modulation. Supported values are:\n" << armral_simulation::print_valid_mod_type(3) + << " Flag to enable/disable the interleaving of \n" + << " coded bits in Polar rate matching.\n" + << " Type 0 : Downlink, Type 1 : Uplink.\n" << " Scaling parameter used in demodulation when\n" << " using fixed-point Q2.13 representation for\n" << " the symbols. is an integer\n" @@ -91,6 +94,8 @@ struct polar_example_data { uint32_t k; // The list decode length (1, 2 or 4) uint32_t l; + // Polar rate matching/rate recovery ibil type + armral_polar_ibil_type i_bil; // Type of modulation armral_modulation_type mod_type; // Demodulation scaling factor @@ -114,6 +119,7 @@ struct polar_example_data { uint8_t *data_decoded_bytes; polar_example_data(uint32_t n_in, uint32_t e_in, uint32_t k_in, uint32_t l_in, + armral_polar_ibil_type i_bil_in, armral_modulation_type mod, uint16_t demod_ulp_in) { assert(k_in <= e_in); assert(l_in == 1 || l_in == 2 || l_in == 4); @@ -121,6 +127,7 @@ struct polar_example_data { e = e_in; k = k_in; l = l_in; + i_bil = i_bil_in; mod_type = mod; demod_ulp = demod_ulp_in; bits_per_mod_symbol = armral_simulation::bits_per_symbol(mod_type); @@ -201,8 +208,9 @@ int run_check(random_state *state, double snr_db, polar_example_data *data) { // Rate match data_encoded to create an array of length e bits from n // bits - armral_polar_rate_matching(data->n, data->e, data->k, data->data_encoded, - data->data_matched); + + armral_polar_rate_matching(data->n, data->e, data->k, data->i_bil, + data->data_encoded, data->data_matched); // Simulate a noisy channel. This involves modulating data, adding noise to // the modulated symbols, and then demodulating @@ -217,8 +225,8 @@ int run_check(random_state *state, double snr_db, polar_example_data *data) { data->data_mod, data->data_demod_soft); // Rate recovery to get N LLRs from E LLRs - armral_polar_rate_recovery(data->n, data->e, data->k, data->data_demod_soft, - data->data_recovered); + armral_polar_rate_recovery(data->n, data->e, data->k, data->i_bil, + data->data_demod_soft, data->data_recovered); // Now run the decoding armral_polar_decode_block(data->n, data->frozen_mask, data->l, @@ -261,11 +269,13 @@ int run_check(random_state *state, double snr_db, polar_example_data *data) { struct sim_result { sim_result(uint32_t n, uint32_t e_in, uint32_t k_in, uint32_t l_in, - armral_modulation_type mod, uint16_t ulp_in, double ebn0_in, - double snr_in, uint32_t nb, uint32_t nm, uint32_t num_messages) + armral_modulation_type mod, armral_polar_ibil_type i_bil_in, + uint16_t ulp_in, double ebn0_in, double snr_in, uint32_t nb, + uint32_t nm, uint32_t num_messages) : len(n), e(e_in), k(k_in), l(l_in), - mod_type(armral_simulation::mod_to_str(mod)), ulp(ulp_in), ebn0(ebn0_in), - snr(snr_in), bler(static_cast(nm) / num_messages), + mod_type(armral_simulation::mod_to_str(mod)), i_bil(i_bil_in), + ulp(ulp_in), ebn0(ebn0_in), snr(snr_in), + bler(static_cast(nm) / num_messages), ber(static_cast(nb) / (num_messages * k)) {} uint32_t len; @@ -273,6 +283,7 @@ struct sim_result { uint32_t k; uint32_t l; const char *mod_type; + armral_polar_ibil_type i_bil; uint16_t ulp; double ebn0; double snr; @@ -285,16 +296,16 @@ struct sim_result { s.setf(std::ios::fixed, std::ios::floatfield); s << "{\"len\": " << len << ", \"e\": " << e << ", \"k\": " << k << ", \"l\": " << l << ", \"mod_type\": \"" << mod_type - << "\", \"ulp\": " << ulp << ", \"Eb/N0\": " << ebn0 - << ", \"snr\": " << snr << ", \"bler\": " << bler << ", \"ber\": " << ber - << "}"; + << ",\"i_bil\": \"" << i_bil << "\", \"ulp\": " << ulp + << ", \"Eb/N0\": " << ebn0 << ", \"snr\": " << snr + << ", \"bler\": " << bler << ", \"ber\": " << ber << "}"; return std::move(s).str(); } }; bool run_snr(uint32_t e, uint32_t k, uint32_t l, - armral_modulation_type mod_type, uint16_t ulp, double ebn0_db) { - + armral_modulation_type mod_type, armral_polar_ibil_type i_bil, + uint16_t ulp, double ebn0_db) { uint32_t n = get_codeword_length(e, k); // Compute SNR in dB int bits_per_symb = armral_simulation::bits_per_symbol(mod_type); @@ -315,7 +326,7 @@ bool run_snr(uint32_t e, uint32_t k, uint32_t l, uint64_t nr = 1e5; #pragma omp parallel reduction(+ : nb, num_message_errors) { - polar_example_data data(n, e, k, l, mod_type, ulp); + polar_example_data data(n, e, k, l, i_bil, mod_type, ulp); #pragma omp for for (uint64_t r = 0; r < nr; ++r) { auto state = random_state::from_seeds({r, nr_total}); @@ -328,7 +339,7 @@ bool run_snr(uint32_t e, uint32_t k, uint32_t l, } // Write out data in JSON format - std::cout << sim_result(n, e, k, l, mod_type, ulp, ebn0_db, snr_db, nb, + std::cout << sim_result(n, e, k, l, mod_type, i_bil, ulp, ebn0_db, snr_db, nb, num_message_errors, nr_total) .to_str() << std::endl; @@ -347,12 +358,13 @@ int main(int argc, char **argv) { uint32_t l = 1; uint16_t ulp = 0; armral_modulation_type mod_type = ARMRAL_MOD_256QAM; + armral_polar_ibil_type i_bil = ARMRAL_POLAR_IBIL_ENABLE; + bool is_i_bil_set = false; bool is_mod_set = false; bool print_usage = false; - // Parse arguments int option; - while ((option = getopt(argc, argv, "k:e:m:u:l:")) != -1) { + while ((option = getopt(argc, argv, "k:e:m:i:u:l")) != -1) { switch (option) { case 'k': k = (uint32_t)atoi(optarg); @@ -366,6 +378,10 @@ int main(int argc, char **argv) { mod_type = (armral_modulation_type)atoi(optarg); is_mod_set = true; break; + case 'i': + i_bil = (armral_polar_ibil_type)atoi(optarg); + is_i_bil_set = true; + break; case 'u': ulp = (uint16_t)atoi(optarg); break; @@ -377,7 +393,6 @@ int main(int argc, char **argv) { print_usage = true; } } - // Check user input if (!is_k_set) { std::cerr << "Please specify a number of information bits (k).\n" @@ -401,6 +416,12 @@ int main(int argc, char **argv) { << armral_simulation::print_valid_mod_type(1) << std::endl; print_usage = true; } + if (!is_i_bil_set) { + std::cerr << "Please specify the flag i_bil to enable/disable\n" + << "the interleaving of coded bits.\n" + << std::endl; + print_usage = true; + } // Print usage if required, then exit and return failure. if (print_usage) { @@ -418,8 +439,8 @@ int main(int argc, char **argv) { // cause the simulation to never decode in an error-free manner. ulp = 128; } - - for (double snr = -2; run_snr(e, k, l, mod_type, ulp, snr); snr += 0.5) { + for (double snr = -2; run_snr(e, k, l, mod_type, i_bil, ulp, snr); + snr += 0.5) { } return 0; diff --git a/src/UpperPHY/Polar/arm_polar_rate_matching.cpp b/src/UpperPHY/Polar/arm_polar_rate_matching.cpp index b856b197e451c0392cad8dc760085be5350837e2..9fdf534085963c8e1026fad2aa05c38dc4606f74 100644 --- a/src/UpperPHY/Polar/arm_polar_rate_matching.cpp +++ b/src/UpperPHY/Polar/arm_polar_rate_matching.cpp @@ -81,33 +81,42 @@ static void channel_interleave(int e, uint8_t *in, uint8_t *out) { template armral_status rate_matching(uint32_t n, uint32_t e, uint32_t k, + armral_polar_ibil_type i_bil, const uint8_t *p_d_seq_in, uint8_t *p_f_seq_out, Allocator &allocator) { auto p_y_seq = allocate_zeroed(allocator, n / 8); - auto p_e_seq = allocate_zeroed(allocator, (e + 7) / 8); // sub-block interleaving polar::subblock_interleave(n, p_d_seq_in, p_y_seq.get()); - // bit selection - polar::bit_selection(n, e, k, p_y_seq.get(), p_e_seq.get()); - // channel interleaving - polar::channel_interleave(e, p_e_seq.get(), p_f_seq_out); + + if (i_bil == ARMRAL_POLAR_IBIL_DISABLE) { + memset((void *)p_f_seq_out, 0, (e + 7) / 8); + // bit selection + polar::bit_selection(n, e, k, p_y_seq.get(), p_f_seq_out); + } else { + auto p_e_seq = allocate_zeroed(allocator, (e + 7) / 8); + // bit selection + polar::bit_selection(n, e, k, p_y_seq.get(), p_e_seq.get()); + // channel interleaving + polar::channel_interleave(e, p_e_seq.get(), p_f_seq_out); + } return ARMRAL_SUCCESS; } } // namespace polar armral_status armral_polar_rate_matching(uint32_t n, uint32_t e, uint32_t k, + armral_polar_ibil_type i_bil, const uint8_t *p_d_seq_in, uint8_t *p_f_seq_out) { heap_allocator allocator{}; - return polar::rate_matching(n, e, k, p_d_seq_in, p_f_seq_out, allocator); + return polar::rate_matching(n, e, k, i_bil, p_d_seq_in, p_f_seq_out, + allocator); } -armral_status armral_polar_rate_matching_noalloc(uint32_t n, uint32_t e, - uint32_t k, - const uint8_t *p_d_seq_in, - uint8_t *p_f_seq_out, - void *buffer) { +armral_status armral_polar_rate_matching_noalloc( + uint32_t n, uint32_t e, uint32_t k, armral_polar_ibil_type i_bil, + const uint8_t *p_d_seq_in, uint8_t *p_f_seq_out, void *buffer) { buffer_bump_allocator allocator{buffer}; - return polar::rate_matching(n, e, k, p_d_seq_in, p_f_seq_out, allocator); + return polar::rate_matching(n, e, k, i_bil, p_d_seq_in, p_f_seq_out, + allocator); } diff --git a/src/UpperPHY/Polar/arm_polar_rate_recovery.cpp b/src/UpperPHY/Polar/arm_polar_rate_recovery.cpp index 8210a14ef4d87a1c239a8d35de457cd2048a21b1..95a751fd6290ad5a1a8d1c42731dccac9750fa1a 100644 --- a/src/UpperPHY/Polar/arm_polar_rate_recovery.cpp +++ b/src/UpperPHY/Polar/arm_polar_rate_recovery.cpp @@ -83,15 +83,22 @@ static void subblock_deinterleave(int n, const int8_t *in, int8_t *out) { } template -armral_status rate_recovery(uint32_t n, uint32_t e, uint32_t k, - const int8_t *p_llr_in, int8_t *p_llr_out, - Allocator &allocator) { +armral_status +rate_recovery(uint32_t n, uint32_t e, uint32_t k, armral_polar_ibil_type i_bil, + const int8_t *p_llr_in, int8_t *p_llr_out, Allocator &allocator) { auto p_y_seq = allocate_zeroed(allocator, n); - auto p_e_seq = allocate_zeroed(allocator, e); - // channel de-interleaving - channel_deinterleave(e, p_llr_in, p_e_seq.get()); - // llr recovery - llr_recovery(n, e, k, p_e_seq.get(), p_y_seq.get()); + + if (i_bil == ARMRAL_POLAR_IBIL_DISABLE) { + // llr recovery + llr_recovery(n, e, k, p_llr_in, p_y_seq.get()); + } else { + auto p_e_seq = allocate_zeroed(allocator, e); + // channel de-interleaving + channel_deinterleave(e, p_llr_in, p_e_seq.get()); + // llr recovery + llr_recovery(n, e, k, p_e_seq.get(), p_y_seq.get()); + } + // sub-block de-interleaving subblock_deinterleave(n, p_y_seq.get(), p_llr_out); return ARMRAL_SUCCESS; @@ -100,17 +107,16 @@ armral_status rate_recovery(uint32_t n, uint32_t e, uint32_t k, } // namespace polar armral_status armral_polar_rate_recovery(uint32_t n, uint32_t e, uint32_t k, + armral_polar_ibil_type i_bil, const int8_t *p_llr_in, int8_t *p_llr_out) { heap_allocator allocator{}; - return polar::rate_recovery(n, e, k, p_llr_in, p_llr_out, allocator); + return polar::rate_recovery(n, e, k, i_bil, p_llr_in, p_llr_out, allocator); } -armral_status armral_polar_rate_recovery_noalloc(uint32_t n, uint32_t e, - uint32_t k, - const int8_t *p_llr_in, - int8_t *p_llr_out, - void *buffer) { +armral_status armral_polar_rate_recovery_noalloc( + uint32_t n, uint32_t e, uint32_t k, armral_polar_ibil_type i_bil, + const int8_t *p_llr_in, int8_t *p_llr_out, void *buffer) { buffer_bump_allocator allocator{buffer}; - return polar::rate_recovery(n, e, k, p_llr_in, p_llr_out, allocator); + return polar::rate_recovery(n, e, k, i_bil, p_llr_in, p_llr_out, allocator); } diff --git a/test/Polar/rate_matching/main.cpp b/test/Polar/rate_matching/main.cpp index c39fd9c3d5cd8e92f580a89ca12c27691834a613..00376cea9e030035ab231ab31e4febc8a13b9762 100644 --- a/test/Polar/rate_matching/main.cpp +++ b/test/Polar/rate_matching/main.cpp @@ -84,20 +84,27 @@ static void ref_channel_interleave(int e, const uint8_t *in, uint8_t *out) { } static void reference_polar_rate_matching(int n, int e, int k, + armral_polar_ibil_type i_bil, const uint8_t *p_d, uint8_t *p_f) { std::vector p_y(n / 8, 0); - std::vector p_e((e + 7) / 8, 0); // sub-block interleaving ref_subblock_interleave(n, p_d, p_y.data()); - // bit selection - ref_bit_selection(n, e, k, p_y.data(), p_e.data()); - // channel interleaving - ref_channel_interleave(e, p_e.data(), p_f); + if (i_bil == ARMRAL_POLAR_IBIL_DISABLE) { + memset((void *)p_f, 0, (e + 7) / 8); + // bit selection + ref_bit_selection(n, e, k, p_y.data(), p_f); + } else { + std::vector p_e((e + 7) / 8, 0); + // bit selection + ref_bit_selection(n, e, k, p_y.data(), p_e.data()); + // channel interleaving + ref_channel_interleave(e, p_e.data(), p_f); + } } template static bool run_polar_rate_matching_test( - char const *name, int n, int e, int k, + char const *name, int n, int e, int k, armral_polar_ibil_type i_bil, PolarRateMatchingFunction polar_rate_matching_under_test) { assert(n % 32 == 0); assert(k <= e); @@ -106,9 +113,9 @@ static bool run_polar_rate_matching_test( auto ref_f = allocate_random_bits(e); auto f = ref_f; - printf("[%s] n=%d, e=%d, k=%d\n", name, n, e, k); - polar_rate_matching_under_test(n, e, k, ref_d.data(), f.data()); - reference_polar_rate_matching(n, e, k, ref_d.data(), ref_f.data()); + printf("[%s] i_bil=%d n=%d, e=%d, k=%d\n", name, i_bil, n, e, k); + polar_rate_matching_under_test(n, e, k, i_bil, ref_d.data(), f.data()); + reference_polar_rate_matching(n, e, k, i_bil, ref_d.data(), ref_f.data()); return check_results_u8(name, f.data(), ref_f.data(), e / 8); } @@ -126,6 +133,11 @@ run_all_tests(char const *name, // - e >= n (repetition) for (int e = k; e <= 2 * n; e += k) { passed &= run_polar_rate_matching_test(name, n, e, k, + ARMRAL_POLAR_IBIL_DISABLE, + polar_rate_matching_under_test); + + passed &= run_polar_rate_matching_test(name, n, e, k, + ARMRAL_POLAR_IBIL_ENABLE, polar_rate_matching_under_test); } } diff --git a/test/Polar/rate_recovery/main.cpp b/test/Polar/rate_recovery/main.cpp index b98df08af32d9d7d2bd42858dc134cbe465a2215..5d985ffb9f3f52d21f4a3dff8ff6e133c1d288b7 100644 --- a/test/Polar/rate_recovery/main.cpp +++ b/test/Polar/rate_recovery/main.cpp @@ -102,20 +102,28 @@ static void ref_subblock_deinterleave(int n, const int8_t *in, int8_t *out) { } static void reference_polar_rate_recovery(int n, int e, int k, + armral_polar_ibil_type i_bil, const int8_t *p_f, int8_t *p_d) { std::vector p_y(n, 0); - std::vector p_e(e, 0); - // channel de-interleaving - ref_channel_deinterleave(e, p_f, p_e.data()); - // llr recovery - ref_llr_recovery(n, e, k, p_e.data(), p_y.data()); + + if (i_bil == ARMRAL_POLAR_IBIL_DISABLE) { + // llr recovery + ref_llr_recovery(n, e, k, p_f, p_y.data()); + + } else { + std::vector p_e(e, 0); + // channel de-interleaving + ref_channel_deinterleave(e, p_f, p_e.data()); + // llr recovery + ref_llr_recovery(n, e, k, p_e.data(), p_y.data()); + } // sub-block de-interleaving ref_subblock_deinterleave(n, p_y.data(), p_d); } template static bool run_polar_rate_recovery_test( - char const *name, int n, int e, int k, + char const *name, int n, int e, int k, armral_polar_ibil_type i_bil, PolarRateRecoveryFunction polar_rate_recovery_under_test) { assert(n % 32 == 0); assert(k <= e); @@ -124,9 +132,11 @@ static bool run_polar_rate_recovery_test( auto ref_llr = allocate_random_i8(n); auto llr = ref_llr; - printf("[%s] n=%d, e=%d, k=%d\n", name, n, e, k); - polar_rate_recovery_under_test(n, e, k, ref_llr_demod.data(), llr.data()); - reference_polar_rate_recovery(n, e, k, ref_llr_demod.data(), ref_llr.data()); + printf("[%s] i_bil=%d n=%d, e=%d, k=%d\n", name, i_bil, n, e, k); + polar_rate_recovery_under_test(n, e, k, i_bil, ref_llr_demod.data(), + llr.data()); + reference_polar_rate_recovery(n, e, k, i_bil, ref_llr_demod.data(), + ref_llr.data()); return check_llrs_equal(llr.data(), ref_llr.data(), n); } @@ -144,6 +154,10 @@ run_all_tests(char const *name, // - e >= n (repetition) for (int e = k; e <= 2 * n; e += k) { passed &= run_polar_rate_recovery_test(name, n, e, k, + ARMRAL_POLAR_IBIL_DISABLE, + polar_rate_recovery_under_test); + passed &= run_polar_rate_recovery_test(name, n, e, k, + ARMRAL_POLAR_IBIL_ENABLE, polar_rate_recovery_under_test); } }