Added Polar RM and removed vectors with malloc from FEC NR

master
Xavier Arteaga 4 years ago committed by Andre Puschmann
parent 2b59e90304
commit bde1fa703d

@ -0,0 +1,76 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*!
* \file polar_chanalloc.h
* \brief Declaration of the subchannel allocation block.
* \author Jesus Gomez (CTTC)
* \date 2020
*
* \copyright Software Radio Systems Limited
*
*
*/
#ifndef SRSLTE_CHANALLOC_H
#define SRSLTE_CHANALLOC_H
#include "srslte/config.h"
#include "stdint.h"
/*!
* Allocates message bits (data + CRC) to the encoder input bit vector at the
* positions specified in \a K_set\\PC_set, computes and allocates the PC bits and
* zeros to the remaining positions.
* \param[in] message A pointer to the vector with the message bits (data and CRC).
* \param[out] input_encoder A pointer to the encoder input bit vector.
* \param[in] N The codeword length.
* \param[in] K Number of data + CRC bits.
* \param[in] nPC Number of parity check (PC) bits.
* \param[in] K_set Pointer to the indices of the encoder input vector containing.
* \param[in] PC_set Pointer to the indices of the parity check bits.
*/
void srslte_polar_chanalloc_tx(const uint8_t* message,
uint8_t* input_encoder,
const uint16_t N,
const uint16_t K,
const uint8_t nPC,
const uint16_t* K_set,
const uint16_t* PC_set);
/*!
* Extracts message bits (data + CRC) from the decoder output vector
* according to the positions specified in \a K_set\\PC_set.
* \param[in] output_decoder A pointer to the decoder output bit vector.
* \param[out] message A pointer to the vector with the message bits (data and CRC).
* \param[in] K Number of data + CRC bits.
* \param[in] nPC Number of parity check (PC) bits.
* \param[in] K_set Pointer to the indices of the encoder input vector containing.
* \param[in] PC_set Pointer to the indices of the parity check bits.
*/
void srslte_polar_chanalloc_rx(const uint8_t* output_decoder,
uint8_t* message,
const uint16_t K,
const uint8_t nPC,
const uint16_t* K_set,
const uint16_t* PC_set);
#endif // SRSLTE_CHANALLOC_H

@ -0,0 +1,417 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*!
* \file polar_code.h
* \brief Declaration of the function that obtains
* the polar code parameters.
* \author Jesus Gomez (CTTC)
* \date 2020
*
* \copyright Software Radio Systems Limited
*
* The message and parity check sets provided by this functions are needed by
* the subchannel allocation block.
* The frozen bit set provided by this function is used by the polar decoder.
*
*/
#ifndef SRSLTE_POLAR_CODE_H
#define SRSLTE_POLAR_CODE_H
#include "srslte/config.h"
#include "srslte/phy/utils/debug.h"
#include <stdint.h>
//#define debug
/*!
* \brief Maximum rate-matched codeword length
*/
static const uint16_t EMAX = 8192;
/*!
* \brief Maximum codeword length
*/
static const uint16_t NMAX = 1024;
/*!
* \brief \f$log_2(EMAX)\f$
*/
static const uint16_t eMAX = 13; // log2(EMAX);
/*!
* \brief Look-up table for the mother code with code_size_log = 5.
*/
static const uint16_t mother_code_5[32] = {0, 1, 2, 4, 8, 16, 3, 5, 9, 6, 17, 10, 18, 12, 20, 24,
7, 11, 19, 13, 14, 21, 26, 25, 22, 28, 15, 23, 27, 29, 30, 31};
/*!
* \brief Look-up table for the mother code with code_size_log = 6.
*/
static const uint16_t mother_code_6[64] = {0, 1, 2, 4, 8, 16, 32, 3, 5, 9, 6, 17, 10, 18, 12, 33,
20, 34, 24, 36, 7, 11, 40, 19, 13, 48, 14, 21, 35, 26, 37, 25,
22, 38, 41, 28, 42, 49, 44, 50, 15, 52, 23, 56, 27, 39, 29, 43,
30, 45, 51, 46, 53, 54, 57, 58, 60, 31, 47, 55, 59, 61, 62, 63};
/*!
* \brief Look-up table for the mother code with code_size_log = 7.
*/
static const uint16_t mother_code_7[128] = {
0, 1, 2, 4, 8, 16, 32, 3, 5, 64, 9, 6, 17, 10, 18, 12, 33, 65, 20, 34, 24, 36,
7, 66, 11, 40, 68, 19, 13, 48, 14, 72, 21, 35, 26, 80, 37, 25, 22, 38, 96, 67, 41, 28,
69, 42, 49, 74, 70, 44, 81, 50, 73, 15, 52, 23, 76, 82, 56, 27, 97, 39, 84, 29, 43, 98,
88, 30, 71, 45, 100, 51, 46, 75, 104, 53, 77, 54, 83, 57, 112, 78, 85, 58, 99, 86, 60, 89,
101, 31, 90, 102, 105, 92, 47, 106, 55, 113, 79, 108, 59, 114, 87, 116, 61, 91, 120, 62, 103, 93,
107, 94, 109, 115, 110, 117, 118, 121, 122, 63, 124, 95, 111, 119, 123, 125, 126, 127};
/*!
* \brief Look-up table for the mother code with code_size_log = 8.
*/
static const uint16_t mother_code_8[256] = {
0, 1, 2, 4, 8, 16, 32, 3, 5, 64, 9, 6, 17, 10, 18, 128, 12, 33, 65, 20, 34, 24,
36, 7, 129, 66, 11, 40, 68, 130, 19, 13, 48, 14, 72, 21, 132, 35, 26, 80, 37, 25, 22, 136,
38, 96, 67, 41, 144, 28, 69, 42, 49, 74, 160, 192, 70, 44, 131, 81, 50, 73, 15, 133, 52, 23,
134, 76, 137, 82, 56, 27, 97, 39, 84, 138, 145, 29, 43, 98, 88, 140, 30, 146, 71, 161, 45, 100,
51, 148, 46, 75, 104, 162, 53, 193, 152, 77, 164, 54, 83, 57, 112, 135, 78, 194, 85, 58, 168, 139,
99, 86, 60, 89, 196, 141, 101, 147, 176, 142, 31, 200, 90, 149, 102, 105, 163, 92, 47, 208, 150, 153,
165, 106, 55, 113, 154, 79, 108, 224, 166, 195, 59, 169, 114, 156, 87, 197, 116, 170, 61, 177, 91, 198,
172, 120, 201, 62, 143, 103, 178, 93, 202, 107, 180, 151, 209, 94, 204, 155, 210, 109, 184, 115, 167, 225,
157, 110, 117, 212, 171, 226, 216, 158, 118, 173, 121, 199, 179, 228, 174, 122, 203, 63, 181, 232, 124, 205,
182, 211, 185, 240, 206, 95, 213, 186, 227, 111, 214, 188, 217, 229, 159, 119, 218, 230, 233, 175, 123, 220,
183, 234, 125, 241, 207, 187, 236, 126, 242, 244, 189, 215, 219, 231, 248, 190, 221, 235, 222, 237, 243, 238,
245, 127, 191, 246, 249, 250, 252, 223, 239, 251, 247, 253, 254, 255};
/*!
* \brief Look-up table for the mother code with code_size_log = 9.
*/
static const uint16_t mother_code_9[512] = {
0, 1, 2, 4, 8, 16, 32, 3, 5, 64, 9, 6, 17, 10, 18, 128, 12, 33, 65, 20, 256, 34, 24,
36, 7, 129, 66, 11, 40, 68, 130, 19, 13, 48, 14, 72, 257, 21, 132, 35, 258, 26, 80, 37, 25, 22,
136, 260, 264, 38, 96, 67, 41, 144, 28, 69, 42, 49, 74, 272, 160, 288, 192, 70, 44, 131, 81, 50, 73,
15, 320, 133, 52, 23, 134, 384, 76, 137, 82, 56, 27, 97, 39, 259, 84, 138, 145, 261, 29, 43, 98, 88,
140, 30, 146, 71, 262, 265, 161, 45, 100, 51, 148, 46, 75, 266, 273, 104, 162, 53, 193, 152, 77, 164, 268,
274, 54, 83, 57, 112, 135, 78, 289, 194, 85, 276, 58, 168, 139, 99, 86, 60, 280, 89, 290, 196, 141, 101,
147, 176, 142, 321, 31, 200, 90, 292, 322, 263, 149, 102, 105, 304, 296, 163, 92, 47, 267, 385, 324, 208, 386,
150, 153, 165, 106, 55, 328, 113, 154, 79, 269, 108, 224, 166, 195, 270, 275, 291, 59, 169, 114, 277, 156, 87,
197, 116, 170, 61, 281, 278, 177, 293, 388, 91, 198, 172, 120, 201, 336, 62, 282, 143, 103, 178, 294, 93, 202,
323, 392, 297, 107, 180, 151, 209, 284, 94, 204, 298, 400, 352, 325, 155, 210, 305, 300, 109, 184, 115, 167, 225,
326, 306, 157, 329, 110, 117, 212, 171, 330, 226, 387, 308, 216, 416, 271, 279, 158, 337, 118, 332, 389, 173, 121,
199, 179, 228, 338, 312, 390, 174, 393, 283, 122, 448, 353, 203, 63, 340, 394, 181, 295, 285, 232, 124, 205, 182,
286, 299, 354, 211, 401, 185, 396, 344, 240, 206, 95, 327, 402, 356, 307, 301, 417, 213, 186, 404, 227, 418, 302,
360, 111, 331, 214, 309, 188, 449, 217, 408, 229, 159, 420, 310, 333, 119, 339, 218, 368, 230, 391, 313, 450, 334,
233, 175, 123, 341, 220, 314, 424, 395, 355, 287, 183, 234, 125, 342, 316, 241, 345, 452, 397, 403, 207, 432, 357,
187, 236, 126, 242, 398, 346, 456, 358, 405, 303, 244, 189, 361, 215, 348, 419, 406, 464, 362, 409, 219, 311, 421,
410, 231, 248, 369, 190, 364, 335, 480, 315, 221, 370, 422, 425, 451, 235, 412, 343, 372, 317, 222, 426, 453, 237,
433, 347, 243, 454, 318, 376, 428, 238, 359, 457, 399, 434, 349, 245, 458, 363, 127, 191, 407, 436, 465, 246, 350,
460, 249, 411, 365, 440, 374, 423, 466, 250, 371, 481, 413, 366, 468, 429, 252, 373, 482, 427, 414, 223, 472, 455,
377, 435, 319, 484, 430, 488, 239, 378, 459, 437, 380, 461, 496, 351, 467, 438, 251, 462, 442, 441, 469, 247, 367,
253, 375, 444, 470, 483, 415, 485, 473, 474, 254, 379, 431, 489, 486, 476, 439, 490, 463, 381, 497, 492, 443, 382,
498, 445, 471, 500, 446, 475, 487, 504, 255, 477, 491, 478, 383, 493, 499, 502, 494, 501, 447, 505, 506, 479, 508,
495, 503, 507, 509, 510, 511};
/*!
* \brief Look-up table for the mother code with code_size_log = 10.
*/
static const uint16_t mother_code_10[1024] = {
0, 1, 2, 4, 8, 16, 32, 3, 5, 64, 9, 6, 17, 10, 18, 128, 12, 33, 65, 20,
256, 34, 24, 36, 7, 129, 66, 512, 11, 40, 68, 130, 19, 13, 48, 14, 72, 257, 21, 132,
35, 258, 26, 513, 80, 37, 25, 22, 136, 260, 264, 38, 514, 96, 67, 41, 144, 28, 69, 42,
516, 49, 74, 272, 160, 520, 288, 528, 192, 544, 70, 44, 131, 81, 50, 73, 15, 320, 133, 52,
23, 134, 384, 76, 137, 82, 56, 27, 97, 39, 259, 84, 138, 145, 261, 29, 43, 98, 515, 88,
140, 30, 146, 71, 262, 265, 161, 576, 45, 100, 640, 51, 148, 46, 75, 266, 273, 517, 104, 162,
53, 193, 152, 77, 164, 768, 268, 274, 518, 54, 83, 57, 521, 112, 135, 78, 289, 194, 85, 276,
522, 58, 168, 139, 99, 86, 60, 280, 89, 290, 529, 524, 196, 141, 101, 147, 176, 142, 530, 321,
31, 200, 90, 545, 292, 322, 532, 263, 149, 102, 105, 304, 296, 163, 92, 47, 267, 385, 546, 324,
208, 386, 150, 153, 165, 106, 55, 328, 536, 577, 548, 113, 154, 79, 269, 108, 578, 224, 166, 519,
552, 195, 270, 641, 523, 275, 580, 291, 59, 169, 560, 114, 277, 156, 87, 197, 116, 170, 61, 531,
525, 642, 281, 278, 526, 177, 293, 388, 91, 584, 769, 198, 172, 120, 201, 336, 62, 282, 143, 103,
178, 294, 93, 644, 202, 592, 323, 392, 297, 770, 107, 180, 151, 209, 284, 648, 94, 204, 298, 400,
608, 352, 325, 533, 155, 210, 305, 547, 300, 109, 184, 534, 537, 115, 167, 225, 326, 306, 772, 157,
656, 329, 110, 117, 212, 171, 776, 330, 226, 549, 538, 387, 308, 216, 416, 271, 279, 158, 337, 550,
672, 118, 332, 579, 540, 389, 173, 121, 553, 199, 784, 179, 228, 338, 312, 704, 390, 174, 554, 581,
393, 283, 122, 448, 353, 561, 203, 63, 340, 394, 527, 582, 556, 181, 295, 285, 232, 124, 205, 182,
643, 562, 286, 585, 299, 354, 211, 401, 185, 396, 344, 586, 645, 593, 535, 240, 206, 95, 327, 564,
800, 402, 356, 307, 301, 417, 213, 568, 832, 588, 186, 646, 404, 227, 896, 594, 418, 302, 649, 771,
360, 539, 111, 331, 214, 309, 188, 449, 217, 408, 609, 596, 551, 650, 229, 159, 420, 310, 541, 773,
610, 657, 333, 119, 600, 339, 218, 368, 652, 230, 391, 313, 450, 542, 334, 233, 555, 774, 175, 123,
658, 612, 341, 777, 220, 314, 424, 395, 673, 583, 355, 287, 183, 234, 125, 557, 660, 616, 342, 316,
241, 778, 563, 345, 452, 397, 403, 207, 674, 558, 785, 432, 357, 187, 236, 664, 624, 587, 780, 705,
126, 242, 565, 398, 346, 456, 358, 405, 303, 569, 244, 595, 189, 566, 676, 361, 706, 589, 215, 786,
647, 348, 419, 406, 464, 680, 801, 362, 590, 409, 570, 788, 597, 572, 219, 311, 708, 598, 601, 651,
421, 792, 802, 611, 602, 410, 231, 688, 653, 248, 369, 190, 364, 654, 659, 335, 480, 315, 221, 370,
613, 422, 425, 451, 614, 543, 235, 412, 343, 372, 775, 317, 222, 426, 453, 237, 559, 833, 804, 712,
834, 661, 808, 779, 617, 604, 433, 720, 816, 836, 347, 897, 243, 662, 454, 318, 675, 618, 898, 781,
376, 428, 665, 736, 567, 840, 625, 238, 359, 457, 399, 787, 591, 678, 434, 677, 349, 245, 458, 666,
620, 363, 127, 191, 782, 407, 436, 626, 571, 465, 681, 246, 707, 350, 599, 668, 790, 460, 249, 682,
573, 411, 803, 789, 709, 365, 440, 628, 689, 374, 423, 466, 793, 250, 371, 481, 574, 413, 603, 366,
468, 655, 900, 805, 615, 684, 710, 429, 794, 252, 373, 605, 848, 690, 713, 632, 482, 806, 427, 904,
414, 223, 663, 692, 835, 619, 472, 455, 796, 809, 714, 721, 837, 716, 864, 810, 606, 912, 722, 696,
377, 435, 817, 319, 621, 812, 484, 430, 838, 667, 488, 239, 378, 459, 622, 627, 437, 380, 818, 461,
496, 669, 679, 724, 841, 629, 351, 467, 438, 737, 251, 462, 442, 441, 469, 247, 683, 842, 738, 899,
670, 783, 849, 820, 728, 928, 791, 367, 901, 630, 685, 844, 633, 711, 253, 691, 824, 902, 686, 740,
850, 375, 444, 470, 483, 415, 485, 905, 795, 473, 634, 744, 852, 960, 865, 693, 797, 906, 715, 807,
474, 636, 694, 254, 717, 575, 913, 798, 811, 379, 697, 431, 607, 489, 866, 723, 486, 908, 718, 813,
476, 856, 839, 725, 698, 914, 752, 868, 819, 814, 439, 929, 490, 623, 671, 739, 916, 463, 843, 381,
497, 930, 821, 726, 961, 872, 492, 631, 729, 700, 443, 741, 845, 920, 382, 822, 851, 730, 498, 880,
742, 445, 471, 635, 932, 687, 903, 825, 500, 846, 745, 826, 732, 446, 962, 936, 475, 853, 867, 637,
907, 487, 695, 746, 828, 753, 854, 857, 504, 799, 255, 964, 909, 719, 477, 915, 638, 748, 944, 869,
491, 699, 754, 858, 478, 968, 383, 910, 815, 976, 870, 917, 727, 493, 873, 701, 931, 756, 860, 499,
731, 823, 922, 874, 918, 502, 933, 743, 760, 881, 494, 702, 921, 501, 876, 847, 992, 447, 733, 827,
934, 882, 937, 963, 747, 505, 855, 924, 734, 829, 965, 938, 884, 506, 749, 945, 966, 755, 859, 940,
830, 911, 871, 639, 888, 479, 946, 750, 969, 508, 861, 757, 970, 919, 875, 862, 758, 948, 977, 923,
972, 761, 877, 952, 495, 703, 935, 978, 883, 762, 503, 925, 878, 735, 993, 885, 939, 994, 980, 926,
764, 941, 967, 886, 831, 947, 507, 889, 984, 751, 942, 996, 971, 890, 509, 949, 973, 1000, 892, 950,
863, 759, 1008, 510, 979, 953, 763, 974, 954, 879, 981, 982, 927, 995, 765, 956, 887, 985, 997, 986,
943, 891, 998, 766, 511, 988, 1001, 951, 1002, 893, 975, 894, 1009, 955, 1004, 1010, 957, 983, 958, 987,
1012, 999, 1016, 767, 989, 1003, 990, 1005, 959, 1011, 1013, 895, 1006, 1014, 1017, 1018, 991, 1020, 1007, 1015,
1019, 1021, 1022, 1023};
/*!
* \brief Look-up table for the block interleaver for code_size_log = 5.
*/
static const uint16_t blk_interleaver_5[32] = {0, 1, 2, 4, 3, 5, 6, 7, 8, 16, 9, 17, 10, 18, 11, 19,
12, 20, 13, 21, 14, 22, 15, 23, 24, 25, 26, 28, 27, 29, 30, 31};
/*!
* \brief Look-up table for the block interleaver for code_size_log = 6.
*/
static const uint16_t blk_interleaver_6[64] = {0, 1, 2, 3, 4, 5, 8, 9, 6, 7, 10, 11, 12, 13, 14, 15,
16, 17, 32, 33, 18, 19, 34, 35, 20, 21, 36, 37, 22, 23, 38, 39,
24, 25, 40, 41, 26, 27, 42, 43, 28, 29, 44, 45, 30, 31, 46, 47,
48, 49, 50, 51, 52, 53, 56, 57, 54, 55, 58, 59, 60, 61, 62, 63};
/*!
* \brief Look-up table for the block interleaver for code_size_log = 7.
*/
static const uint16_t blk_interleaver_7[128] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 12, 13, 14, 15, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 64, 65, 66, 67, 36, 37, 38, 39,
68, 69, 70, 71, 40, 41, 42, 43, 72, 73, 74, 75, 44, 45, 46, 47, 76, 77, 78, 79, 48, 49,
50, 51, 80, 81, 82, 83, 52, 53, 54, 55, 84, 85, 86, 87, 56, 57, 58, 59, 88, 89, 90, 91,
60, 61, 62, 63, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 112, 113,
114, 115, 108, 109, 110, 111, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
/*!
* \brief Look-up table for the block interleaver for code_size_log = 8.
*/
static const uint16_t blk_interleaver_8[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 32, 33, 34, 35, 36, 37, 38, 39, 24, 25, 26, 27, 28, 29, 30, 31, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 128, 129, 130, 131, 132, 133, 134, 135, 72, 73, 74, 75, 76, 77, 78, 79,
136, 137, 138, 139, 140, 141, 142, 143, 80, 81, 82, 83, 84, 85, 86, 87, 144, 145, 146, 147, 148, 149,
150, 151, 88, 89, 90, 91, 92, 93, 94, 95, 152, 153, 154, 155, 156, 157, 158, 159, 96, 97, 98, 99,
100, 101, 102, 103, 160, 161, 162, 163, 164, 165, 166, 167, 104, 105, 106, 107, 108, 109, 110, 111, 168, 169,
170, 171, 172, 173, 174, 175, 112, 113, 114, 115, 116, 117, 118, 119, 176, 177, 178, 179, 180, 181, 182, 183,
120, 121, 122, 123, 124, 125, 126, 127, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 224, 225, 226, 227,
228, 229, 230, 231, 216, 217, 218, 219, 220, 221, 222, 223, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
/*!
* \brief Look-up table for the block interleaver for code_size_log = 9.
*/
static const uint16_t blk_interleaver_9[512] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
138, 139, 140, 141, 142, 143, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 144,
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 272, 273, 274, 275, 276, 277, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
175, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 176, 177, 178, 179, 180, 181,
182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
317, 318, 319, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 320, 321, 322, 323,
324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
219, 220, 221, 222, 223, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 224, 225,
226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 352, 353, 354, 355, 356, 357, 358, 359, 360,
361, 362, 363, 364, 365, 366, 367, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390,
391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413,
414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 448, 449, 450, 451, 452,
453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443,
444, 445, 446, 447, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482,
483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505,
506, 507, 508, 509, 510, 511};
/*!
* \brief Look-up table for the block interleaver for code_size_log = 10.
*/
static const uint16_t blk_interleaver_10[1024] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527,
528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 288, 289, 290,
291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 544, 545, 546, 547, 548, 549, 550, 551, 552,
553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571,
572, 573, 574, 575, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 576, 577,
578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596,
597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 352, 353, 354, 355, 356, 357, 358, 359,
360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
379, 380, 381, 382, 383, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621,
622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 384,
385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403,
404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 640, 641, 642, 643, 644, 645, 646,
647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665,
666, 667, 668, 669, 670, 671, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428,
429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447,
672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690,
691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 448, 449, 450, 451, 452, 453,
454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472,
473, 474, 475, 476, 477, 478, 479, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715,
716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734,
735, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497,
498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 736, 737, 738, 739, 740,
741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759,
760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778,
779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797,
798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835,
836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854,
855, 856, 857, 858, 859, 860, 861, 862, 863, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924,
925, 926, 927, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879,
880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 928, 929, 930,
931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949,
950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968,
969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987,
988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006,
1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023};
/*!
* \brief Describes a polar set.
*/
typedef struct {
uint16_t N; /*!< \brief Number of coded bits (N). */
uint8_t n; /*!< \brief \f$ log_2(N)\f$.*/
uint16_t K; /*!< \brief Number of message bits (data and CRC). */
uint16_t nPC; /*!< \brief Number of parity check bits. */
uint16_t nWmPC; /*!< \brief Number of parity bits of minimum bandwidth type. */
uint16_t F_set_size; /*!< \brief Number of frozen bits. */
uint16_t* K_set; /*!< \brief Pointer to the indices of the encoder input vector containing data and CRC bits. */
uint16_t* tmp_K_set; /*!< \brief Temporal Pointer. */
uint16_t PC_set[4]; /*!< \brief Pointer to the indices of the encoder input vector containing the parity bits.*/
uint16_t* F_set; /*!< \brief Pointer to the indices of the encoder input vector containing frozen bits.*/
} srslte_polar_code_t;
/*!
* Returns a pointer to the desired mother code.
*/
static inline const uint16_t* get_mother_code(uint8_t n)
{
switch (n) {
case 5:
return mother_code_5;
break;
case 6:
return mother_code_6;
break;
case 7:
return mother_code_7;
break;
case 8:
return mother_code_8;
break;
case 9:
return mother_code_9;
break;
case 10:
return mother_code_10;
break;
default:
ERROR("Wrong code_size_log\n");
return NULL;
}
}
/*!
* Returns a pointer to the desired blk_interleaver.
*/
static inline const uint16_t* get_blk_interleaver(uint8_t n)
{
switch (n) {
case 5:
return blk_interleaver_5;
break;
case 6:
return blk_interleaver_6;
break;
case 7:
return blk_interleaver_7;
break;
case 8:
return blk_interleaver_8;
break;
case 9:
return blk_interleaver_9;
break;
case 10:
return blk_interleaver_10;
break;
default:
ERROR("Wrong code_size_log\n");
return NULL;
}
}
/*!
* Allocates resources for the message set, frozen set and parity set of any polar code.
* \param[out] c A pointer to the initialized polar code.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
int srslte_polar_code_init(srslte_polar_code_t* c);
/*!
* Initializes the different index sets as needed by the subchannel allocation block and/or by the polar decoder.
* \param[out] c A pointer to the initialized polar code.
* \param[in] K Number of data + CRC bits.
* \param[in] E Number of bits of the codeword after rate matching.
* \param[in] nMax Maximum \f$log_2(N)\f$, where \f$N\f$ is the codeword size, nMax = 9 for downlink and nMax = 10, for
* uplink.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
int srslte_polar_code_get(srslte_polar_code_t* c, const uint16_t K, const uint16_t E, const uint8_t nMax);
/*!
* The polar code "destructor": it frees all the resources.
* \param[in] c A pointer to the dismantled polar code.
*/
void srslte_polar_code_free(srslte_polar_code_t* c);
#endif // SRSLTE_POLAR_CODE_H

@ -31,7 +31,7 @@
/*! /*!
* Lists the different types of polar decoder. * Lists the different types of polar decoder.
*/ */
typedef enum { typedef enum SRSLTE_API {
SRSLTE_POLAR_DECODER_SSC_F = 0, /*!< \brief Floating-point Simplified Successive Cancellation (SSC) decoder. */ SRSLTE_POLAR_DECODER_SSC_F = 0, /*!< \brief Floating-point Simplified Successive Cancellation (SSC) decoder. */
SRSLTE_POLAR_DECODER_SSC_S = 1, /*!< \brief Fixed-point (16 bit) Simplified Successive Cancellation (SSC) decoder. */ SRSLTE_POLAR_DECODER_SSC_S = 1, /*!< \brief Fixed-point (16 bit) Simplified Successive Cancellation (SSC) decoder. */
SRSLTE_POLAR_DECODER_SSC_C = 2, /*!< \brief Fixed-point (8 bit) Simplified Successive Cancellation (SSC) decoder. */ SRSLTE_POLAR_DECODER_SSC_C = 2, /*!< \brief Fixed-point (8 bit) Simplified Successive Cancellation (SSC) decoder. */
@ -43,17 +43,27 @@ typedef enum {
* \brief Describes a polar decoder. * \brief Describes a polar decoder.
*/ */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
void* ptr; /*!< \brief Pointer to the actual polar decoder structure. */ void* ptr; /*!< \brief Pointer to the actual polar decoder structure. */
int (*decode_f)(void* ptr, uint8_t nMax; /*!< \brief Maximum \f$log_2(code_size)\f$. */
const float* symbols, int (*decode_f)(void* ptr,
uint8_t* data_decoded); /*!< \brief Pointer to the decoder function (float version). */ const float* symbols,
int (*decode_s)(void* ptr, uint8_t* data_decoded,
const int16_t* symbols, const uint8_t n,
uint8_t* data_decoded); /*!< \brief Pointer to the decoder function (16-bit version). */ const uint16_t* frozen_set,
int (*decode_c)(void* ptr, const uint16_t frozen_set_size); /*!< \brief Pointer to the decoder function (float version). */
const int8_t* symbols, int (*decode_s)(void* ptr,
uint8_t* data_decoded); /*!< \brief Pointer to the decoder function (8-bit version). */ const int16_t* symbols,
void (*free)(void*); /*!< \brief Pointer to a "destructor". */ uint8_t* data_decoded,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size); /*!< \brief Pointer to the decoder function (16-bit version). */
int (*decode_c)(void* ptr,
const int8_t* symbols,
uint8_t* data_decoded,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size); /*!< \brief Pointer to the decoder function (8-bit version). */
void (*free)(void*); /*!< \brief Pointer to a "destructor". */
} srslte_polar_decoder_t; } srslte_polar_decoder_t;
/*! /*!
@ -62,15 +72,11 @@ typedef struct SRSLTE_API {
* \param[out] q A pointer to the initialized polar decoder. * \param[out] q A pointer to the initialized polar decoder.
* \param[in] polar_decoder_type Polar decoder type. * \param[in] polar_decoder_type Polar decoder type.
* \param[in] code_size_log The \f$ log_2\f$ of the number of bits of the decoder input/output vector. * \param[in] code_size_log The \f$ log_2\f$ of the number of bits of the decoder input/output vector.
* \param[in] frozen_set A pointer to the frozenbit set (array of indices).
* \param[in] frozen_set_size Number of frozen bits.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
SRSLTE_API int srslte_polar_decoder_init(srslte_polar_decoder_t* q, SRSLTE_API int srslte_polar_decoder_init(srslte_polar_decoder_t* q,
srslte_polar_decoder_type_t polar_decoder_type, srslte_polar_decoder_type_t polar_decoder_type,
uint16_t code_size_log, const uint8_t code_size_log);
uint16_t* frozen_set,
uint16_t frozen_set_size);
/*! /*!
* The polar decoder "destructor": it frees all the resources. * The polar decoder "destructor": it frees all the resources.
@ -83,27 +89,51 @@ SRSLTE_API void srslte_polar_decoder_free(srslte_polar_decoder_t* q);
* \param[in] q A pointer to the desired polar decoder. * \param[in] q A pointer to the desired polar decoder.
* \param[in] input_llr The decoder LLR input vector. * \param[in] input_llr The decoder LLR input vector.
* \param[out] data_decoded The decoder output vector. * \param[out] data_decoded The decoder output vector.
* \param[in] code_size_log The \f$ log_2\f$ of the number of bits of the decoder input/output vector.
* \param[in] frozen_set The position of the frozen bits in increasing order.
* \param[in] frozen_set_size The size of the frozen_set.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
SRSLTE_API int srslte_polar_decoder_decode_f(srslte_polar_decoder_t* q, const float* input_llr, uint8_t* data_decoded); SRSLTE_API int srslte_polar_decoder_decode_f(srslte_polar_decoder_t* q,
const float* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
/*! /*!
* Decodes the input (int16_t) codeword with the specified polar decoder. * Decodes the input (int16_t) codeword with the specified polar decoder.
* \param[in] q A pointer to the desired polar decoder. * \param[in] q A pointer to the desired polar decoder.
* \param[in] input_llr The decoder LLR input vector. * \param[in] input_llr The decoder LLR input vector.
* \param[out] data_decoded The decoder output vector. * \param[out] data_decoded The decoder output vector.
* \param[in] code_size_log The \f$ log_2\f$ of the number of bits of the decoder input/output vector.
* \param[in] frozen_set The position of the frozen bits in increasing order.
* \param[in] frozen_set_size The size of the frozen_set.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
SRSLTE_API int SRSLTE_API int srslte_polar_decoder_decode_s(srslte_polar_decoder_t* q,
srslte_polar_decoder_decode_s(srslte_polar_decoder_t* q, const int16_t* input_llr, uint8_t* data_decoded); const int16_t* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
/*! /*!
* Decodes the input (int8_t) codeword with the specified polar decoder. * Decodes the input (int8_t) codeword with the specified polar decoder.
* \param[in] q A pointer to the desired polar decoder. * \param[in] q A pointer to the desired polar decoder.
* \param[in] input_llr The decoder LLR input vector. * \param[in] input_llr The decoder LLR input vector.
* \param[out] data_decoded The decoder output vector. * \param[out] data_decoded The decoder output vector.
* \param[in] code_size_log The \f$ log_2\f$ of the number of bits of the decoder input/output vector.
* \param[in] frozen_set The position of the frozen bits in increasing order.
* \param[in] frozen_set_size The size of the frozen_set.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
SRSLTE_API int srslte_polar_decoder_decode_c(srslte_polar_decoder_t* q, const int8_t* input_llr, uint8_t* data_decoded); SRSLTE_API int srslte_polar_decoder_decode_c(srslte_polar_decoder_t* q,
const int8_t* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
#endif // SRSLTE_POLARDECODER_H #endif // SRSLTE_POLARDECODER_H

@ -31,7 +31,7 @@
/*! /*!
* Lists the different types of polar decoder. * Lists the different types of polar decoder.
*/ */
typedef enum SRSLTE_API { typedef enum {
SRSLTE_POLAR_ENCODER_PIPELINED = 0, /*!< \brief Non-optimized version of the pipelined polar encoder*/ SRSLTE_POLAR_ENCODER_PIPELINED = 0, /*!< \brief Non-optimized version of the pipelined polar encoder*/
SRSLTE_POLAR_ENCODER_AVX2 = 1, /*!< \brief SIMD implementation of the polar encoder */ SRSLTE_POLAR_ENCODER_AVX2 = 1, /*!< \brief SIMD implementation of the polar encoder */
} srslte_polar_encoder_type_t; } srslte_polar_encoder_type_t;
@ -39,7 +39,7 @@ typedef enum SRSLTE_API {
/*! /*!
* \brief Describes a polar encoder. * \brief Describes a polar encoder.
*/ */
typedef struct srslte_polar_encoder_t { typedef struct SRSLTE_API {
void* ptr; /*!< \brief Pointer to the actual polar encoder structure. */ void* ptr; /*!< \brief Pointer to the actual polar encoder structure. */
int (*encode)(void* ptr, int (*encode)(void* ptr,
const uint8_t* input, const uint8_t* input,

@ -0,0 +1,181 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*!
* \file polar_rm.h
* \brief Declaration of the polar RateMatcher and RateDematcher.
* \author Jesus Gomez (CTTC)
* \date 2020
*
* \copyright Software Radio Systems Limited
*
*/
#ifndef SRSLTE_POLARRM_H
#define SRSLTE_POLARRM_H
/*!
* \brief Describes a polar rate matcher or rate dematcher
*/
typedef struct SRSLTE_API {
void* ptr; /*!< \brief Rate Matcher auxiliary registers. */
} srslte_polar_rm_t;
/*!
* Initializes the Rate Matcher for the maximum rate-matched codeword length
* \param[out] q A pointer to a srslte_polar_rm_t structure.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_tx_init(srslte_polar_rm_t* q);
/*!
* Carries out the actual rate-matching.
* \param[in] q A pointer to the Rate-Matcher (a srslte_polar_rm_t structure
* instance) that carries out the rate matching.
* \param[in] input The codeword obtained from the polar encoder.
* \param[out] output The rate-matched codeword resulting from the rate-matching
* operation.
* \param[in] n \f$log_2\f$ of the codeword length.
* \param[in] E Rate-matched codeword length.
* \param[in] K Message size (including CRC).
* \param[in] ibil Indicator of bit interliaver (set to 0 to disable).
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_tx(srslte_polar_rm_t* q,
const uint8_t* input,
uint8_t* output,
const uint8_t n,
const uint32_t E,
const uint32_t K,
const uint8_t ibil);
/*!
* Initializes all the Rate DeMatcher variables.
* \param[out] q A pointer to a srslte_polar_rm_t structure.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_rx_init_f(srslte_polar_rm_t* q);
/*!
* Carries out the actual rate-dematching.
* \param[in] q A pointer to the Rate-DeMatcher (a srslte_polar_rm_t structure
* instance) that carries out the rate matching.
* \param[in] input The LLRs obtained from the channel samples that correspond to
* the codeword to be first, rate-dematched and then decoded.
* \param[out] output The rate-dematched codeword resulting from the rate-dematching
* operation.
* \param[in] E Rate-matched codeword length.
* \param[in] n \f$log_2\f$ of the codeword length.
* \param[in] K Message size (including CRC).
* \param[in] ibil Indicator of bit interliaver (set to 0 to disable).
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_rx_f(srslte_polar_rm_t* q,
const float* input,
float* output,
const uint32_t E,
const uint8_t n,
const uint32_t K,
const uint8_t ibil);
/*!
* Initializes all the Rate DeMatcher variables (int16_t inputs).
* \param[out] q A pointer to a srslte_polar_rm_t structure.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_rx_init_s(srslte_polar_rm_t* q);
/*!
* Carries out the actual rate-dematching (in16_t inputs)
* \param[in] q A pointer to the Rate-DeMatcher (a srslte_polar_rm_t structure
* instance) that carries out the rate matching.
* \param[in] input The LLRs obtained from the channel samples that correspond to
* the codeword to be first, rate-dematched and then decoded.
* \param[out] output The rate-dematched codeword resulting from the rate-dematching
* operation.
* \param[in] E Rate-matched codeword length.
* \param[in] n \f$log_2\f$ of the codeword length.
* \param[in] K Message size (including CRC).
* \param[in] ibil Indicator of bit interliaver (set to 0 to disable).
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_rx_s(srslte_polar_rm_t* q,
const int16_t* input,
int16_t* output,
const uint32_t E,
const uint8_t n,
const uint32_t K,
const uint8_t ibil);
/*!
* Initializes all the Rate DeMatcher variables (int8_t inputs).
* \param[out] q A pointer to a srslte_polar_rm_t structure.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_rx_init_c(srslte_polar_rm_t* q);
/*!
* Carries out the actual rate-dematching (int8_t inputs).
* \param[in] q A pointer to the Rate-DeMatcher (a srslte_polar_rm_t structure
* instance) that carries out the rate matching.
* \param[in] input The LLRs obtained from the channel samples that correspond to
* the codeword to be first, rate-dematched and then decoded.
* \param[out] output The rate-dematched codeword resulting from the rate-dematching
* operation.
* \param[in] E Rate-matched codeword length.
* \param[in] n \f$log_2\f$ of the codeword length.
* \param[in] K Message size (including CRC).
* \param[in] ibil Indicator of bit interliaver (set to 0 to disable).
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_polar_rm_rx_c(srslte_polar_rm_t* q,
const int8_t* input,
int8_t* output,
const uint32_t E,
const uint8_t n,
const uint32_t K,
const uint8_t ibil);
/*!
* The Rate Matcher "destructor": it frees all the resources allocated to the rate-matcher.
* \param[in] q A pointer to the dismantled rate-matcher.
*/
SRSLTE_API void srslte_polar_rm_tx_free(srslte_polar_rm_t* q);
/*!
* The Rate Matcher "destructor": it frees all the resources allocated to the rate-dematcher.
* \param[in] q A pointer to the dismantled rate-dematcher.
*/
SRSLTE_API void srslte_polar_rm_rx_free_f(srslte_polar_rm_t* q);
/*!
* The Rate Matcher "destructor" for short symbols: it frees all the resources allocated to the rate-dematcher.
* \param[in] q A pointer to the dismantled rate-dematcher.
*/
SRSLTE_API void srslte_polar_rm_rx_free_s(srslte_polar_rm_t* q);
/*!
* The Rate Matcher "destructor" for int8_t symbols: it frees all the resources allocated to the rate-dematcher.
* \param[in] q A pointer to the dismantled rate-dematcher.
*/
SRSLTE_API void srslte_polar_rm_rx_free_c(srslte_polar_rm_t* q);
#endif // SRSLTE_POLARRM_H

@ -88,18 +88,18 @@ void* create_ldpc_dec_s(uint8_t bgN, uint8_t bgM, uint16_t ls, float scaling_fct
return NULL; return NULL;
} }
if ((vp->soft_bits = malloc(liftN * sizeof(int16_t))) == NULL) { if ((vp->soft_bits = srslte_vec_i16_malloc(liftN)) == NULL) {
free(vp); free(vp);
return NULL; return NULL;
} }
if ((vp->check_to_var = malloc((hrrN + ls) * bgM * sizeof(int16_t))) == NULL) { if ((vp->check_to_var = srslte_vec_i16_malloc((hrrN + ls) * bgM)) == NULL) {
free(vp->soft_bits); free(vp->soft_bits);
free(vp); free(vp);
return NULL; return NULL;
} }
if ((vp->var_to_check = malloc((hrrN + ls) * sizeof(int16_t))) == NULL) { if ((vp->var_to_check = srslte_vec_i16_malloc(hrrN + ls)) == NULL) {
free(vp->check_to_var); free(vp->check_to_var);
free(vp->soft_bits); free(vp->soft_bits);
free(vp); free(vp);

@ -694,7 +694,7 @@ int srslte_ldpc_decoder_init(srslte_ldpc_decoder_t* q,
q->liftM = ls * q->bgM; q->liftM = ls * q->bgM;
q->liftN = ls * q->bgN; q->liftN = ls * q->bgN;
q->pcm = srslte_vec_malloc(q->bgM * q->bgN * sizeof(uint16_t)); q->pcm = srslte_vec_u16_malloc(q->bgM * q->bgN);
if (!q->pcm) { if (!q->pcm) {
perror("malloc"); perror("malloc");
return -1; return -1;

@ -111,7 +111,7 @@ static int init_c(srslte_ldpc_encoder_t* q)
q->free = free_enc_c; q->free = free_enc_c;
q->ptr = srslte_vec_malloc(q->bgM * q->ls * sizeof(uint8_t)); q->ptr = srslte_vec_u8_malloc(q->bgM * q->ls);
if (!q->ptr) { if (!q->ptr) {
perror("malloc"); perror("malloc");
free_enc_c(q); free_enc_c(q);
@ -337,7 +337,7 @@ int srslte_ldpc_encoder_init(srslte_ldpc_encoder_t* q,
q->liftM = ls * q->bgM; q->liftM = ls * q->bgM;
q->liftN = ls * q->bgN; q->liftN = ls * q->bgN;
q->pcm = srslte_vec_malloc(q->bgM * q->bgN * sizeof(uint16_t)); q->pcm = srslte_vec_u16_malloc(q->bgM * q->bgN);
if (!q->pcm) { if (!q->pcm) {
perror("malloc"); perror("malloc");
return -1; return -1;

@ -205,9 +205,6 @@ int main(int argc, char** argv)
uint32_t F = encoder.bgK - 5; // This value is arbitrary uint32_t F = encoder.bgK - 5; // This value is arbitrary
finalK = encoder.liftK;
finalN = encoder.liftN - 2 * lift_size;
if (rm_length == 0) { if (rm_length == 0) {
rm_length = finalN - F; rm_length = finalN - F;
} }
@ -229,18 +226,21 @@ int main(int argc, char** argv)
1.0 * (encoder.liftK - F) / rm_length); 1.0 * (encoder.liftK - F) / rm_length);
printf("\n Signal-to-Noise Ratio -> %.2f dB\n", snr); printf("\n Signal-to-Noise Ratio -> %.2f dB\n", snr);
messages_true = malloc(finalK * batch_size * sizeof(uint8_t)); finalK = encoder.liftK;
messages_sim_f = malloc(finalK * batch_size * sizeof(uint8_t)); finalN = encoder.liftN - 2 * lift_size;
messages_sim_s = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_c = malloc(finalK * batch_size * sizeof(uint8_t)); messages_true = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_c_flood = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_f = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_avx = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_s = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_avx_flood = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_c = srslte_vec_u8_malloc(finalK * batch_size);
codewords = malloc(finalN * batch_size * sizeof(uint8_t)); messages_sim_c_flood = srslte_vec_u8_malloc(finalK * batch_size);
symbols_rm = malloc((rm_length + F) * batch_size * sizeof(float)); messages_sim_avx = srslte_vec_u8_malloc(finalK * batch_size);
symbols = malloc(finalN * batch_size * sizeof(float)); messages_sim_avx_flood = srslte_vec_u8_malloc(finalK * batch_size);
symbols_s = malloc(finalN * batch_size * sizeof(int16_t)); codewords = srslte_vec_u8_malloc(finalN * batch_size);
symbols_c = malloc(finalN * batch_size * sizeof(int8_t)); symbols_rm = srslte_vec_f_malloc((rm_length + F) * batch_size);
symbols = srslte_vec_f_malloc(finalN * batch_size);
symbols_s = srslte_vec_i16_malloc(finalN * batch_size);
symbols_c = srslte_vec_i8_malloc(finalN * batch_size);
if (!messages_true || !messages_sim_f || !messages_sim_s || !messages_sim_c || // if (!messages_true || !messages_sim_f || !messages_sim_s || !messages_sim_c || //
!messages_sim_avx || !messages_sim_c_flood || !messages_sim_avx_flood || // !messages_sim_avx || !messages_sim_c_flood || !messages_sim_avx_flood || //
!codewords || !symbols || !symbols_s || !symbols_c) { !codewords || !symbols || !symbols_s || !symbols_c) {

@ -25,6 +25,7 @@
* - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2). * - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2).
*/ */
#include "srslte/phy/utils/vector.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -167,10 +168,10 @@ int main(int argc, char** argv)
finalK = decoder.liftK; finalK = decoder.liftK;
finalN = decoder.liftN - 2 * lift_size; finalN = decoder.liftN - 2 * lift_size;
messages_true = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_true = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
messages_sim = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_sim = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
codewords = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
symbols = malloc(finalN * NOF_MESSAGES * sizeof(int8_t)); symbols = srslte_vec_i8_malloc(finalN * NOF_MESSAGES);
if (!messages_true || !messages_sim || !codewords || !symbols) { if (!messages_true || !messages_sim || !codewords || !symbols) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);

@ -25,6 +25,7 @@
* - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2). * - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2).
*/ */
#include "srslte/phy/utils/vector.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -166,10 +167,10 @@ int main(int argc, char** argv)
finalK = decoder.liftK; finalK = decoder.liftK;
finalN = decoder.liftN - 2 * lift_size; finalN = decoder.liftN - 2 * lift_size;
messages_true = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_true = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
messages_sim = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_sim = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
codewords = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
symbols = malloc(finalN * NOF_MESSAGES * sizeof(int8_t)); symbols = srslte_vec_i8_malloc(finalN * NOF_MESSAGES);
if (!messages_true || !messages_sim || !codewords || !symbols) { if (!messages_true || !messages_sim || !codewords || !symbols) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);

@ -25,6 +25,7 @@
* - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2). * - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2).
*/ */
#include "srslte/phy/utils/vector.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -158,10 +159,10 @@ int main(int argc, char** argv)
finalK = decoder.liftK; finalK = decoder.liftK;
finalN = decoder.liftN - 2 * lift_size; finalN = decoder.liftN - 2 * lift_size;
messages_true = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_true = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
messages_sim = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_sim = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
codewords = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
symbols = malloc(finalN * NOF_MESSAGES * sizeof(int16_t)); symbols = srslte_vec_i16_malloc(finalN * NOF_MESSAGES);
if (!messages_true || !messages_sim || !codewords || !symbols) { if (!messages_true || !messages_sim || !codewords || !symbols) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);

@ -33,6 +33,7 @@
#include "srslte/phy/fec/ldpc/ldpc_common.h" #include "srslte/phy/fec/ldpc/ldpc_common.h"
#include "srslte/phy/fec/ldpc/ldpc_decoder.h" #include "srslte/phy/fec/ldpc/ldpc_decoder.h"
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */ srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
int lift_size = 2; /*!< \brief Lifting Size. */ int lift_size = 2; /*!< \brief Lifting Size. */
@ -158,10 +159,10 @@ int main(int argc, char** argv)
finalK = decoder.liftK; finalK = decoder.liftK;
finalN = decoder.liftN - 2 * lift_size; finalN = decoder.liftN - 2 * lift_size;
messages_true = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_true = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
messages_sim = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages_sim = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
codewords = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
symbols = malloc(finalN * NOF_MESSAGES * sizeof(float)); symbols = srslte_vec_f_malloc(finalN * NOF_MESSAGES);
if (!messages_true || !messages_sim || !codewords || !symbols) { if (!messages_true || !messages_sim || !codewords || !symbols) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);

@ -26,6 +26,7 @@
* - **-R \<number\>** Number of times tests are repeated (for computing throughput). * - **-R \<number\>** Number of times tests are repeated (for computing throughput).
*/ */
#include "srslte/phy/utils/vector.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -165,9 +166,9 @@ int main(int argc, char** argv)
finalK = encoder.liftK; finalK = encoder.liftK;
finalN = encoder.liftN - 2 * lift_size; finalN = encoder.liftN - 2 * lift_size;
messages = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
codewords_true = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords_true = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
codewords_sim = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords_sim = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
if (!messages || !codewords_true || !codewords_sim) { if (!messages || !codewords_true || !codewords_sim) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);

@ -34,6 +34,7 @@
#include "srslte/phy/fec/ldpc/ldpc_common.h" #include "srslte/phy/fec/ldpc/ldpc_common.h"
#include "srslte/phy/fec/ldpc/ldpc_encoder.h" #include "srslte/phy/fec/ldpc/ldpc_encoder.h"
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
static srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */ static srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
static int lift_size = 2; /*!< \brief Lifting Size. */ static int lift_size = 2; /*!< \brief Lifting Size. */
@ -165,9 +166,9 @@ int main(int argc, char** argv)
finalK = encoder.liftK; finalK = encoder.liftK;
finalN = encoder.liftN - 2 * lift_size; finalN = encoder.liftN - 2 * lift_size;
messages = malloc(finalK * NOF_MESSAGES * sizeof(uint8_t)); messages = srslte_vec_u8_malloc(finalK * NOF_MESSAGES);
codewords_true = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords_true = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
codewords_sim = malloc(finalN * NOF_MESSAGES * sizeof(uint8_t)); codewords_sim = srslte_vec_u8_malloc(finalN * NOF_MESSAGES);
if (!messages || !codewords_true || !codewords_sim) { if (!messages || !codewords_true || !codewords_sim) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);

@ -286,22 +286,22 @@ int main(int argc, char** argv)
1.0 * (encoder.liftK - F) / rm_length); 1.0 * (encoder.liftK - F) / rm_length);
printf("\n Signal-to-Noise Ratio -> %.2f dB\n", snr); printf("\n Signal-to-Noise Ratio -> %.2f dB\n", snr);
messages_true = malloc(finalK * batch_size * sizeof(uint8_t)); messages_true = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_f = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_f = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_s = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_s = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_c = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_c = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_c_flood = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_c_flood = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_avx = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_avx = srslte_vec_u8_malloc(finalK * batch_size);
messages_sim_avx_flood = malloc(finalK * batch_size * sizeof(uint8_t)); messages_sim_avx_flood = srslte_vec_u8_malloc(finalK * batch_size);
codewords = malloc(finalN * batch_size * sizeof(uint8_t)); codewords = srslte_vec_u8_malloc(finalN * batch_size);
rm_codewords = malloc(rm_length * batch_size * sizeof(uint8_t)); rm_codewords = srslte_vec_u8_malloc(rm_length * batch_size);
rm_symbols = malloc(rm_length * batch_size * sizeof(float)); rm_symbols = srslte_vec_f_malloc(rm_length * batch_size);
rm_symbols_s = malloc(rm_length * batch_size * sizeof(uint16_t)); rm_symbols_s = srslte_vec_i16_malloc(rm_length * batch_size);
rm_symbols_c = malloc(rm_length * batch_size * sizeof(uint8_t)); rm_symbols_c = srslte_vec_i8_malloc(rm_length * batch_size);
symbols = malloc(finalN * batch_size * sizeof(float)); symbols = srslte_vec_f_malloc(finalN * batch_size);
symbols_s = malloc(finalN * batch_size * sizeof(int16_t)); symbols_s = srslte_vec_i16_malloc(finalN * batch_size);
symbols_c = malloc(finalN * batch_size * sizeof(int8_t)); symbols_c = srslte_vec_i8_malloc(finalN * batch_size);
if (!messages_true || !messages_sim_f || !messages_sim_s || !messages_sim_c || // if (!messages_true || !messages_sim_f || !messages_sim_s || !messages_sim_c || //
!messages_sim_avx || !messages_sim_c_flood || !messages_sim_avx_flood || // !messages_sim_avx || !messages_sim_c_flood || !messages_sim_avx_flood || //
!codewords || !rm_codewords || !rm_symbols || !rm_symbols_s || !rm_symbols_c || !symbols || !symbols_s || !codewords || !rm_codewords || !rm_symbols || !rm_symbols_s || !rm_symbols_c || !symbols || !symbols_s ||

@ -192,15 +192,15 @@ int main(int argc, char** argv)
printf(" Final code rate -> (K-F)/E = (%d - %d)/%d = %.3f\n", encoder.liftK, F, E, 1.0 * (encoder.liftK - F) / E); printf(" Final code rate -> (K-F)/E = (%d - %d)/%d = %.3f\n", encoder.liftK, F, E, 1.0 * (encoder.liftK - F) / E);
printf("\n"); printf("\n");
codeblocks = malloc(C * K * sizeof(uint8_t)); codeblocks = srslte_vec_u8_malloc(C * K);
codewords = malloc(C * N * sizeof(uint8_t)); codewords = srslte_vec_u8_malloc(C * N);
rm_codewords = malloc(C * E * sizeof(uint8_t)); rm_codewords = srslte_vec_u8_malloc(C * E);
rm_symbols = malloc(C * E * sizeof(float)); rm_symbols = srslte_vec_f_malloc(C * E);
rm_symbols_s = malloc(C * E * sizeof(int16_t)); rm_symbols_s = srslte_vec_i16_malloc(C * E);
rm_symbols_c = malloc(C * E * sizeof(int8_t)); rm_symbols_c = srslte_vec_i8_malloc(C * E);
unrm_symbols = malloc(C * N * sizeof(float)); unrm_symbols = srslte_vec_f_malloc(C * N);
unrm_symbols_s = malloc(C * N * sizeof(int16_t)); unrm_symbols_s = srslte_vec_i16_malloc(C * N);
unrm_symbols_c = malloc(C * N * sizeof(int8_t)); unrm_symbols_c = srslte_vec_i8_malloc(C * N);
if (!codeblocks || !codewords || !rm_codewords || !rm_symbols || !rm_symbols_s || !rm_symbols_c || !unrm_symbols || if (!codeblocks || !codewords || !rm_codewords || !rm_symbols || !rm_symbols_s || !rm_symbols_c || !unrm_symbols ||
!unrm_symbols_s || !unrm_symbols_c) { !unrm_symbols_s || !unrm_symbols_c) {
perror("malloc"); perror("malloc");

@ -15,6 +15,8 @@ if (HAVE_AVX2)
endif (HAVE_AVX2) endif (HAVE_AVX2)
set(FEC_SOURCES ${FEC_SOURCES} ${AVX2_SOURCES} set(FEC_SOURCES ${FEC_SOURCES} ${AVX2_SOURCES}
polar/polar_chanalloc.c
polar/polar_code.c
polar/polar_encoder.c polar/polar_encoder.c
polar/polar_encoder_pipelined.c polar/polar_encoder_pipelined.c
polar/polar_decoder.c polar/polar_decoder.c
@ -23,6 +25,7 @@ set(FEC_SOURCES ${FEC_SOURCES} ${AVX2_SOURCES}
polar/polar_decoder_ssc_s.c polar/polar_decoder_ssc_s.c
polar/polar_decoder_ssc_c.c polar/polar_decoder_ssc_c.c
polar/polar_decoder_vector.c polar/polar_decoder_vector.c
polar/polar_rm.c
PARENT_SCOPE) PARENT_SCOPE)
add_subdirectory(test) add_subdirectory(test)

@ -0,0 +1,103 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*!
* \file polar_chanalloc.c
* \brief Definition of the subchannel allocation block.
* \author Jesus Gomez (CTTC)
* \date 2020
*
* \copyright Software Radio Systems Limited
*
*/
#include "srslte/phy/fec/polar/polar_chanalloc.h"
#include <string.h>
void srslte_polar_chanalloc_tx(const uint8_t* message,
uint8_t* input_encoder,
const uint16_t N,
const uint16_t K,
const uint8_t nPC,
const uint16_t* K_set,
const uint16_t* PC_set)
{
bzero(input_encoder, N * sizeof(uint8_t));
uint16_t i_o = 0;
if (nPC == 0) {
for (uint16_t i = 0; i < K; i++) {
i_o = K_set[i];
input_encoder[i_o] = message[i];
}
} else {
uint16_t tmpy0 = 0;
uint16_t y0 = 0;
uint16_t y1 = 0;
uint16_t y2 = 0;
uint16_t y3 = 0;
uint16_t y4 = 0;
uint16_t iKPC = 0;
uint16_t iPC = 0;
uint16_t iK = 0;
for (i_o = 0; i_o < N; i_o++) {
// circ. shift register
tmpy0 = y0;
y0 = y1;
y1 = y2;
y2 = y3;
y3 = y4;
y4 = tmpy0;
if (i_o == K_set[iKPC]) { // information bit
iKPC = iKPC + 1;
if (i_o == PC_set[iPC]) { // parity bit
iPC++;
input_encoder[i_o] = y0;
} else {
input_encoder[i_o] = message[iK];
y0 = y0 ^ message[iK];
iK++;
}
}
}
}
}
void srslte_polar_chanalloc_rx(const uint8_t* output_decoder,
uint8_t* message,
const uint16_t K,
const uint8_t nPC,
const uint16_t* K_set,
const uint16_t* PC_set)
{
uint16_t i_o = 0;
uint16_t iPC = 0;
uint16_t iK = 0;
for (uint16_t iKPC = 0; iKPC < K + nPC; iKPC++) {
i_o = K_set[iKPC]; // includes parity bits
if (i_o == PC_set[iPC]) { // skip
iPC = iPC + 1;
} else {
message[iK] = output_decoder[i_o];
iK = iK + 1;
}
}
}

@ -0,0 +1,315 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*!
* \file polar_code.c
* \brief Definition of the function that computes the polar code parameters including,
* message set (K_Set), the frozen set (F_set), and the parity check bits set (PC_Set)..
* \author Jesus Gomez (CTTC)
* \date 2020
*
* \copyright Software Radio Systems Limited
*
* The message and parity check sets provided by this functions are needed by
* the subchannel allocation block.
* The frozen bit set provided by this function is used by the polar decoder.
*/
#include "srslte/phy/utils/vector.h"
#include <stdint.h>
#include <stdlib.h>
#include "srslte/phy/fec/polar/polar_code.h"
#include "srslte/phy/utils/debug.h"
/*!
* Extracts the elements in x that are smaller than T or are in y.
* Returns the length of the output vector z.
*/
static uint16_t
setdiff_stable(const uint16_t* x, const uint16_t* y, uint16_t* z, const int T, const uint16_t len1, const uint16_t len2)
{
uint16_t o = 0;
int flag = 0;
for (int i = 0; i < len1; i++) {
// is x[i] in y ?
flag = 0;
if (x[i] <= T) {
flag = 1;
} else {
for (int j = 0; j < len2; j++) {
if (x[i] == y[j]) {
flag = 1;
break;
}
}
}
if (flag == 0) {
z[o] = x[i];
o++;
}
}
return o;
}
/*!
* Compares two uint16_t
*/
int cmpfunc(const void* a, const void* b)
{
const uint16_t ai = *(const uint16_t*)a;
const uint16_t bi = *(const uint16_t*)b;
if (ai < bi) {
return -1;
}
if (ai > bi) {
return 1;
}
return 0;
}
/*!
* Gets the codeword length N, nPC and nWmPC depending on the code parameters.
* Returns -1 if not supported configuration, otherwise returns 0.
*/
int get_code_params(srslte_polar_code_t* c, const uint16_t K, const uint16_t E, const uint8_t nMax)
{
// include here also npc and nwmPC computatoins
if (E > EMAX) {
ERROR("Rate-matched codeword size (E) not supported. Chose E<=8192\n");
return -1;
}
switch (nMax) {
case 9: // downlink
// iil = true
if (K < 36 || K > 164) {
ERROR("Codeblock length (K) not supported for downlink transmission, choose 165 > K > 35\n");
return -1;
}
break;
case 10:
// iil = false
if (K < 18 || (K > 25 && K < 31) || K > 1023) {
ERROR("Codeblock length (K) not supported for uplink transmission, choose K > 17 and K < 1024, "
"excluding 31 > K > 25\n");
return -1;
}
break;
default:
ERROR("nMax not supported choose 9 for downlink and 10 for uplink transmissions\n");
return -1;
}
// number of parity check bits (nPC) and parity check bits of minimum bandwidth nWmPC
uint8_t nPC = 0;
uint8_t nWmPC = 0;
if (K >= 18 && K <= 25) {
nPC = 3;
if (E > K + 189) {
nWmPC = 1;
}
}
if (K + nPC >= E) {
ERROR(" Rate-matched codeword length (E) not supported, choose E > %d\n", K + nPC);
return -1;
}
// determination of the codeword size (N)
// ceil(log2(E))
uint16_t tmpE = 0;
uint8_t e = 1;
for (; e <= eMAX; e++) {
tmpE = 1U << e; // 2^e
if (tmpE >= E) {
break;
}
}
uint8_t n1 = 0;
uint8_t e_1 = e - 1;
if ((8 * E <= 9 * (1U << e_1)) && (16 * K < 9 * E)) {
n1 = e - 1;
} else {
n1 = e;
}
// ceil(log2(K))
uint16_t tmpK = 0;
uint8_t k = 0;
for (; k <= 10; k++) {
tmpK = 1U << k; // 2^e
if (tmpK >= K) {
break;
}
}
uint8_t n2 = k + 3;
// min(n1, n2, n3)
uint8_t n = n1;
if (n2 < n1) {
n = n2;
}
if (nMax < n) {
n = nMax;
}
if (n < 5) {
n = 5;
}
uint16_t N = (1U << n);
if (K >= N) {
ERROR("Codeblock length (K) not supported, choose K < N\n");
return -1;
}
c->N = N;
c->n = n;
c->nPC = nPC;
c->nWmPC = nWmPC;
return 0;
}
void srslte_polar_code_free(srslte_polar_code_t* c)
{
if (c != NULL) {
free(c->F_set);
free(c->tmp_K_set); // also removes K_set
}
}
// allocate resources to the message set, frozen set and parity set, polar code
int srslte_polar_code_init(srslte_polar_code_t* c)
{
c->tmp_K_set = srslte_vec_u16_malloc(NMAX + 1); // +1 to mark the end with 1024
if (!c->tmp_K_set) {
perror("malloc");
exit(-1);
}
c->F_set = srslte_vec_u16_malloc(NMAX);
if (!c->F_set) {
free(c->tmp_K_set);
perror("malloc");
exit(-1);
}
return 0;
}
int srslte_polar_code_get(srslte_polar_code_t* c, uint16_t K, uint16_t E, uint8_t nMax)
{
if (c == NULL) {
return -1;
}
// check polar code parameters
if (get_code_params(c, K, E, nMax) == -1) {
return -1;
}
uint8_t nPC = c->nPC;
uint8_t nWmPC = c->nWmPC;
uint8_t n = c->n;
uint16_t N = c->N;
const uint16_t* blk_interleaver = get_blk_interleaver(n);
const uint16_t* mother_code = get_mother_code(n);
c->F_set_size = N - K - nPC;
c->K = K;
// Frozen bits due to Puncturing and Shortening.
int T = -1;
int tmp_F_set_size = N - E;
int N_th = 3 * N / 4;
if (tmp_F_set_size > 0) {
if (16 * K <= 7 * E) { // Puncturing
if (E >= N_th) {
T = N_th - (E >> 1U) - 1;
} else {
T = 9 * N / 16 - (E >> 2U);
}
memcpy(c->F_set,
blk_interleaver,
tmp_F_set_size * sizeof(uint16_t)); // The first (less reliable) after interleaving
} else { // Shortening
memcpy(c->F_set,
blk_interleaver + E,
tmp_F_set_size * sizeof(uint16_t)); // The first (less reliable) after interleaving
}
} else {
tmp_F_set_size = 0;
}
int tmp_K = setdiff_stable(mother_code, c->F_set, c->tmp_K_set, T, N, tmp_F_set_size);
// Select only the most reliable (message and parity)
c->K_set = c->tmp_K_set + tmp_K - K - nPC;
// take the nPC - nWmPC less reliable
for (int i = 0; i < nPC - nWmPC; i++) {
c->PC_set[i] = c->K_set[i];
}
// This only happens if K=18:25 and E=E+189+1:8192
// In this cases there is no puncturing or shortening
if (nWmPC == 1) {
if (K <= 21) {
c->PC_set[nPC - 1] = 252;
} else {
c->PC_set[nPC - 1] = 248;
}
}
// sorted K_set (includes parity bits)
qsort(c->K_set, c->K + c->nPC, sizeof(uint16_t), &cmpfunc);
// sorted PC_set
if (nPC > 0) {
qsort(c->PC_set, nPC, sizeof(uint16_t), &cmpfunc);
}
// create the sorted frozen set as the complement of sorted K_set
uint16_t i_k = 0;
uint16_t fvalue = 0;
uint16_t i_f = 0;
while (i_f < c->F_set_size) {
if (c->K_set[i_k] == fvalue) {
i_k++; // skip
fvalue++;
} else {
c->F_set[i_f] = fvalue;
fvalue++;
i_f++;
}
}
// mark the end of the sets (useful at subchannel allocation)
c->K_set[c->K + c->nPC] = 1024;
c->PC_set[c->nPC] = 1024;
return 0;
}

@ -36,12 +36,16 @@
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
/*! SSC Polar decoder with float LLR inputs. */ /*! SSC Polar decoder with float LLR inputs. */
static int decode_ssc_f(void* o, const float* symbols, uint8_t* data) static int decode_ssc_f(void* o,
const float* symbols,
uint8_t* data,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
srslte_polar_decoder_t* q = o; srslte_polar_decoder_t* q = o;
init_polar_decoder_ssc_f(q->ptr, symbols, data); init_polar_decoder_ssc_f(q->ptr, symbols, data, n, frozen_set, frozen_set_size);
polar_decoder_ssc_f(q->ptr, data); polar_decoder_ssc_f(q->ptr, data);
@ -49,11 +53,16 @@ static int decode_ssc_f(void* o, const float* symbols, uint8_t* data)
} }
/*! SSC Polar decoder with int16_t LLR inputs. */ /*! SSC Polar decoder with int16_t LLR inputs. */
static int decode_ssc_s(void* o, const int16_t* symbols, uint8_t* data) static int decode_ssc_s(void* o,
const int16_t* symbols,
uint8_t* data,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
srslte_polar_decoder_t* q = o; srslte_polar_decoder_t* q = o;
init_polar_decoder_ssc_s(q->ptr, symbols, data); init_polar_decoder_ssc_s(q->ptr, symbols, data, n, frozen_set, frozen_set_size);
polar_decoder_ssc_s(q->ptr, data); polar_decoder_ssc_s(q->ptr, data);
@ -61,11 +70,16 @@ static int decode_ssc_s(void* o, const int16_t* symbols, uint8_t* data)
} }
/*! SSC Polar decoder with int8_t LLR inputs. */ /*! SSC Polar decoder with int8_t LLR inputs. */
static int decode_ssc_c(void* o, const int8_t* symbols, uint8_t* data) static int decode_ssc_c(void* o,
const int8_t* symbols,
uint8_t* data,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
srslte_polar_decoder_t* q = o; srslte_polar_decoder_t* q = o;
init_polar_decoder_ssc_c(q->ptr, symbols, data); init_polar_decoder_ssc_c(q->ptr, symbols, data, n, frozen_set, frozen_set_size);
polar_decoder_ssc_c(q->ptr, data); polar_decoder_ssc_c(q->ptr, data);
@ -74,11 +88,16 @@ static int decode_ssc_c(void* o, const int8_t* symbols, uint8_t* data)
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
/*! SSC Polar decoder AVX2 with int8_t LLR inputs . */ /*! SSC Polar decoder AVX2 with int8_t LLR inputs . */
static int decode_ssc_c_avx2(void* o, const int8_t* symbols, uint8_t* data) static int decode_ssc_c_avx2(void* o,
const int8_t* symbols,
uint8_t* data,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
srslte_polar_decoder_t* q = o; srslte_polar_decoder_t* q = o;
init_polar_decoder_ssc_c_avx2(q->ptr, symbols, data); init_polar_decoder_ssc_c_avx2(q->ptr, symbols, data, n, frozen_set, frozen_set_size);
polar_decoder_ssc_c_avx2(q->ptr, data); polar_decoder_ssc_c_avx2(q->ptr, data);
@ -117,12 +136,12 @@ static void free_ssc_c_avx2(void* o)
#endif #endif
/*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with float LLR inputs. */ /*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with float LLR inputs. */
static int init_ssc_f(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t code_size_log, uint16_t frozen_set_size) static int init_ssc_f(srslte_polar_decoder_t* q)
{ {
q->decode_f = decode_ssc_f; q->decode_f = decode_ssc_f;
q->free = free_ssc_f; q->free = free_ssc_f;
if ((q->ptr = create_polar_decoder_ssc_f(frozen_set, code_size_log, frozen_set_size)) == NULL) { if ((q->ptr = create_polar_decoder_ssc_f(q->nMax)) == NULL) {
ERROR("create_polar_decoder_ssc_f failed\n"); ERROR("create_polar_decoder_ssc_f failed\n");
free_ssc_f(q); free_ssc_f(q);
return -1; return -1;
@ -131,12 +150,12 @@ static int init_ssc_f(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t
} }
/*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with uint16_t LLR inputs. */ /*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with uint16_t LLR inputs. */
static int init_ssc_s(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t code_size_log, uint16_t frozen_set_size) static int init_ssc_s(srslte_polar_decoder_t* q)
{ {
q->decode_s = decode_ssc_s; q->decode_s = decode_ssc_s;
q->free = free_ssc_s; q->free = free_ssc_s;
if ((q->ptr = create_polar_decoder_ssc_s(frozen_set, code_size_log, frozen_set_size)) == NULL) { if ((q->ptr = create_polar_decoder_ssc_s(q->nMax)) == NULL) {
ERROR("create_polar_decoder_ssc_s failed\n"); ERROR("create_polar_decoder_ssc_s failed\n");
free_ssc_s(q); free_ssc_s(q);
return -1; return -1;
@ -145,12 +164,12 @@ static int init_ssc_s(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t
} }
/*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with uint8_t LLR inputs. */ /*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with uint8_t LLR inputs. */
static int init_ssc_c(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t code_size_log, uint16_t frozen_set_size) static int init_ssc_c(srslte_polar_decoder_t* q)
{ {
q->decode_c = decode_ssc_c; q->decode_c = decode_ssc_c;
q->free = free_ssc_c; q->free = free_ssc_c;
if ((q->ptr = create_polar_decoder_ssc_c(frozen_set, code_size_log, frozen_set_size)) == NULL) { if ((q->ptr = create_polar_decoder_ssc_c(q->nMax)) == NULL) {
ERROR("create_polar_decoder_ssc_c failed\n"); ERROR("create_polar_decoder_ssc_c failed\n");
free_ssc_c(q); free_ssc_c(q);
return -1; return -1;
@ -161,13 +180,12 @@ static int init_ssc_c(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
/*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with uint8_t LLR inputs and AVX2 /*! Initializes a polar decoder structure to use the SSC polar decoder algorithm with uint8_t LLR inputs and AVX2
* instructions. */ * instructions. */
static int static int init_ssc_c_avx2(srslte_polar_decoder_t* q)
init_ssc_c_avx2(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t code_size_log, uint16_t frozen_set_size)
{ {
q->decode_c = decode_ssc_c_avx2; q->decode_c = decode_ssc_c_avx2;
q->free = free_ssc_c_avx2; q->free = free_ssc_c_avx2;
if ((q->ptr = create_polar_decoder_ssc_c_avx2(frozen_set, code_size_log, frozen_set_size)) == NULL) { if ((q->ptr = create_polar_decoder_ssc_c_avx2(q->nMax)) == NULL) {
ERROR("create_polar_decoder_ssc_c failed\n"); ERROR("create_polar_decoder_ssc_c failed\n");
free_ssc_c_avx2(q); free_ssc_c_avx2(q);
return -1; return -1;
@ -176,22 +194,19 @@ init_ssc_c_avx2(srslte_polar_decoder_t* q, uint16_t* frozen_set, uint16_t code_s
} }
#endif #endif
int srslte_polar_decoder_init(srslte_polar_decoder_t* q, int srslte_polar_decoder_init(srslte_polar_decoder_t* q, srslte_polar_decoder_type_t type, const uint8_t nMax)
srslte_polar_decoder_type_t type,
uint16_t code_size_log,
uint16_t* frozen_set,
uint16_t frozen_set_size)
{ {
q->nMax = nMax;
switch (type) { switch (type) {
case SRSLTE_POLAR_DECODER_SSC_F: case SRSLTE_POLAR_DECODER_SSC_F:
return init_ssc_f(q, frozen_set, code_size_log, frozen_set_size); return init_ssc_f(q);
case SRSLTE_POLAR_DECODER_SSC_S: case SRSLTE_POLAR_DECODER_SSC_S:
return init_ssc_s(q, frozen_set, code_size_log, frozen_set_size); return init_ssc_s(q);
case SRSLTE_POLAR_DECODER_SSC_C: case SRSLTE_POLAR_DECODER_SSC_C:
return init_ssc_c(q, frozen_set, code_size_log, frozen_set_size); return init_ssc_c(q);
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
case SRSLTE_POLAR_DECODER_SSC_C_AVX2: case SRSLTE_POLAR_DECODER_SSC_C_AVX2:
return init_ssc_c_avx2(q, frozen_set, code_size_log, frozen_set_size); return init_ssc_c_avx2(q);
#endif #endif
default: default:
ERROR("Decoder not implemented\n"); ERROR("Decoder not implemented\n");
@ -208,17 +223,44 @@ void srslte_polar_decoder_free(srslte_polar_decoder_t* q)
memset(q, 0, sizeof(srslte_polar_decoder_t)); memset(q, 0, sizeof(srslte_polar_decoder_t));
} }
int srslte_polar_decoder_decode_f(srslte_polar_decoder_t* q, const float* llr, uint8_t* data_decoded) int srslte_polar_decoder_decode_f(srslte_polar_decoder_t* q,
const float* llr,
uint8_t* data_decoded,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
return q->decode_f(q, llr, data_decoded); if (q->nMax >= n) {
return q->decode_f(q, llr, data_decoded, n, frozen_set, frozen_set_size);
}
return -1;
} }
int srslte_polar_decoder_decode_s(srslte_polar_decoder_t* q, const int16_t* llr, uint8_t* data_decoded) int srslte_polar_decoder_decode_s(srslte_polar_decoder_t* q,
const int16_t* llr,
uint8_t* data_decoded,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
return q->decode_s(q, llr, data_decoded); if (q->nMax >= n) {
return q->decode_s(q, llr, data_decoded, n, frozen_set, frozen_set_size);
}
return -1;
} }
int srslte_polar_decoder_decode_c(srslte_polar_decoder_t* q, const int8_t* llr, uint8_t* data_decoded) int srslte_polar_decoder_decode_c(srslte_polar_decoder_t* q,
const int8_t* llr,
uint8_t* data_decoded,
const uint8_t n,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
return q->decode_c(q, llr, data_decoded); if (q->nMax >= n) {
return q->decode_c(q, llr, data_decoded, n, frozen_set, frozen_set_size);
}
return -1;
} }

@ -22,6 +22,138 @@
*/ */
#include "polar_decoder_ssc_all.h" #include "polar_decoder_ssc_all.h"
#include "../utils_avx2.h" #include "../utils_avx2.h"
#include "srslte/phy/utils/vector.h"
/*!
* \brief Structure with pointers needed to obtain the node_type
*/
struct Tmp_node_type {
uint8_t* is_not_rate_0; /*!< \brief Pointers to a temporary buffer. */
uint8_t* is_rate_1; /*!< \brief Pointers to a temporary buffer. */
uint16_t* i_even; /*!< \brief Pointers to a temporary buffer. */
uint16_t* i_odd; /*!< \brief Pointers to a temporary buffer. */
};
void* create_tmp_node_type(const uint8_t nMax)
{
struct Tmp_node_type* tmp = NULL;
// allocate memory to the polar decoder instance
if ((tmp = malloc(sizeof(struct Tmp_node_type))) == NULL) {
return NULL;
}
SRSLTE_MEM_ZERO(tmp, struct Tmp_node_type, 1);
uint16_t max_code_size = (1U << nMax);
uint8_t nMax_1 = nMax - 1;
uint16_t max_code_half_size = (1U << nMax_1);
tmp->is_not_rate_0 = srslte_vec_u8_malloc(2 * max_code_size);
if (!tmp->is_not_rate_0) {
free(tmp);
perror("malloc");
return NULL;
}
tmp->is_rate_1 = tmp->is_not_rate_0 + max_code_size;
tmp->i_odd = srslte_vec_u16_malloc(max_code_half_size);
if (!tmp->i_odd) {
free(tmp->is_not_rate_0);
free(tmp);
perror("malloc");
return NULL;
}
tmp->i_even = srslte_vec_u16_malloc(max_code_half_size);
if (!tmp->i_even) {
free(tmp->is_not_rate_0);
free(tmp->i_odd);
free(tmp);
perror("malloc");
return NULL;
}
return tmp;
}
void delete_tmp_node_type(void* p)
{
struct Tmp_node_type* pp = p;
if (p != NULL) {
free(pp->i_even);
free(pp->i_odd);
free(pp->is_not_rate_0); // it also removes is_rate_1
free(pp);
}
}
int compute_node_type(void* p,
uint8_t** node_type,
const uint16_t* frozen_set,
const uint16_t code_size_log,
const uint16_t frozen_set_size)
{
struct Tmp_node_type* tmp = p;
if (p == NULL) {
return -1;
}
uint8_t s = 0; // stage
uint8_t* is_not_rate_0 = tmp->is_not_rate_0;
uint8_t* is_rate_1 = tmp->is_rate_1;
uint16_t* i_even = tmp->i_even;
uint16_t* i_odd = tmp->i_odd;
uint16_t code_size = (1U << code_size_log);
uint8_t code_size_log_1 = code_size_log - 1;
uint16_t code_half_size = (1U << code_size_log_1);
memset(i_even, 0, code_half_size);
memset(i_odd, 0, code_half_size);
for (uint16_t i = 0; i < code_half_size; i++) {
i_even[i] = 2 * i;
i_odd[i] = 2 * i + 1;
}
// node_type = is_not_rate_0_node: 0 if rate 0, 1 if not rate 0.
memset(is_not_rate_0, 1, code_size);
memset(is_rate_1, 1, code_size);
for (uint16_t i = 0; i < frozen_set_size; i++) {
is_not_rate_0[frozen_set[i]] = 0;
is_rate_1[frozen_set[i]] = 0;
}
s = 0;
for (uint16_t j = 0; j < code_size; j++) {
node_type[s][j] = 3 * is_not_rate_0[j]; // 0 if rate-0; 2 if rate-r; 3 if rate 1
}
uint16_t code_stage_size = 0;
uint16_t code_size_log_s = 0;
for (s = 1; s < code_size_log + 1; s++) {
code_size_log_s = code_size_log - s;
code_stage_size = (1U << code_size_log_s);
for (uint16_t j = 0; j < code_stage_size; j++) {
is_not_rate_0[j] = is_not_rate_0[i_even[j]] | is_not_rate_0[i_odd[j]]; // bitor
is_rate_1[j] = is_rate_1[i_even[j]] & is_rate_1[i_odd[j]]; // bitand
node_type[s][j] = 2 * is_not_rate_0[j] + is_rate_1[j]; // 0 if rate-0; 2 if rate-r; 3 if rate 1
}
}
#ifdef debug
for (s = 0; s < code_size_log + 1; s++) {
printf("Node types (%d): ", s);
code_stage_size = (1U << (code_size_log - s));
for (uint16_t j = 0; j < code_stage_size; j++) {
printf("%d ", node_type[s][j]);
}
printf("\n");
}
#endif
return 0;
}
int init_node_type(const uint16_t* frozen_set, struct Params* param) int init_node_type(const uint16_t* frozen_set, struct Params* param)
{ {
@ -35,21 +167,21 @@ int init_node_type(const uint16_t* frozen_set, struct Params* param)
uint16_t code_size = param->code_stage_size[param->code_size_log]; uint16_t code_size = param->code_stage_size[param->code_size_log];
uint16_t code_half_size = param->code_stage_size[param->code_size_log - 1]; uint16_t code_half_size = param->code_stage_size[param->code_size_log - 1];
is_not_rate_0 = aligned_alloc(SRSLTE_AVX2_B_SIZE, 2 * code_size * sizeof(uint8_t)); is_not_rate_0 = srslte_vec_u8_malloc(2 * code_size);
if (!is_not_rate_0) { if (!is_not_rate_0) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
is_rate_1 = is_not_rate_0 + code_size; is_rate_1 = is_not_rate_0 + code_size;
i_odd = malloc(code_half_size * sizeof(uint16_t)); i_odd = srslte_vec_u16_malloc(code_half_size);
if (!i_odd) { if (!i_odd) {
free(is_not_rate_0); free(is_not_rate_0);
perror("malloc"); perror("malloc");
return -1; return -1;
} }
i_even = malloc(code_half_size * sizeof(uint16_t)); i_even = srslte_vec_u16_malloc(code_half_size);
if (!i_even) { if (!i_even) {
free(is_not_rate_0); free(is_not_rate_0);
free(i_odd); free(i_odd);

@ -66,4 +66,31 @@ struct State {
*/ */
int init_node_type(const uint16_t* frozen_set, struct Params* param); int init_node_type(const uint16_t* frozen_set, struct Params* param);
/*!
* Computes node types for the decoding tree associated to the given frozen set.
* \param[in] p Pointer of a Tmp_node_type structure with the memory resources needed.
* \param[out] node_type Double pointer containing the node type at each stage of the decoding tree.
* \param[in] code_size_log \f$log_2\f$ of code size.
* \param[in] frozen_set The position of the frozen bits in the codeword.
* \param[in] frozen_set_size The size of the frozen set.
*/
int compute_node_type(void* p,
uint8_t** node_type,
const uint16_t* frozen_set,
const uint16_t code_size_log,
const uint16_t frozen_set_size);
/*!
* The "destructor" of the memory resources used to compute the node types.
* \param[in, out] p A pointer to the dismantled resources..
*/
void delete_tmp_node_type(void* p);
/*!
* Allocates memory resources for the computation of the node_type.
* \param[in] nMax \f$log_2\f$ of the maximum number of bits in the codeword.
* \return A pointer to a Tmp_node_type structure if the function executes correctly, NULL otherwise.
*/
void* create_tmp_node_type(const uint8_t nMax);
#endif // polar_decoder_SSC_ALL_H #endif // polar_decoder_SSC_ALL_H

@ -41,12 +41,13 @@
* \brief Describes an SSC polar decoder (8-bit version). * \brief Describes an SSC polar decoder (8-bit version).
*/ */
struct pSSC_c { struct pSSC_c {
int8_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */ int8_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */
int8_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */ int8_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */
uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */ uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */
struct Params* param; /*!< \brief Pointer to a Params structure. */ struct Params* param; /*!< \brief Pointer to a Params structure. */
struct State* state; /*!< \brief Pointer to a State. */ struct State* state; /*!< \brief Pointer to a State. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */ void* tmp_node_type; /*!< \brief Pointer to a Tmp_node_type. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */
void (*f)(const int8_t* x, const int8_t* y, int8_t* z, const uint16_t len); /*!< \brief Pointer to the function-f. */ void (*f)(const int8_t* x, const int8_t* y, int8_t* z, const uint16_t len); /*!< \brief Pointer to the function-f. */
void (*g)(const uint8_t* b, void (*g)(const uint8_t* b,
const int8_t* x, const int8_t* x,
@ -94,7 +95,12 @@ static void rate_1_node(void* p, uint8_t* message);
*/ */
static void rate_r_node(void* p, uint8_t* message); static void rate_r_node(void* p, uint8_t* message);
int init_polar_decoder_ssc_c(void* p, const int8_t* input_llr, uint8_t* data_decoded) int init_polar_decoder_ssc_c(void* p,
const int8_t* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
struct pSSC_c* pp = p; struct pSSC_c* pp = p;
@ -102,9 +108,9 @@ int init_polar_decoder_ssc_c(void* p, const int8_t* input_llr, uint8_t* data_dec
return -1; return -1;
} }
uint8_t code_size_log = pp->param->code_size_log; // code_size_log. pp->param->code_size_log = code_size_log;
int16_t code_size = pp->param->code_stage_size[code_size_log]; int16_t code_size = pp->param->code_stage_size[code_size_log];
int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1]; int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1];
// Initializes the data_decoded_vector to all zeros // Initializes the data_decoded_vector to all zeros
memset(data_decoded, 0, code_size); memset(data_decoded, 0, code_size);
@ -125,6 +131,12 @@ int init_polar_decoder_ssc_c(void* p, const int8_t* input_llr, uint8_t* data_dec
} }
pp->state->flag_finished = false; pp->state->flag_finished = false;
// frozen_set
pp->param->frozen_set_size = frozen_set_size;
// computes the node types for the decoding tree
compute_node_type(pp->tmp_node_type, pp->param->node_type, frozen_set, code_size_log, frozen_set_size);
return 0; return 0;
} }
@ -144,23 +156,46 @@ void delete_polar_decoder_ssc_c(void* p)
struct pSSC_c* pp = p; struct pSSC_c* pp = p;
if (p != NULL) { if (p != NULL) {
free(pp->llr0[0]); // remove LLR buffer. if (pp->llr0) {
free(pp->llr0); if (pp->llr0[0]) {
free(pp->llr1); free(pp->llr0[0]); // remove LLR buffer.
free(pp->param->node_type[0]); }
free(pp->param->node_type); free(pp->llr0);
free(pp->est_bit); // remove estbits buffer. }
free(pp->param->code_stage_size); if (pp->llr1) {
free(pp->param); free(pp->llr1);
free(pp->state->active_node_per_stage); }
free(pp->state); if (pp->param) {
srslte_polar_encoder_free(pp->enc); if (pp->param->node_type) {
free(pp->enc); if (pp->param->node_type[0]) {
free(pp->param->node_type[0]);
}
free(pp->param->node_type);
}
if (pp->param->code_stage_size) {
free(pp->param->code_stage_size);
}
free(pp->param);
}
if (pp->est_bit) {
free(pp->est_bit); // remove estbits buffer.
}
if (pp->state) {
free(pp->state->active_node_per_stage);
free(pp->state);
}
if (pp->enc) {
srslte_polar_encoder_free(pp->enc);
free(pp->enc);
}
if (pp->tmp_node_type) {
delete_tmp_node_type(pp->tmp_node_type);
}
free(pp); free(pp);
} }
} }
void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_log, const uint16_t frozen_set_size) void* create_polar_decoder_ssc_c(const uint8_t nMax)
{ {
struct pSSC_c* pp = NULL; // pointer to the polar decoder instance struct pSSC_c* pp = NULL; // pointer to the polar decoder instance
@ -168,6 +203,7 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
if ((pp = malloc(sizeof(struct pSSC_c))) == NULL) { if ((pp = malloc(sizeof(struct pSSC_c))) == NULL) {
return NULL; return NULL;
} }
SRSLTE_MEM_ZERO(pp, struct pSSC_c, 1);
// set functions // set functions
pp->f = srslte_vec_function_f_ccc; pp->f = srslte_vec_function_f_ccc;
@ -176,33 +212,28 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
pp->hard_bit = srslte_vec_hard_bit_cc; pp->hard_bit = srslte_vec_hard_bit_cc;
// encoder of maximum size // encoder of maximum size
if ((pp->enc = malloc(sizeof(srslte_polar_encoder_t))) == NULL) { if ((pp->enc = SRSLTE_MEM_ALLOC(srslte_polar_encoder_t, 1)) == NULL) {
free(pp); delete_polar_decoder_ssc_c(pp);
return NULL; return NULL;
} }
srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_PIPELINED, code_size_log); srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_PIPELINED, nMax);
// algorithm constants/parameters // algorithm constants/parameters
if ((pp->param = malloc(sizeof(struct Params))) == NULL) { if ((pp->param = SRSLTE_MEM_ALLOC(struct Params, 1)) == NULL) {
free(pp->enc); delete_polar_decoder_ssc_c(pp);
free(pp);
return NULL; return NULL;
} }
if ((pp->param->code_stage_size = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) { if ((pp->param->code_stage_size = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
free(pp->param); delete_polar_decoder_ssc_c(pp);
free(pp->enc);
free(pp);
return NULL; return NULL;
} }
pp->param->code_stage_size[0] = 1; pp->param->code_stage_size[0] = 1;
for (uint8_t i = 1; i < code_size_log + 1; i++) { for (uint8_t i = 1; i < nMax + 1; i++) {
pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1]; pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1];
} }
pp->param->code_size_log = code_size_log;
// state -- initialized in polar_decoder_ssc_init // state -- initialized in polar_decoder_ssc_init
if ((pp->state = malloc(sizeof(struct State))) == NULL) { if ((pp->state = malloc(sizeof(struct State))) == NULL) {
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
@ -211,7 +242,7 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
free(pp); free(pp);
return NULL; return NULL;
} }
if ((pp->state->active_node_per_stage = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) { if ((pp->state->active_node_per_stage = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
free(pp->state); free(pp->state);
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
free(pp->param); free(pp->param);
@ -221,13 +252,13 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
} }
// allocates memory for estimated bits per stage // allocates memory for estimated bits per stage
uint16_t est_bits_size = pp->param->code_stage_size[code_size_log]; uint16_t est_bits_size = pp->param->code_stage_size[nMax];
pp->est_bit = aligned_alloc(SRSLTE_AVX2_B_SIZE, est_bits_size); // every 32 chars are aligned pp->est_bit = srslte_vec_u8_malloc(est_bits_size); // every 32 chars are aligned
// allocate memory for LLR pointers. // allocate memory for LLR pointers.
pp->llr0 = malloc((code_size_log + 1) * sizeof(int8_t*)); pp->llr0 = malloc((nMax + 1) * sizeof(int8_t*));
pp->llr1 = malloc((code_size_log + 1) * sizeof(int8_t*)); pp->llr1 = malloc((nMax + 1) * sizeof(int8_t*));
// There are LLR buffers for n = 0 to n = code_size_log. Each with size 2^n. Thus, // There are LLR buffers for n = 0 to n = code_size_log. Each with size 2^n. Thus,
// the total memory needed is 2^(n+1)-1. // the total memory needed is 2^(n+1)-1.
@ -237,10 +268,10 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
// i.e. in a SIMD instruction we can load 2^(n_simd_llr) LLR values // i.e. in a SIMD instruction we can load 2^(n_simd_llr) LLR values
// then the memory for stages s >= n_simd_llr - 1 is aligned. // then the memory for stages s >= n_simd_llr - 1 is aligned.
// but only the operations at stages s > n_simd_llr have all the inputs aligned. // but only the operations at stages s > n_simd_llr have all the inputs aligned.
uint8_t n_llr_all_stages = code_size_log + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages. uint8_t n_llr_all_stages = nMax + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages.
uint16_t llr_all_stages = 1U << n_llr_all_stages; uint16_t llr_all_stages = 1U << n_llr_all_stages;
pp->llr0[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(int8_t)); // 32*8=256 pp->llr0[0] = srslte_vec_i8_malloc(llr_all_stages); // 32*8=256
// allocate memory to the polar decoder instance // allocate memory to the polar decoder instance
if (pp->llr0[0] == NULL) { if (pp->llr0[0] == NULL) {
free(pp->est_bit); free(pp->est_bit);
@ -254,18 +285,17 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
// initialize all LLR pointers // initialize all LLR pointers
pp->llr1[0] = pp->llr0[0] + 1; pp->llr1[0] = pp->llr0[0] + 1;
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->llr0[s] = pp->llr0[0] + pp->param->code_stage_size[s]; pp->llr0[s] = pp->llr0[0] + pp->param->code_stage_size[s];
pp->llr1[s] = pp->llr0[0] + pp->param->code_stage_size[s] + pp->param->code_stage_size[s - 1]; pp->llr1[s] = pp->llr0[0] + pp->param->code_stage_size[s] + pp->param->code_stage_size[s - 1];
} }
// allocate memory for node type pointers, one per stage. // allocate memory for node type pointers, one per stage.
pp->param->frozen_set_size = frozen_set_size; pp->param->node_type = malloc((nMax + 1) * sizeof(uint8_t*));
pp->param->node_type = malloc((code_size_log + 1) * sizeof(uint8_t*));
// allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N. // allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N.
// Thus, same size as LLRs all stages. // Thus, same size as LLRs all stages.
pp->param->node_type[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(uint8_t)); // 32*8=256 pp->param->node_type[0] = srslte_vec_u8_malloc(llr_all_stages); // 32*8=256
if (pp->param->node_type[0] == NULL) { if (pp->param->node_type[0] == NULL) {
free(pp->param->node_type); free(pp->param->node_type);
@ -279,11 +309,24 @@ void* create_polar_decoder_ssc_c(uint16_t* frozen_set, const uint8_t code_size_l
} }
// initialize all node type pointers. (stage 0 is the first, opposite to LLRs) // initialize all node type pointers. (stage 0 is the first, opposite to LLRs)
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[code_size_log - s + 1]; pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[nMax - s + 1];
} }
init_node_type(frozen_set, pp->param); // memory allocation to compute node_type
pp->tmp_node_type = create_tmp_node_type(nMax);
if (pp->tmp_node_type == NULL) {
free(pp->param->node_type[0]);
free(pp->llr0[0]);
free(pp->llr1);
free(pp->llr0);
free(pp->state);
free(pp->param->code_stage_size);
free(pp->param);
free(pp->enc);
free(pp);
return NULL;
}
return pp; return pp;
} }

@ -30,13 +30,10 @@
* This function is exactly the same as the one for the floating-point version. * This function is exactly the same as the one for the floating-point version.
* Note, however, that it works with a different pSSC structure (different function pointers * Note, however, that it works with a different pSSC structure (different function pointers
* pSSC::f, pSSC::f, pSSC::g, pSSC::xor and pSSC::hard_bit). * pSSC::f, pSSC::f, pSSC::g, pSSC::xor and pSSC::hard_bit).
* * \param[in] nMax \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set The position of the frozen bits in the codeword.
* \param[in] frozen_set_size Number of frozen bits.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \return A pointer to a pSSC structure if the function executes correctly, NULL otherwise. * \return A pointer to a pSSC structure if the function executes correctly, NULL otherwise.
*/ */
void* create_polar_decoder_ssc_c(uint16_t* frozen_set, uint8_t code_size_log, uint16_t frozen_set_size); void* create_polar_decoder_ssc_c(uint8_t nMax);
/*! /*!
* The (8-bit) polar decoder SSC "destructor": it frees all the resources allocated to the decoder. * The (8-bit) polar decoder SSC "destructor": it frees all the resources allocated to the decoder.
@ -51,9 +48,17 @@ void delete_polar_decoder_ssc_c(void* p);
* \param[in, out] p A void pointer used to declare a pSSC structure. * \param[in, out] p A void pointer used to declare a pSSC structure.
* \param[in] llr LLRs for the new codeword. * \param[in] llr LLRs for the new codeword.
* \param[out] data_decoded Pointer to the decoded message. * \param[out] data_decoded Pointer to the decoded message.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set The position of the frozen bits in increasing order.
* \param[in] frozen_set_size The size of the frozen_set.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
int init_polar_decoder_ssc_c(void* p, const int8_t* llr, uint8_t* data_decoded); int init_polar_decoder_ssc_c(void* p,
const int8_t* llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
/*! /*!
* Decodes a data message from a 8 bit resolution codeword with the specified decoder. Note that * Decodes a data message from a 8 bit resolution codeword with the specified decoder. Note that

@ -42,12 +42,13 @@ struct StateAVX2 {
* \brief Describes an SSC polar decoder (8-bit version). * \brief Describes an SSC polar decoder (8-bit version).
*/ */
struct pSSC_c_avx2 { struct pSSC_c_avx2 {
int8_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */ int8_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */
int8_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */ int8_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */
uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */ uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */
struct Params* param; /*!< \brief Pointer to a Params structure. */ struct Params* param; /*!< \brief Pointer to a Params structure. */
struct StateAVX2* state; /*!< \brief Pointer to a State. */ struct StateAVX2* state; /*!< \brief Pointer to a State. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */ void* tmp_node_type; /*!< \brief Pointer to a Tmp_node_type. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */
void (*f)(const int8_t* x, const int8_t* y, int8_t* z, const uint16_t len); /*!< \brief Pointer to the function-f. */ void (*f)(const int8_t* x, const int8_t* y, int8_t* z, const uint16_t len); /*!< \brief Pointer to the function-f. */
void (*g)(const uint8_t* b, void (*g)(const uint8_t* b,
const int8_t* x, const int8_t* x,
@ -96,22 +97,45 @@ void delete_polar_decoder_ssc_c_avx2(void* p)
struct pSSC_c_avx2* pp = p; struct pSSC_c_avx2* pp = p;
if (p != NULL) { if (p != NULL) {
free(pp->llr0[0]); // remove LLR buffer. if (pp->llr0[0]) {
free(pp->llr0); free(pp->llr0[0]); // remove LLR buffer.
free(pp->llr1); }
free(pp->param->node_type[0]); if (pp->llr0) {
free(pp->param->node_type); free(pp->llr0);
free(pp->est_bit); // remove estbits buffer. }
free(pp->param->code_stage_size); if (pp->llr1) {
free(pp->param); free(pp->llr1);
free(pp->state); }
srslte_polar_encoder_free(pp->enc); if (pp->param) {
free(pp->enc); if (pp->param->node_type[0]) {
free(pp->param->node_type[0]);
}
if (pp->param->node_type) {
free(pp->param->node_type);
}
if (pp->param->code_stage_size) {
free(pp->param->code_stage_size);
}
free(pp->param);
}
if (pp->est_bit) {
free(pp->est_bit); // remove estbits buffer.
}
if (pp->state) {
free(pp->state);
}
if (pp->enc) {
srslte_polar_encoder_free(pp->enc);
free(pp->enc);
}
if (pp->tmp_node_type) {
delete_tmp_node_type(pp->tmp_node_type);
}
free(pp); free(pp);
} }
} }
void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_size_log, const uint16_t frozen_set_size) void* create_polar_decoder_ssc_c_avx2(const uint8_t nMax)
{ {
struct pSSC_c_avx2* pp = NULL; // pointer to the polar decoder instance struct pSSC_c_avx2* pp = NULL; // pointer to the polar decoder instance
// allocate memory to the polar decoder instance // allocate memory to the polar decoder instance
@ -131,7 +155,7 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
return NULL; return NULL;
} }
srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_AVX2, code_size_log); srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_AVX2, nMax);
// algorithm constants/parameters // algorithm constants/parameters
if ((pp->param = malloc(sizeof(struct Params))) == NULL) { if ((pp->param = malloc(sizeof(struct Params))) == NULL) {
@ -140,8 +164,7 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
return NULL; return NULL;
} }
printf("-- code_stage_size=%d;\n", code_size_log + 1); if ((pp->param->code_stage_size = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
if ((pp->param->code_stage_size = srslte_vec_u16_malloc(code_size_log + 1)) == NULL) {
free(pp->param); free(pp->param);
free(pp->enc); free(pp->enc);
free(pp); free(pp);
@ -149,12 +172,10 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
} }
pp->param->code_stage_size[0] = 1; pp->param->code_stage_size[0] = 1;
for (uint8_t i = 1; i < code_size_log + 1; i++) { for (uint8_t i = 1; i < nMax + 1; i++) {
pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1]; pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1];
} }
pp->param->code_size_log = code_size_log;
// state -- initialized in polar_decoder_ssc_init // state -- initialized in polar_decoder_ssc_init
if ((pp->state = malloc(sizeof(struct StateAVX2))) == NULL) { if ((pp->state = malloc(sizeof(struct StateAVX2))) == NULL) {
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
@ -166,13 +187,13 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
// allocates memory for estimated bits per stage // allocates memory for estimated bits per stage
// allocates extra SRSLTE_AVX2_B_SIZE bytes to allow store the output of 256-bit instructions // allocates extra SRSLTE_AVX2_B_SIZE bytes to allow store the output of 256-bit instructions
int est_bit_size = pp->param->code_stage_size[code_size_log] + SRSLTE_AVX2_B_SIZE; int est_bit_size = pp->param->code_stage_size[nMax] + SRSLTE_AVX2_B_SIZE;
pp->est_bit = aligned_alloc(SRSLTE_AVX2_B_SIZE, est_bit_size); // every 32 chars are aligned pp->est_bit = srslte_vec_u8_malloc(est_bit_size); // every 32 chars are aligned
// allocate memory for LLR pointers. // allocate memory for LLR pointers.
pp->llr0 = malloc((code_size_log + 1) * sizeof(int8_t*)); pp->llr0 = malloc((nMax + 1) * sizeof(int8_t*));
pp->llr1 = malloc((code_size_log + 1) * sizeof(int8_t*)); pp->llr1 = malloc((nMax + 1) * sizeof(int8_t*));
// LLR MEMORY NOT ALIGNED FOR LLR_BUFFERS_SIZE < SRSLTE_SIMB_LLR_ALIGNED // LLR MEMORY NOT ALIGNED FOR LLR_BUFFERS_SIZE < SRSLTE_SIMB_LLR_ALIGNED
@ -180,7 +201,7 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
// operation, the second half of the output vector needs to be moved to the next // operation, the second half of the output vector needs to be moved to the next
// aligned position. This extra operation may incur more overhead that the gain of aligned memory. // aligned position. This extra operation may incur more overhead that the gain of aligned memory.
uint8_t n_llr_all_stages = code_size_log + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages. uint8_t n_llr_all_stages = nMax + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages.
uint16_t llr_all_stages = 1U << n_llr_all_stages; uint16_t llr_all_stages = 1U << n_llr_all_stages;
// Reserve at least SRSLTE_AVX2_B_SIZE bytes for each stage, so that there is space for the output // Reserve at least SRSLTE_AVX2_B_SIZE bytes for each stage, so that there is space for the output
@ -188,65 +209,63 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
// llr1 (second half) of lower stages is not aligned. // llr1 (second half) of lower stages is not aligned.
uint16_t llr_all_stages_avx2 = llr_all_stages; uint16_t llr_all_stages_avx2 = llr_all_stages;
if (code_size_log >= 5) { if (nMax >= 5) {
llr_all_stages_avx2 += SRSLTE_AVX2_B_SIZE * 5; llr_all_stages_avx2 += SRSLTE_AVX2_B_SIZE * 5;
} else { } else {
llr_all_stages_avx2 += (code_size_log + 1) * SRSLTE_AVX2_B_SIZE; llr_all_stages_avx2 += (nMax + 1) * SRSLTE_AVX2_B_SIZE;
} }
// add extra SRSLTE_AVX2_B_SIZE llrs positions for hard_bit functions on the last bits have // add extra SRSLTE_AVX2_B_SIZE llrs positions for hard_bit functions on the last bits have
// access to allocated memory // access to allocated memory
llr_all_stages_avx2 += SRSLTE_AVX2_B_SIZE; llr_all_stages_avx2 += SRSLTE_AVX2_B_SIZE;
pp->llr0[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages_avx2 * sizeof(int8_t)); // 32*8=256 pp->llr0[0] = srslte_vec_i8_malloc(llr_all_stages_avx2); // 32*8=256
// allocate memory to the polar decoder instance // allocate memory to the polar decoder instance
if (pp->llr0[0] == NULL) { if (pp->llr0[0] == NULL) {
free(pp->est_bit); delete_polar_decoder_ssc_c_avx2(pp);
free(pp->state);
free(pp->param->code_stage_size);
free(pp->param);
free(pp->enc);
free(pp);
return NULL; return NULL;
} }
pp->llr1[0] = pp->llr0[0] + 1; pp->llr1[0] = pp->llr0[0] + 1;
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->llr0[s] = pp->llr0[s - 1] + max(SRSLTE_AVX2_B_SIZE, pp->param->code_stage_size[s - 1]); pp->llr0[s] = pp->llr0[s - 1] + max(SRSLTE_AVX2_B_SIZE, pp->param->code_stage_size[s - 1]);
pp->llr1[s] = pp->llr0[s] + pp->param->code_stage_size[s - 1]; pp->llr1[s] = pp->llr0[s] + pp->param->code_stage_size[s - 1];
} }
// allocate memory for node type pointers, one per stage. // allocate memory for node type pointers, one per stage.
pp->param->frozen_set_size = frozen_set_size; pp->param->node_type = SRSLTE_MEM_ALLOC(uint8_t*, nMax + 1);
pp->param->node_type = malloc((code_size_log + 1) * sizeof(uint8_t*));
// allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N. // allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N.
// Thus, same size as LLRs all stages. // Thus, same size as LLRs all stages.
pp->param->node_type[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(uint8_t)); // 32*8=256 pp->param->node_type[0] = srslte_vec_u8_malloc(llr_all_stages); // 32*8=256
if (pp->param->node_type[0] == NULL) { if (pp->param->node_type[0] == NULL) {
free(pp->param->node_type); delete_polar_decoder_ssc_c_avx2(pp);
free(pp->est_bit);
free(pp->state);
free(pp->param->code_stage_size);
free(pp->param);
free(pp->enc);
free(pp);
return NULL; return NULL;
} }
// initialize all node type pointers. (stage 0 is the first, opposite to LLRs) // initialize all node type pointers. (stage 0 is the first, opposite to LLRs)
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[code_size_log - s + 1]; pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[nMax - s + 1];
} }
init_node_type(frozen_set, pp->param); // memory allocation to compute node_type
pp->tmp_node_type = create_tmp_node_type(nMax);
if (pp->tmp_node_type == NULL) {
delete_polar_decoder_ssc_c_avx2(pp);
return NULL;
}
return pp; return pp;
} }
int init_polar_decoder_ssc_c_avx2(void* p, const int8_t* input_llr, uint8_t* data_decoded) int init_polar_decoder_ssc_c_avx2(void* p,
const int8_t* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
struct pSSC_c_avx2* pp = p; struct pSSC_c_avx2* pp = p;
@ -254,9 +273,9 @@ int init_polar_decoder_ssc_c_avx2(void* p, const int8_t* input_llr, uint8_t* dat
return -1; return -1;
} }
uint8_t code_size_log = pp->param->code_size_log; pp->param->code_size_log = code_size_log;
int16_t code_size = pp->param->code_stage_size[code_size_log]; int16_t code_size = pp->param->code_stage_size[code_size_log];
int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1]; int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1];
// Initializes the data_decoded_vector to all zeros // Initializes the data_decoded_vector to all zeros
memset(data_decoded, 0, code_size); memset(data_decoded, 0, code_size);
@ -273,6 +292,12 @@ int init_polar_decoder_ssc_c_avx2(void* p, const int8_t* input_llr, uint8_t* dat
pp->state->stage = code_size_log + 1; // start from the only one node at the last stage + 1. pp->state->stage = code_size_log + 1; // start from the only one node at the last stage + 1.
pp->state->bit_pos = 0; pp->state->bit_pos = 0;
// frozen_set
pp->param->frozen_set_size = frozen_set_size;
// computes the node types for the decoding tree
compute_node_type(pp->tmp_node_type, pp->param->node_type, frozen_set, code_size_log, frozen_set_size);
return 0; return 0;
} }
@ -309,9 +334,6 @@ static void simplified_node(struct pSSC_c_avx2* p)
uint16_t stage_size = pp->param->code_stage_size[stage]; uint16_t stage_size = pp->param->code_stage_size[stage];
uint16_t stage_half_size = 0; uint16_t stage_half_size = 0;
if (stage > 0) {
stage_half_size = pp->param->code_stage_size[stage - 1];
}
switch (pp->param->node_type[stage][bit_pos]) { switch (pp->param->node_type[stage][bit_pos]) {
@ -327,6 +349,8 @@ static void simplified_node(struct pSSC_c_avx2* p)
case RATE_R: case RATE_R:
stage_half_size = pp->param->code_stage_size[stage - 1];
// compute_function_f(pp);
pp->f(pp->llr0[stage], pp->llr1[stage], pp->llr0[stage - 1], stage_half_size); pp->f(pp->llr0[stage], pp->llr1[stage], pp->llr0[stage - 1], stage_half_size);
// move to the child node to the left (up) of the tree. // move to the child node to the left (up) of the tree.

@ -28,12 +28,10 @@
/*! /*!
* Creates an SSC polar decoder structure of type pSSC_c_avx2, and allocates memory for the decoding buffers. * Creates an SSC polar decoder structure of type pSSC_c_avx2, and allocates memory for the decoding buffers.
* *
* \param[in] frozen_set The position of the frozen bits in the codeword. * \param[in] nMax \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set_size Number of frozen bits.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \return A pointer to a pSSC_c_avx2 structure if the function executes correctly, NULL otherwise. * \return A pointer to a pSSC_c_avx2 structure if the function executes correctly, NULL otherwise.
*/ */
void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, uint8_t code_size_log, uint16_t frozen_set_size); void* create_polar_decoder_ssc_c_avx2(uint8_t nMax);
/*! /*!
* The (8-bit, avx2) polar decoder SSC "destructor": it frees all the resources allocated to the decoder. * The (8-bit, avx2) polar decoder SSC "destructor": it frees all the resources allocated to the decoder.
@ -48,9 +46,17 @@ void delete_polar_decoder_ssc_c_avx2(void* p);
* \param[in, out] p A void pointer used to declare a pSSC_c_avx2 structure. * \param[in, out] p A void pointer used to declare a pSSC_c_avx2 structure.
* \param[in] llr LLRs for the new codeword. * \param[in] llr LLRs for the new codeword.
* \param[out] data_decoded Pointer to the decoded message. * \param[out] data_decoded Pointer to the decoded message.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set The position of the frozen bits in the codeword.
* \param[in] frozen_set_size Number of frozen bits.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
int init_polar_decoder_ssc_c_avx2(void* p, const int8_t* llr, uint8_t* data_decoded); int init_polar_decoder_ssc_c_avx2(void* p,
const int8_t* llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
/*! /*!
* Decodes a data message from a 8 bit resolution codeword with the specified decoder. Note that * Decodes a data message from a 8 bit resolution codeword with the specified decoder. Note that

@ -32,12 +32,13 @@
* \brief Describes an SSC polar decoder (float version). * \brief Describes an SSC polar decoder (float version).
*/ */
struct pSSC_f { struct pSSC_f {
float** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */ float** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */
float** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */ float** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */
uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */ uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */
struct Params* param; /*!< \brief Pointer to a Params structure. */ struct Params* param; /*!< \brief Pointer to a Params structure. */
struct State* state; /*!< \brief Pointer to a State. */ struct State* state; /*!< \brief Pointer to a State. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */ void* tmp_node_type; /*!< \brief Pointer to a Tmp_node_type. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */
void (*f)(const float* x, const float* y, float* z, const uint16_t len); /*!< \brief Pointer to the function-f. */ void (*f)(const float* x, const float* y, float* z, const uint16_t len); /*!< \brief Pointer to the function-f. */
void (*g)(const uint8_t* b, void (*g)(const uint8_t* b,
const float* x, const float* x,
@ -85,17 +86,22 @@ static void rate_1_node(void* p, uint8_t* message);
*/ */
static void rate_r_node(void* p, uint8_t* message); static void rate_r_node(void* p, uint8_t* message);
int init_polar_decoder_ssc_f(void* p, const float* input_llr, uint8_t* data_decoded) int init_polar_decoder_ssc_f(void* p,
const float* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
struct pSSC_f* pp = p;
if (p == NULL) { if (p == NULL) {
return -1; return -1;
} }
struct pSSC_f* pp = p;
uint8_t code_size_log = pp->param->code_size_log; pp->param->code_size_log = code_size_log;
int16_t code_size = pp->param->code_stage_size[code_size_log]; int16_t code_size = pp->param->code_stage_size[code_size_log];
int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1]; int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1];
// Initializes the data_decoded_vector to all zeros // Initializes the data_decoded_vector to all zeros
memset(data_decoded, 0, code_size); memset(data_decoded, 0, code_size);
@ -116,6 +122,12 @@ int init_polar_decoder_ssc_f(void* p, const float* input_llr, uint8_t* data_deco
} }
pp->state->flag_finished = false; pp->state->flag_finished = false;
// frozen_set
pp->param->frozen_set_size = frozen_set_size;
// computes the node types for the decoding tree
compute_node_type(pp->tmp_node_type, pp->param->node_type, frozen_set, code_size_log, frozen_set_size);
return 0; return 0;
} }
@ -146,11 +158,13 @@ void delete_polar_decoder_ssc_f(void* p)
free(pp->state); free(pp->state);
srslte_polar_encoder_free(pp->enc); srslte_polar_encoder_free(pp->enc);
free(pp->enc); free(pp->enc);
// free(pp->frozen_set); // this is not SSC responsibility.
delete_tmp_node_type(pp->tmp_node_type);
free(pp); free(pp);
} }
} }
void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_log, const uint16_t frozen_set_size) void* create_polar_decoder_ssc_f(const uint8_t nMax)
{ {
struct pSSC_f* pp = NULL; // pointer to the polar decoder instance struct pSSC_f* pp = NULL; // pointer to the polar decoder instance
@ -170,7 +184,7 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
free(pp); free(pp);
return NULL; return NULL;
} }
srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_PIPELINED, code_size_log); srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_PIPELINED, nMax);
// algorithm constants/parameters // algorithm constants/parameters
if ((pp->param = malloc(sizeof(struct Params))) == NULL) { if ((pp->param = malloc(sizeof(struct Params))) == NULL) {
@ -179,7 +193,7 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
return NULL; return NULL;
} }
if ((pp->param->code_stage_size = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) { if ((pp->param->code_stage_size = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
free(pp->param); free(pp->param);
free(pp->enc); free(pp->enc);
free(pp); free(pp);
@ -187,12 +201,10 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
} }
pp->param->code_stage_size[0] = 1; pp->param->code_stage_size[0] = 1;
for (uint8_t i = 1; i < code_size_log + 1; i++) { for (uint8_t i = 1; i < nMax + 1; i++) {
pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1]; pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1];
} }
pp->param->code_size_log = code_size_log;
// state -- initialized in polar_decoder_ssc_init // state -- initialized in polar_decoder_ssc_init
if ((pp->state = malloc(sizeof(struct State))) == NULL) { if ((pp->state = malloc(sizeof(struct State))) == NULL) {
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
@ -201,7 +213,7 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
free(pp); free(pp);
return NULL; return NULL;
} }
if ((pp->state->active_node_per_stage = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) { if ((pp->state->active_node_per_stage = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
free(pp->state); free(pp->state);
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
free(pp->param); free(pp->param);
@ -211,13 +223,13 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
} }
// allocates memory for estimated bits per stage // allocates memory for estimated bits per stage
uint16_t est_bits_size = pp->param->code_stage_size[code_size_log]; uint16_t est_bits_size = pp->param->code_stage_size[nMax];
pp->est_bit = aligned_alloc(SRSLTE_AVX2_B_SIZE, est_bits_size); // every 32 chars are aligned pp->est_bit = srslte_vec_u8_malloc(est_bits_size); // every 32 chars are aligned
// allocate memory for LLR pointers. // allocate memory for LLR pointers.
pp->llr0 = malloc((code_size_log + 1) * sizeof(float*)); pp->llr0 = malloc((nMax + 1) * sizeof(float*));
pp->llr1 = malloc((code_size_log + 1) * sizeof(float*)); pp->llr1 = malloc((nMax + 1) * sizeof(float*));
// There are LLR buffers for n = 0 to n = code_size_log. Each with size 2^n. Thus, // There are LLR buffers for n = 0 to n = code_size_log. Each with size 2^n. Thus,
// the total memory needed is 2^(n+1)-1. // the total memory needed is 2^(n+1)-1.
@ -227,10 +239,10 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
// i.e. in a SIMD instruction we can load 2^(n_simd_llr) LLR values // i.e. in a SIMD instruction we can load 2^(n_simd_llr) LLR values
// then the memory for stages s >= n_simd_llr - 1 is aligned. // then the memory for stages s >= n_simd_llr - 1 is aligned.
// but only the operations at stages s > n_simd_llr have all the inputs aligned. // but only the operations at stages s > n_simd_llr have all the inputs aligned.
uint8_t n_llr_all_stages = code_size_log + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages. uint8_t n_llr_all_stages = nMax + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages.
uint16_t llr_all_stages = 1U << n_llr_all_stages; uint16_t llr_all_stages = 1U << n_llr_all_stages;
pp->llr0[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(float)); // 32*8=256 pp->llr0[0] = srslte_vec_f_malloc(llr_all_stages); // 32*8=256
// allocate memory to the polar decoder instance // allocate memory to the polar decoder instance
if (pp->llr0[0] == NULL) { if (pp->llr0[0] == NULL) {
@ -246,18 +258,18 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
// initialize all LLR pointers // initialize all LLR pointers
pp->llr1[0] = pp->llr0[0] + 1; pp->llr1[0] = pp->llr0[0] + 1;
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->llr0[s] = pp->llr0[0] + pp->param->code_stage_size[s]; pp->llr0[s] = pp->llr0[0] + pp->param->code_stage_size[s];
pp->llr1[s] = pp->llr0[0] + pp->param->code_stage_size[s] + pp->param->code_stage_size[s - 1]; pp->llr1[s] = pp->llr0[0] + pp->param->code_stage_size[s] + pp->param->code_stage_size[s - 1];
} }
// allocate memory for node type pointers, one per stage. // allocate memory for node type pointers, one per stage.
pp->param->frozen_set_size = frozen_set_size;
pp->param->node_type = malloc((code_size_log + 1) * sizeof(uint8_t*)); pp->param->node_type = malloc((nMax + 1) * sizeof(uint8_t*));
// allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N. // allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N.
// Thus, same size as LLRs all stages. // Thus, same size as LLRs all stages.
pp->param->node_type[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(uint8_t)); // 32*8=256 pp->param->node_type[0] = srslte_vec_u8_malloc(llr_all_stages); // 32*8=256
if (pp->param->node_type[0] == NULL) { if (pp->param->node_type[0] == NULL) {
free(pp->llr0[0]); free(pp->llr0[0]);
@ -272,11 +284,24 @@ void* create_polar_decoder_ssc_f(uint16_t* frozen_set, const uint8_t code_size_l
} }
// initialize all node type pointers. (stage 0 is the first, opposite to LLRs) // initialize all node type pointers. (stage 0 is the first, opposite to LLRs)
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[code_size_log - s + 1]; pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[nMax - s + 1];
} }
init_node_type(frozen_set, pp->param); // memory allocation to compute node_type
pp->tmp_node_type = create_tmp_node_type(nMax);
if (pp->tmp_node_type == NULL) {
free(pp->param->node_type[0]);
free(pp->llr0[0]);
free(pp->llr1);
free(pp->llr0);
free(pp->state);
free(pp->param->code_stage_size);
free(pp->param);
free(pp->enc);
free(pp);
return NULL;
}
return pp; return pp;
} }

@ -28,12 +28,10 @@
/*! /*!
* Creates an SSC polar decoder structure of type pSSC, and allocates memory for the decoding buffers. * Creates an SSC polar decoder structure of type pSSC, and allocates memory for the decoding buffers.
* \param[in] frozen_set The position of the frozen bits in the codeword. * \param[in] nMax \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set_size Number of frozen bits.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \return A pointer to a pSSC structure if the function executes correctly, NULL otherwise. * \return A pointer to a pSSC structure if the function executes correctly, NULL otherwise.
*/ */
void* create_polar_decoder_ssc_f(uint16_t* frozen_set, uint8_t code_size_log, uint16_t frozen_set_size); void* create_polar_decoder_ssc_f(const uint8_t nMax);
/*! /*!
* The polar decoder SSC "destructor": it frees all the resources allocated to the decoder. * The polar decoder SSC "destructor": it frees all the resources allocated to the decoder.
@ -46,9 +44,17 @@ void delete_polar_decoder_ssc_f(void* p);
* \param[in, out] p A void pointer used to declare a pSSC structure. * \param[in, out] p A void pointer used to declare a pSSC structure.
* \param[in] llr LLRs for the new codeword. * \param[in] llr LLRs for the new codeword.
* \param[out] data_decoded Pointer to the decoded message. * \param[out] data_decoded Pointer to the decoded message.
* \param[in] code_size_log \f$\log_2(code_size)\f$.
* \param[in] frozen_set The position of the frozen bits in increasing order.
* \param[in] frozen_set_size The size of the frozen_set.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
int init_polar_decoder_ssc_f(void* p, const float* llr, uint8_t* data_decoded); int init_polar_decoder_ssc_f(void* p,
const float* llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
/*! /*!
* Decodes a data message from a codeword with the specified decoder. Note that * Decodes a data message from a codeword with the specified decoder. Note that

@ -46,12 +46,13 @@
* \brief Describes an SSC polar decoder (16-bit version). * \brief Describes an SSC polar decoder (16-bit version).
*/ */
struct pSSC_s { struct pSSC_s {
int16_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */ int16_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */
int16_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */ int16_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */
uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */ uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */
struct Params* param; /*!< \brief Pointer to a Params structure. */ struct Params* param; /*!< \brief Pointer to a Params structure. */
struct State* state; /*!< \brief Pointer to a State. */ struct State* state; /*!< \brief Pointer to a State. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */ void* tmp_node_type; /*!< \brief Pointer to a Tmp_node_type. */
srslte_polar_encoder_t* enc; /*!< \brief Pointer to a srslte_polar_encoder_t. */
void (*f)(const int16_t* x, void (*f)(const int16_t* x,
const int16_t* y, const int16_t* y,
int16_t* z, int16_t* z,
@ -102,7 +103,12 @@ static void rate_1_node(void* p, uint8_t* message);
*/ */
static void rate_r_node(void* p, uint8_t* message); static void rate_r_node(void* p, uint8_t* message);
int init_polar_decoder_ssc_s(void* p, const int16_t* input_llr, uint8_t* data_decoded) int init_polar_decoder_ssc_s(void* p,
const int16_t* input_llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size)
{ {
struct pSSC_s* pp = p; struct pSSC_s* pp = p;
@ -110,9 +116,9 @@ int init_polar_decoder_ssc_s(void* p, const int16_t* input_llr, uint8_t* data_de
return -1; return -1;
} }
uint8_t code_size_log = pp->param->code_size_log; pp->param->code_size_log = code_size_log;
int16_t code_size = pp->param->code_stage_size[code_size_log]; int16_t code_size = pp->param->code_stage_size[code_size_log];
int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1]; int16_t code_half_size = pp->param->code_stage_size[code_size_log - 1];
// Initializes the data_decoded_vector to all zeros // Initializes the data_decoded_vector to all zeros
memset(data_decoded, 0, code_size); memset(data_decoded, 0, code_size);
@ -133,6 +139,12 @@ int init_polar_decoder_ssc_s(void* p, const int16_t* input_llr, uint8_t* data_de
} }
pp->state->flag_finished = false; pp->state->flag_finished = false;
// frozen_set
pp->param->frozen_set_size = frozen_set_size;
// computes the node types for the decoding tree
compute_node_type(pp->tmp_node_type, pp->param->node_type, frozen_set, code_size_log, frozen_set_size);
return 0; return 0;
} }
@ -164,11 +176,13 @@ void delete_polar_decoder_ssc_s(void* p)
free(pp->state); free(pp->state);
srslte_polar_encoder_free(pp->enc); srslte_polar_encoder_free(pp->enc);
free(pp->enc); free(pp->enc);
// free(pp->frozen_set); // this is not SSC responsibility.
delete_tmp_node_type(pp->tmp_node_type);
free(pp); free(pp);
} }
} }
void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_log, const uint16_t frozen_set_size) void* create_polar_decoder_ssc_s(const uint8_t nMax)
{ {
struct pSSC_s* pp = NULL; // pointer to the polar decoder instance struct pSSC_s* pp = NULL; // pointer to the polar decoder instance
@ -188,7 +202,7 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
free(pp); free(pp);
return NULL; return NULL;
} }
srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_PIPELINED, code_size_log); srslte_polar_encoder_init(pp->enc, SRSLTE_POLAR_ENCODER_PIPELINED, nMax);
// algorithm constants/parameters // algorithm constants/parameters
if ((pp->param = malloc(sizeof(struct Params))) == NULL) { if ((pp->param = malloc(sizeof(struct Params))) == NULL) {
@ -197,7 +211,7 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
return NULL; return NULL;
} }
if ((pp->param->code_stage_size = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) { if ((pp->param->code_stage_size = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
free(pp->param); free(pp->param);
free(pp->enc); free(pp->enc);
free(pp); free(pp);
@ -205,12 +219,10 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
} }
pp->param->code_stage_size[0] = 1; pp->param->code_stage_size[0] = 1;
for (uint8_t i = 1; i < code_size_log + 1; i++) { for (uint8_t i = 1; i < nMax + 1; i++) {
pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1]; pp->param->code_stage_size[i] = 2 * pp->param->code_stage_size[i - 1];
} }
pp->param->code_size_log = code_size_log;
// state -- initialized in polar_decoder_ssc_init // state -- initialized in polar_decoder_ssc_init
if ((pp->state = malloc(sizeof(struct State))) == NULL) { if ((pp->state = malloc(sizeof(struct State))) == NULL) {
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
@ -219,7 +231,7 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
free(pp); free(pp);
return NULL; return NULL;
} }
if ((pp->state->active_node_per_stage = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) { if ((pp->state->active_node_per_stage = srslte_vec_u16_malloc(nMax + 1)) == NULL) {
free(pp->state); free(pp->state);
free(pp->param->code_stage_size); free(pp->param->code_stage_size);
free(pp->param); free(pp->param);
@ -229,13 +241,13 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
} }
// allocates memory for estimated bits per stage // allocates memory for estimated bits per stage
uint16_t est_bits_size = pp->param->code_stage_size[code_size_log]; uint16_t est_bits_size = pp->param->code_stage_size[nMax];
pp->est_bit = aligned_alloc(SRSLTE_AVX2_B_SIZE, est_bits_size); // every 32 chars are aligned pp->est_bit = srslte_vec_u8_malloc(est_bits_size); // every 32 chars are aligned
// allocate memory for LLR pointers. // allocate memory for LLR pointers.
pp->llr0 = malloc((code_size_log + 1) * sizeof(int16_t*)); pp->llr0 = malloc((nMax + 1) * sizeof(int16_t*));
pp->llr1 = malloc((code_size_log + 1) * sizeof(int16_t*)); pp->llr1 = malloc((nMax + 1) * sizeof(int16_t*));
// There are LLR buffers for n = 0 to n = code_size_log. Each with size 2^n. Thus, // There are LLR buffers for n = 0 to n = code_size_log. Each with size 2^n. Thus,
// the total memory needed is 2^(n+1)-1. // the total memory needed is 2^(n+1)-1.
@ -245,10 +257,10 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
// i.e. in a SIMD instruction we can load 2^(n_simd_llr) LLR values // i.e. in a SIMD instruction we can load 2^(n_simd_llr) LLR values
// then the memory for stages s >= n_simd_llr - 1 is aligned. // then the memory for stages s >= n_simd_llr - 1 is aligned.
// but only the operations at stages s > n_simd_llr have all the inputs aligned. // but only the operations at stages s > n_simd_llr have all the inputs aligned.
uint8_t n_llr_all_stages = code_size_log + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages. uint8_t n_llr_all_stages = nMax + 1; // there are 2^(n_llr_all_stages) - 1 LLR values summing up all stages.
uint16_t llr_all_stages = 1U << n_llr_all_stages; uint16_t llr_all_stages = 1U << n_llr_all_stages;
pp->llr0[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(int16_t)); // 32*8=256 pp->llr0[0] = srslte_vec_i16_malloc(llr_all_stages); // 32*8=256
// allocate memory to the polar decoder instance // allocate memory to the polar decoder instance
if (pp->llr0[0] == NULL) { if (pp->llr0[0] == NULL) {
free(pp->est_bit); free(pp->est_bit);
@ -262,18 +274,17 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
// initialize all LLR pointers // initialize all LLR pointers
pp->llr1[0] = pp->llr0[0] + 1; pp->llr1[0] = pp->llr0[0] + 1;
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->llr0[s] = pp->llr0[0] + pp->param->code_stage_size[s]; pp->llr0[s] = pp->llr0[0] + pp->param->code_stage_size[s];
pp->llr1[s] = pp->llr0[0] + pp->param->code_stage_size[s] + pp->param->code_stage_size[s - 1]; pp->llr1[s] = pp->llr0[0] + pp->param->code_stage_size[s] + pp->param->code_stage_size[s - 1];
} }
// allocate memory for node type pointers, one per stage. // allocate memory for node type pointers, one per stage.
pp->param->frozen_set_size = frozen_set_size; pp->param->node_type = malloc((nMax + 1) * sizeof(uint8_t*));
pp->param->node_type = malloc((code_size_log + 1) * sizeof(uint8_t*));
// allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N. // allocate memory to node_type_ssc. Stage s has 2^(N-s) nodes s=0,...,N.
// Thus, same size as LLRs all stages. // Thus, same size as LLRs all stages.
pp->param->node_type[0] = aligned_alloc(SRSLTE_AVX2_B_SIZE, llr_all_stages * sizeof(uint8_t)); // 32*8=256 pp->param->node_type[0] = srslte_vec_u8_malloc(llr_all_stages); // 32*8=256
if (pp->param->node_type[0] == NULL) { if (pp->param->node_type[0] == NULL) {
free(pp->param->node_type); free(pp->param->node_type);
@ -287,11 +298,23 @@ void* create_polar_decoder_ssc_s(uint16_t* frozen_set, const uint8_t code_size_l
} }
// initialize all node type pointers. (stage 0 is the first, opposite to LLRs) // initialize all node type pointers. (stage 0 is the first, opposite to LLRs)
for (uint8_t s = 1; s < code_size_log + 1; s++) { for (uint8_t s = 1; s < nMax + 1; s++) {
pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[code_size_log - s + 1]; pp->param->node_type[s] = pp->param->node_type[s - 1] + pp->param->code_stage_size[nMax - s + 1];
}
// memory allocation to compute node_type
pp->tmp_node_type = create_tmp_node_type(nMax);
if (pp->tmp_node_type == NULL) {
free(pp->param->node_type[0]);
free(pp->llr0[0]);
free(pp->llr1);
free(pp->llr0);
free(pp->state);
free(pp->param->code_stage_size);
free(pp->param);
free(pp->enc);
free(pp);
return NULL;
} }
init_node_type(frozen_set, pp->param);
return pp; return pp;
} }

@ -31,13 +31,10 @@
* This function is exactly the same as the one for the floating-point version. * This function is exactly the same as the one for the floating-point version.
* Note, however, that it works with a different pSSC structure (different function pointers * Note, however, that it works with a different pSSC structure (different function pointers
* pSSC::f, pSSC::f, pSSC::g, pSSC::xor and pSSC::hard_bit). * pSSC::f, pSSC::f, pSSC::g, pSSC::xor and pSSC::hard_bit).
* * \param[in] nMax \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set The position of the frozen bits in the codeword.
* \param[in] frozen_set_size Number of frozen bits.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \return A pointer to a pSSC structure if the function executes correctly, NULL otherwise. * \return A pointer to a pSSC structure if the function executes correctly, NULL otherwise.
*/ */
void* create_polar_decoder_ssc_s(uint16_t* frozen_set, uint8_t code_size_log, uint16_t frozen_set_size); void* create_polar_decoder_ssc_s(uint8_t nMax);
/*! /*!
* The 16-bit polar decoder SSC "destructor": it frees all the resources allocated to the decoder. * The 16-bit polar decoder SSC "destructor": it frees all the resources allocated to the decoder.
@ -52,9 +49,17 @@ void delete_polar_decoder_ssc_s(void* p);
* \param[in, out] p A void pointer used to declare a pSSC structure. * \param[in, out] p A void pointer used to declare a pSSC structure.
* \param[in] llr LLRs for the new codeword. * \param[in] llr LLRs for the new codeword.
* \param[out] data_decoded Pointer to the decoded message. * \param[out] data_decoded Pointer to the decoded message.
* \param[in] code_size_log \f$log_2\f$ of the number of bits in the codeword.
* \param[in] frozen_set The position of the frozen bits in the codeword.
* \param[in] frozen_set_size Number of frozen bits.
* \return An integer: 0 if the function executes correctly, -1 otherwise. * \return An integer: 0 if the function executes correctly, -1 otherwise.
*/ */
int init_polar_decoder_ssc_s(void* p, const int16_t* llr, uint8_t* data_decoded); int init_polar_decoder_ssc_s(void* p,
const int16_t* llr,
uint8_t* data_decoded,
const uint8_t code_size_log,
const uint16_t* frozen_set,
const uint16_t frozen_set_size);
/*! /*!
* Decodes a data message from a 16-bit resolution codeword with the specified decoder. Note that * Decodes a data message from a 16-bit resolution codeword with the specified decoder. Note that

@ -23,6 +23,7 @@
*/ */
#include "../utils_avx2.h" #include "../utils_avx2.h"
#include "srslte/phy/utils/vector.h"
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -66,9 +67,9 @@ void* create_polar_encoder_avx2(const uint8_t code_size_log)
uint16_t code_size = 1U << code_size_log; uint16_t code_size = 1U << code_size_log;
if (code_size_log > SRSLTE_AVX2_B_SIZE_LOG) { if (code_size_log > SRSLTE_AVX2_B_SIZE_LOG) {
q->tmp = malloc(code_size * sizeof(uint8_t)); q->tmp = srslte_vec_u8_malloc(code_size);
} else { } else {
q->tmp = malloc(SRSLTE_AVX2_B_SIZE * sizeof(uint8_t)); q->tmp = srslte_vec_u8_malloc(SRSLTE_AVX2_B_SIZE);
} }
if (!q->tmp) { if (!q->tmp) {
free(q); free(q);

@ -26,6 +26,7 @@
*/ */
#include "srslte/phy/fec/polar/polar_encoder.h" #include "srslte/phy/fec/polar/polar_encoder.h"
#include "srslte/phy/utils/vector.h"
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -71,14 +72,14 @@ void* create_polar_encoder_pipelined(const uint8_t code_size_log)
uint16_t code_size = 1U << code_size_log; uint16_t code_size = 1U << code_size_log;
uint16_t code_half_size = code_size / 2; uint16_t code_half_size = code_size / 2;
q->i_odd = malloc(code_half_size * sizeof(uint16_t)); q->i_odd = srslte_vec_u16_malloc(code_half_size);
if (!q->i_odd) { if (!q->i_odd) {
free(q); free(q);
perror("malloc"); perror("malloc");
return NULL; return NULL;
} }
q->i_even = malloc(code_half_size * sizeof(uint16_t)); q->i_even = srslte_vec_u16_malloc(code_half_size);
if (!q->i_even) { if (!q->i_even) {
free(q->i_odd); free(q->i_odd);
free(q); free(q);
@ -86,7 +87,7 @@ void* create_polar_encoder_pipelined(const uint8_t code_size_log)
return NULL; return NULL;
} }
q->tmp = malloc(code_size * sizeof(uint8_t)); q->tmp = srslte_vec_u8_malloc(code_size);
if (!q->tmp) { if (!q->tmp) {
free(q->i_even); free(q->i_even);
free(q->i_odd); free(q->i_odd);

@ -0,0 +1,615 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*!
* \file polar_rm.c
* \brief Definition of the LDPC Rate Matcher and Rate Dematcher (float-valued, int16_t and int8_t)
* \author Jesus Gomez (CTTC)
* \date 2020
*
* \copyright Software Radio Systems Limited
*
*/
#include "srslte/phy/utils/vector.h"
#include <stddef.h>
#include <stdint.h>
#include "srslte/phy/fec/polar/polar_code.h"
#include "srslte/phy/fec/polar/polar_rm.h"
#include "srslte/phy/utils/debug.h"
/*!
* \brief Describes an rate matcher.
*/
struct pRM_tx {
uint8_t* y_e; /*!< \brief Pointer to a temporal buffer to store the block interleaved codeword (y), as well as the
rate-matched codewords (e). */
};
/*!
* \brief Describes an rate dematcher (float version).
*/
struct pRM_rx_f {
float* y_e; /*!< \brief Pointer to a temporal buffer to symbols before and after bit_selection_rx. */
float* e; /*!< \brief Pointer to a the position in the y_e buffer where the rate matched llr start.*/
};
/*!
* \brief Describes an rate dematcher (int8_t version).
*/
struct pRM_rx_s {
int16_t* y_e; /*!< \brief Pointer to a temporal buffer to symbols before and after bit_selection_rx. */
int16_t* e; /*!< \brief Pointer to a the position in the y_e buffer where the rate matched llr start.*/
};
/*!
* \brief Describes an rate dematcher (int8_t version).
*/
struct pRM_rx_c {
int8_t* y_e; /*!< \brief Pointer to a temporal buffer to symbols before and after bit_selection_rx. */
int8_t* e; /*!< \brief Pointer to a the position in the y_e buffer where the rate matched llr start.*/
};
/*!
* generic interleaver
*/
static void interleaver_rm_tx(const uint8_t* input, uint8_t* output, const uint16_t* indices, const uint16_t len)
{
for (uint32_t j = 0; j < len; j++) {
output[j] = input[indices[j]];
}
}
/*!
* generic deinterleaver.
*/
static void interleaver_rm_rx(const float* input, float* output, const uint16_t* indices, const uint16_t len)
{
for (uint32_t j = 0; j < len; j++) {
output[indices[j]] = input[j];
}
}
/*!
* generic deinterleaver (int16_t).
*/
static void interleaver_rm_rx_s(const int16_t* input, int16_t* output, const uint16_t* indices, const uint16_t len)
{
for (uint32_t j = 0; j < len; j++) {
output[indices[j]] = input[j];
}
}
/*!
* generic deinterleaver (int8_t).
*/
static void interleaver_rm_rx_c(const int8_t* input, int8_t* output, const uint16_t* indices, const uint16_t len)
{
for (uint32_t j = 0; j < len; j++) {
output[indices[j]] = input[j];
}
}
/*!
* Bit selection for the polar rate-matching block. ye has length N, but there is EMAX memory allocated to it.
*/
static uint8_t* bit_selection_rm_tx(uint8_t* y, const uint32_t N, const uint32_t E, const uint32_t K)
{
uint8_t* e = NULL;
uint32_t k_N = 0;
e = y;
if (E >= N) { // repetition
for (uint32_t k = N; k < E; k++) {
k_N = k % N;
e[k] = y[k_N];
}
} else {
if (16 * K <= 7 * E) { // puncturing the first N-E bits
e = y + (N - E);
} // else shortening the last N-E bits
}
return e;
}
/*!
* Undoes bit selection for the rate-dematching block float).
* The output has the codeword length N. It inserts 0 to punctured bits (completely unknown bit)
* and 127 (to indicate very reliable 0 bit). Repeated symbols are added.
*/
static float* bit_selection_rm_rx(float* e, const uint32_t E, const uint32_t N, const uint32_t K)
{
float* y = NULL;
uint32_t k_N = 0;
y = e;
if (E >= N) { // add repetitions
y = e;
for (uint32_t k = N; k < E; k++) {
k_N = k % N;
y[k_N] = y[k_N] + e[k];
}
} else {
if (16 * K <= 7 * E) { // puncturing bits are completely unknown, i.e. llr = 0;
y = e - (N - E);
for (uint32_t k = 0; k < N - E; k++) {
y[k] = 0;
}
} else { // shortening, bits are know to be 0. i.e., very high llrs
for (uint32_t k = E; k < N; k++) {
y[k] = 1e+20F; /* max value */
}
}
}
return y;
}
/*!
* Undoes bit selection for the rate-dematching block (int16_t).
* The output has the codeword length N. It inserts 0 to punctured bits (completely unknown bit)
* and 127 (to indicate very reliable 0 bit). Repeated symbols are added.
*/
static int16_t* bit_selection_rm_rx_s(int16_t* e, const uint32_t E, const uint32_t N, const uint32_t K)
{
int16_t* y = NULL;
uint32_t k_N = 0;
long tmp = 0;
y = e;
if (E >= N) { // add repetitions
y = e;
for (uint32_t k = N; k < E; k++) {
k_N = k % N;
tmp = (long)y[k_N] + e[k];
// control saturation
if (tmp > 32767) {
tmp = 32767;
}
if (tmp < -32767) {
tmp = -32767;
}
y[k_N] = (int16_t)tmp;
}
} else {
if (16 * K <= 7 * E) { // puncturing bits are completely unknown, i.e. llr = 0;
y = e - (N - E);
for (uint32_t k = 0; k < N - E; k++) {
y[k] = 0;
}
} else { // shortening, bits are know to be 0. i.e., very high llrs
for (uint32_t k = E; k < N; k++) {
y[k] = 32767; /* max value */
}
}
}
return y;
}
/*!
* Undoes bit selection for the rate-dematching block (int8_t).
* The output has the codeword length N. It inserts 0 to punctured bits (completely unknown bit)
* and 127 (to indicate very reliable 0 bit). Repeated symbols are added.
*/
static int8_t* bit_selection_rm_rx_c(int8_t* e, const uint32_t E, const uint32_t N, const uint32_t K)
{
int8_t* y = NULL;
uint32_t k_N = 0;
long tmp = 0;
y = e;
if (E >= N) { // add repetitions
y = e;
for (uint32_t k = N; k < E; k++) {
k_N = k % N;
tmp = (long)y[k_N] + e[k];
// control saturation
if (tmp > 127) {
tmp = 127;
}
if (tmp < -127) {
tmp = -127;
}
y[k_N] = (int8_t)tmp;
}
} else {
if (16 * K <= 7 * E) { // puncturing bits are completely unknown, i.e. llr = 0;
y = e - (N - E);
for (uint32_t k = 0; k < N - E; k++) {
y[k] = 0;
}
} else { // shortening, bits are know to be 0. i.e., very high llrs
for (uint32_t k = E; k < N; k++) {
y[k] = 127; /* max value */
}
}
}
return y;
}
/*!
* Channel interleaver.
*/
static void ch_interleaver_rm_tx(const uint8_t* e, uint8_t* f, const uint32_t E)
{
// compute T - Smaller integer such that T(T+1)/2 >= E. Use the fact that 1+2+,..,+T = T(T+1)/2
uint32_t S = 1;
uint32_t T = 1;
while (S < E) {
T++;
S = S + T;
}
uint32_t i_out = 0;
uint32_t i_in = 0;
for (uint32_t r = 0; r < T; r++) {
i_in = r;
for (uint32_t c = 0; c < T - r; c++) {
if (i_in < E) {
f[i_out] = e[i_in];
i_out++;
i_in = i_in + (T - c);
} else {
break;
}
}
}
}
/*!
* Channel deinterleaver.
*/
static void ch_interleaver_rm_rx(const float* f, float* e, const uint32_t E)
{
// compute T - Smaller integer such that T(T+1)/2 >= E. Use the fact that 1+2+,..,+T = T(T+1)/2
uint32_t S = 1;
uint32_t T = 1;
while (S < E) {
T++;
S = S + T;
}
uint32_t i_out = 0;
uint32_t i_in = 0;
for (uint32_t r = 0; r < T; r++) {
i_in = r;
for (uint32_t c = 0; c < T - r; c++) {
if (i_in < E) {
e[i_in] = f[i_out];
i_out++;
i_in = i_in + (T - c);
} else {
break;
}
}
}
}
/*!
* Channel deinterleaver (int16_t).
*/
static void ch_interleaver_rm_rx_s(const int16_t* f, int16_t* e, const uint32_t E)
{
// compute T - Smaller integer such that T(T+1)/2 >= E. Use the fact that 1+2+,..,+T = T(T+1)/2
uint32_t S = 1;
uint32_t T = 1;
while (S < E) {
T++;
S = S + T;
}
uint32_t i_out = 0;
uint32_t i_in = 0;
for (uint32_t r = 0; r < T; r++) {
i_in = r;
for (uint32_t c = 0; c < T - r; c++) {
if (i_in < E) {
e[i_in] = f[i_out];
i_out++;
i_in = i_in + (T - c);
} else {
break;
}
}
}
}
/*!
* Channel deinterleaver (int8_t).
*/
static void ch_interleaver_rm_rx_c(const int8_t* f, int8_t* e, const uint32_t E)
{
// compute T - Smaller integer such that T(T+1)/2 >= E. Use the fact that 1+2+,..,+T = T(T+1)/2
uint32_t S = 1;
uint32_t T = 1;
while (S < E) {
T++;
S = S + T;
}
uint32_t i_out = 0;
uint32_t i_in = 0;
for (uint32_t r = 0; r < T; r++) {
i_in = r;
for (uint32_t c = 0; c < T - r; c++) {
if (i_in < E) {
e[i_in] = f[i_out];
i_out++;
i_in = i_in + (T - c);
} else {
break;
}
}
}
}
int srslte_polar_rm_tx_init(srslte_polar_rm_t* p)
{
if (p == NULL) {
return -1;
}
struct pRM_tx* pp = NULL; // pointer to the rate matcher instance
// allocate memory to the rate-matcher instance
if ((pp = malloc(sizeof(struct pRM_tx))) == NULL) {
return -1;
}
p->ptr = pp;
// allocate memory to the blk interleaved codeword
if ((pp->y_e = srslte_vec_u8_malloc(EMAX)) == NULL) {
free(pp);
return -1;
}
return 0;
}
int srslte_polar_rm_rx_init_f(srslte_polar_rm_t* p)
{
if (p == NULL) {
return -1;
}
struct pRM_rx_f* pp = NULL; // pointer to the rate matcher instance
// allocate memory to ther rate-demacher instance
if ((pp = malloc(sizeof(struct pRM_rx_f))) == NULL) {
return -1;
}
p->ptr = pp;
// allocate memory to the temporal buffer of chDeInterleaved llrs
if ((pp->y_e = srslte_vec_f_malloc(EMAX + NMAX)) == NULL) {
free(pp);
return -1;
}
pp->e = pp->y_e + NMAX;
return 0;
}
int srslte_polar_rm_rx_init_s(srslte_polar_rm_t* p)
{
if (p == NULL) {
return -1;
}
struct pRM_rx_s* pp = NULL; // pointer to the rate matcher instance
// allocate memory to ther rate-demacher instance
if ((pp = malloc(sizeof(struct pRM_rx_s))) == NULL) {
return -1;
}
p->ptr = pp;
// allocate memory to the temporal buffer of chDeInterleaved llrs
if ((pp->y_e = srslte_vec_i16_malloc(EMAX + NMAX)) == NULL) {
free(pp);
return -1;
}
pp->e = pp->y_e + NMAX;
return 0;
}
int srslte_polar_rm_rx_init_c(srslte_polar_rm_t* p)
{
if (p == NULL) {
return -1;
}
struct pRM_rx_c* pp = NULL; // pointer to the rate matcher instance
// allocate memory to ther rate-demacher instance
if ((pp = malloc(sizeof(struct pRM_rx_c))) == NULL) {
return -1;
}
p->ptr = pp;
// allocate memory to the temporal buffer of chDeInterleaved llrs
if ((pp->y_e = srslte_vec_i8_malloc(EMAX + NMAX)) == NULL) {
free(pp);
return -1;
}
pp->e = pp->y_e + NMAX;
return 0;
}
void srslte_polar_rm_tx_free(srslte_polar_rm_t* q)
{
if (q != NULL) {
struct pRM_tx* qq = q->ptr;
free(qq->y_e);
free(qq);
}
}
void srslte_polar_rm_rx_free_f(srslte_polar_rm_t* q)
{
if (q != NULL) {
struct pRM_rx_f* qq = q->ptr;
free(qq->y_e);
// free(qq->indices);
free(qq);
}
}
void srslte_polar_rm_rx_free_s(srslte_polar_rm_t* q)
{
if (q != NULL) {
struct pRM_rx_s* qq = q->ptr;
free(qq->y_e);
// free(qq->indices);
free(qq);
}
}
void srslte_polar_rm_rx_free_c(srslte_polar_rm_t* q)
{
if (q != NULL) {
struct pRM_rx_c* qq = q->ptr;
free(qq->y_e);
// free(qq->indices);
free(qq);
}
}
int srslte_polar_rm_tx(srslte_polar_rm_t* q,
const uint8_t* input,
uint8_t* output,
const uint8_t n,
const uint32_t E,
const uint32_t K,
const uint8_t ibil)
{
const uint16_t* blk_interleaver = get_blk_interleaver(n);
uint32_t N = (1U << n);
struct pRM_tx* pp = q->ptr;
uint8_t* y = pp->y_e;
uint8_t* e = NULL;
interleaver_rm_tx(input, y, blk_interleaver, N);
e = bit_selection_rm_tx(y, N, E, K); // moves the pointer if puncturing e = y + (N-E), otherwise e = y;
if (ibil == 0) {
memcpy(output, e, E * sizeof(uint8_t));
} else {
ch_interleaver_rm_tx(e, output, E);
}
return 0;
}
int srslte_polar_rm_rx_f(srslte_polar_rm_t* q,
const float* input,
float* output,
const uint32_t E,
const uint8_t n,
const uint32_t K,
const uint8_t ibil)
{
struct pRM_rx_f* pp = q->ptr;
float* y = NULL;
float* e = pp->e; // length E
uint32_t N = (1U << n);
const uint16_t* blk_interleaver = get_blk_interleaver(n);
if (ibil == 0) {
memcpy(e, input, E * sizeof(float));
} else {
ch_interleaver_rm_rx(input, e, E);
}
y = bit_selection_rm_rx(e, E, N, K);
interleaver_rm_rx(y, output, blk_interleaver, N);
return 0;
}
int srslte_polar_rm_rx_s(srslte_polar_rm_t* q,
const int16_t* input,
int16_t* output,
const uint32_t E,
const uint8_t n,
const uint32_t K,
const uint8_t ibil)
{
struct pRM_rx_s* pp = q->ptr;
int16_t* y = NULL;
int16_t* e = pp->e;
uint32_t N = (1U << n);
const uint16_t* blk_interleaver = get_blk_interleaver(n);
if (ibil == 0) {
memcpy(e, input, E * sizeof(int16_t));
} else {
ch_interleaver_rm_rx_s(input, e, E);
}
y = bit_selection_rm_rx_s(e, E, N, K);
interleaver_rm_rx_s(y, output, blk_interleaver, N);
return 0;
}
int srslte_polar_rm_rx_c(srslte_polar_rm_t* q,
const int8_t* input,
int8_t* output,
const uint32_t E,
const uint8_t n,
const uint32_t K,
const uint8_t ibil)
{
struct pRM_rx_c* pp = q->ptr;
int8_t* y = NULL;
int8_t* e = pp->e;
uint32_t N = (1U << n);
const uint16_t* blk_interleaver = get_blk_interleaver(n);
if (ibil == 0) {
memcpy(e, input, E * sizeof(int8_t));
} else {
ch_interleaver_rm_rx_c(input, e, E);
}
y = bit_selection_rm_rx_c(e, E, N, K);
interleaver_rm_rx_c(y, output, blk_interleaver, N);
return 0;
}

@ -13,35 +13,80 @@ add_executable(polar_chain_test polar_chain_test.c)
target_link_libraries(polar_chain_test srslte_phy polar_test_utils) target_link_libraries(polar_chain_test srslte_phy polar_test_utils)
### Test polar libs ### Test polar libs
function(polar_unit_tests) function(polar_tests_lite)
set(S ${ARGV0}) #101 means no noise, 100 scan set(S ${ARGV0}) #101 means no noise, 100 scan
set(listC 5 6 6 6 7 7 8 8 9 9 10) set(listN 10 10 9 9 9 9 9 9 10 9 10)
set(listR 32 64 64 64 128 128 256 256 512 864 1024) set(listE 32 64 64 64 128 128 256 256 512 864 1024)
set(listM 31 31 36 63 36 64 36 128 256 56 512) set(listK 31 31 36 63 36 64 36 128 256 56 512)
set(listP 0 0 0 0 0 0 0 0 0 0 0) set(listI 0 0 0 0 0 0 0 0 1 0 1)
set(listW 0 0 0 0 0 0 0 0 0 0 0) list(LENGTH listN len)
list(LENGTH listC len)
math(EXPR lenr "${len} - 1") math(EXPR lenr "${len} - 1")
foreach(num RANGE ${lenr}) foreach(num RANGE ${lenr})
list(GET listC ${num} cval) list(GET listN ${num} nval)
list(GET listR ${num} rval) list(GET listE ${num} eval)
list(GET listM ${num} mval) list(GET listK ${num} kval)
list(GET listP ${num} pval) list(GET listI ${num} ival)
list(GET listW ${num} wval) add_test(NAME ${test_name}-s${S}-n${nval}-e${eval}-k${kval}-i${ival}
add_test(NAME ${test_name}-s${S}-c${cval}-r${rval}-m${mval}-p${pval}-w${wval} COMMAND ${test_command} -s${S} -n${nval} -e${eval} -k${kval} -i${ival}
COMMAND ${test_command} -s${S} -c${cval} -r${rval} -m${mval} -p${pval} -w${wval} -E1 -N1 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/polar
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
) )
endforeach() endforeach()
endfunction() endfunction()
### Test polar libs
function(polar_tests)
set(S ${ARGV0}) #101 means no noise, 100 scan
#Downlink tests
set(nval 9)
foreach(Kval RANGE 36 164 32)
math(EXPR Emin "${Kval} + 1")
foreach(Eval RANGE ${Emin} 8192 128)
add_test(NAME ${test_name}-s${S}-k${Kval}-e${Eval}-n${nval}-i0
COMMAND ${test_command} -s${S} -k${Kval} -e${Eval} -n${nval} -i0
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/polar
)
endforeach()
endforeach()
#Uplink tests
set(nval 10)
foreach(Kval RANGE 18 25)
math(EXPR Emin "${Kval} + 3 + 1")
foreach(Eval RANGE ${Emin} 8192 128)
add_test(NAME ${test_name}-s${S}-k${Kval}-e${Eval}-n${nval}-i1
COMMAND ${test_command} -s${S} -k${Kval} -e${Eval} -n${nval} -i1
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/polar
)
endforeach()
endforeach()
foreach(Kval RANGE 32 1023 32)
math(EXPR Emin "${Kval} + 1")
foreach(Eval RANGE ${Emin} 8192 128)
add_test(NAME ${test_name}-s${S}-k${Kval}-e${Eval}-n${nval}-i1
COMMAND ${test_command} -s${S} -k${Kval} -e${Eval} -n${nval} -i1
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/polar
)
endforeach()
endforeach()
endfunction()
# Unit tests # Unit tests
set(test_name POLAR-UNIT-TEST) set(test_name POLAR-UNIT-TEST-LITE)
set(test_command polar_chain_test) set(test_command polar_chain_test)
polar_unit_tests(101) polar_tests_lite(101)
# WER (performance) tests # WER (performance) tests
# For these tests, run ctest --verbose
set(test_name POLAR-PERF-TEST) set(test_name POLAR-PERF-TEST)
set(test_command polar_chain_test) set(test_command polar_chain_test)
polar_unit_tests(-3) polar_tests_lite(-3)
# Unit tests full
set(test_name POLAR-UNIT-TEST)
set(test_command polar_chain_test)
polar_tests(101)

@ -12,47 +12,40 @@
/*! /*!
* \file polar_chain_test.c * \file polar_chain_test.c
* \brief Throughput and WER tests for the polar encoder/decoder. * \brief Ent-to-end test for the Polar coding chain including: subchannel allocator, encoder, rate-matcher,
rate-dematcher, decoder and subchannel deallocation.
* *
* Synopsis: **polar_test [options]** * A batch of example messages is randomly generated, frozen bits are added, encoded, rate-matched, 2-PAM modulated,
* sent over an AWGN channel, rate-dematched, and, finally, decoded by all three types of
* decoder. Transmitted and received messages are compared to estimate the WER.
* Multiple batches are simulated if the number of errors is not significant
* enough.
* *
* Options: * Synopsis: **polar_chain_test [options]**
*
* - <b>-c \<number\></b> \f$log_2\f$ of the codeword length [Default 8]
*
* - <b>-r \<number\></b> Rate matching size [Default 256]
*
* - <b>-m \<number\></b> Message size [Default 128]
* *
* - <b>-p \<number\></b> Parity-set size [Default 0] * Options:
*
* - <b>-w \<number\></b> nWmPC [Default 0]
*
* - <b>-s \<number\></b> SNR [dB, Default 3.00 dB] -- Use 100 for scan, and 101 for noiseless
* *
* - <b>-n \<number\></b> nMax, [Default 9] -- Use 9 for downlink, and 10 for uplink configuration.
* - <b>-k \<number\></b> Message size (K), [Default 128]. K includes the CRC bits if applicable.
* If nMax = 9, K must satisfy 165 > K > 35. If nMax = 10, K must satisfy K > 17 and K <1024, excluding 31 > K > 25.
* - <b>-e \<number\></b> Rate matching size (E), [Default 256]. If 17 < K < 26, E must satisfy K +3 < E < 8193.
* If K > 30, E must satisfy K < E < 8193.
* - <b>-i \<number\></b> Enable bit interleaver (bil), [Default 0] -- Set bil = 0 to disable the
* bit interleaver at rate matching. Choose 0 for downlink and 1 for uplink configuration.
* - <b>-s \<number\></b> SNR [dB, Default 3.00 dB] -- Use 100 for scan, and 101 for noiseless.
* - <b>-o \<number\></b> Print output results [Default 0] -- Use 0 for detailed, Use 1 for 1 line, Use 2 for vector * - <b>-o \<number\></b> Print output results [Default 0] -- Use 0 for detailed, Use 1 for 1 line, Use 2 for vector
* form * form.
* *
* - <b>-B \<number\>** Number of codewords in a batch.(Default 100). * Example 1: BCH - ./polar_chain_test -n9 -k56 -e864 -i0 -s101 -o1
* *
* - <b>-N \<number\>** Max number of simulated batches.(Default 10000). * Example 2: DCI - ./polar_chain_test -n9 -k40 -e100 -i0 -s101 -o1
* *
* - <b>-E \<number\>** Minimum number of errors for a significant simulation.(Default 100). * Example 3: UCI - PC bits - ./polar_chain_test -n10 -k20 -e256 -i1 -s101 -o1
* *
* It (1) generates a random set of bits (data); (2) passes the data bits * Example 4: UCI - puncturing 19 first bits - ./polar_chain_test -n10 -k18 -e45 -i1 -s101 -o1
* through the subchannel allocation block where the input vector to the
* encoder is generated; (3) encodes the input vector; (4) adds Gaussian channel noise
* (optional); (5) passes the decoder output through the subchannel
* deallocation block where data bits are extracted; (6) compares the decoded
* bits with the original data bits and measures the throughput (in bit / s).
* *
* The message, frozen and parity bit sets corresponding to the input * Example 5: UCI - shortening 26 last bits - ./polar_chain_test -n10 -k18 -e38 -i1 -s101 -o1
* parameters -c, -r, -m, -p, -w must be available in the subfolder \a
* frozensets of the execution directory.
* These sets are stored in files with the following name convention:
* > polar_code_<code_size>_<rate_matching_size>_<message_size>_<parity_set_size>_<wmPC>.bin
* *
* See \ref polar for futher details.
* *
*/ */
@ -64,7 +57,7 @@
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/phy_logger.h" #include "srslte/phy/utils/phy_logger.h"
#include "srslte/phy/utils/random.h" #include "srslte/phy/utils/random.h"
#include "srslte/phy/utils/vector.h" // srslte_convert_dB_to_amplitude #include "srslte/phy/utils/vector.h"
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
@ -76,45 +69,44 @@
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
// polar libs // polar libs
#include "polar_sets.h" #include "srslte/phy/fec/polar/polar_chanalloc.h"
#include "srslte/phy/fec/polar/polar_code.h"
#include "srslte/phy/fec/polar/polar_decoder.h" #include "srslte/phy/fec/polar/polar_decoder.h"
#include "srslte/phy/fec/polar/polar_encoder.h" #include "srslte/phy/fec/polar/polar_encoder.h"
#include "subchannel_allocation.h" #include "srslte/phy/fec/polar/polar_rm.h"
//#define debug
//#define DATA_ALL_ONES
#define SNR_POINTS 10 /*!< \brief Number of SNR evaluation points.*/ #define SNR_POINTS 10 /*!< \brief Number of SNR evaluation points.*/
#define SNR_MIN (-2.0) /*!< \brief Min SNR [dB].*/ #define SNR_MIN (-2.0) /*!< \brief Min SNR [dB].*/
#define SNR_MAX 8.0 /*!< \brief Max SNR [dB].*/ #define SNR_MAX 8.0 /*!< \brief Max SNR [dB].*/
static int batch_size = 100; /*!< \brief Number of codewords in a batch. */ #define BATCH_SIZE 100 /*!< \brief Number of codewords in a batch. */
static int max_n_batch = 10000; /*!< \brief Max number of simulated batches. */ #define MAX_N_BATCH 10000 /*!< \brief Max number of simulated batches. */
static int req_errors = 100; /*!< \brief Minimum number of errors for a significant simulation. */ #define REQ_ERRORS 100 /*!< \brief Minimum number of errors for a significant simulation. */
// default values // default values
static uint8_t code_size_log = 8; /*!< \brief \f$log_2\f$ of code size. */ static uint16_t K = 128; /*!< \brief Number of message bits (data and CRC). */
static uint16_t message_size = 128; /*!< \brief Number of message bits (data and CRC). */ static uint16_t E = 256; /*!< \brief Number of bits of the codeword after rate matching. */
static uint16_t rate_matching_size = 256; /*!< \brief Number of bits of the codeword after rate matching. */ static uint8_t nMax = 9; /*!< \brief Maximum \f$log_2(N)\f$, where \f$N\f$ is the codeword size.*/
static uint8_t parity_set_size = 0; /*!< \brief Number of parity bits. */ static uint8_t bil = 0; /*!< \brief If bil = 0 channel interleaver disabled. */
static uint8_t nWmPC = 0; /*!< \brief Number of parity bits of minimum weight type. */ static double snr_db = 3; /*!< \brief SNR in dB (101 for no noise, 100 for scan). */
static double snr_db = 3; /*!< \brief SNR in dB (101 for no noise, 100 for scan). */ static int print_output = 0; /*!< \brief print output form (0 for detailed, 1 for one line, 2 for vector). */
static int print_output = 0; /*!< \brief print output form (0 for detailed, 1 for 1 line, 2 for vector). */
/*! /*!
* \brief Prints test help when a wrong parameter is passed as input. * \brief Prints test help when a wrong parameter is passed as input.
*/ */
void usage(char* prog) void usage(char* prog)
{ {
printf("Usage: %s [-cX] [-rX] [-mX] [-pX] [-wX] [-sX]\n", prog); printf("Usage: %s [-nX] [-kX] [-eX] [-iX] [-sX] [-oX]\n", prog);
printf("\t-c log2 of the codeword length [Default %d]\n", code_size_log); printf("\t-n nMax [Default %d]\n", nMax);
printf("\t-r Rate matching size [Default %d]\n", rate_matching_size); printf("\t-k Message size [Default %d]\n", K);
printf("\t-m Message size [Default %d]\n", message_size); printf("\t-e Rate matching size [Default %d]\n", E);
printf("\t-p Parity-set size [Default %d]\n", parity_set_size); printf("\t-i Bit interleaver indicator [Default %d]\n", bil);
printf("\t-w nWmPC [Default %d]\n", nWmPC);
printf("\t-s SNR [dB, Default %.2f dB] -- Use 100 for scan, and 101 for noiseless\n", snr_db); printf("\t-s SNR [dB, Default %.2f dB] -- Use 100 for scan, and 101 for noiseless\n", snr_db);
printf("\t-o Print output results [Default %d] -- Use 0 for detailed, Use 1 for 1 line, Use 2 for vector form\n", printf("\t-o Print output results [Default %d] -- Use 0 for detailed, Use 1 for 1 line, Use 2 for vector form\n",
print_output); print_output);
printf("\t-B Number of codewords in a batch. [Default %d]\n", batch_size);
printf("\t-N Max number of simulated batches. [Default %d]\n", max_n_batch);
printf("\t-E Minimum number of errors for a significant simulation. [Default %d]\n", req_errors);
} }
/*! /*!
@ -123,22 +115,20 @@ void usage(char* prog)
void parse_args(int argc, char** argv) void parse_args(int argc, char** argv)
{ {
int opt = 0; int opt = 0;
while ((opt = getopt(argc, argv, "c:r:m:p:w:e:s:t:o:B:N:E:")) != -1) { while ((opt = getopt(argc, argv, "n:k:e:i:s:o:")) != -1) {
// printf("opt : %d\n", opt);
switch (opt) { switch (opt) {
case 'c': case 'e':
code_size_log = (int)strtol(optarg, NULL, 10); E = (int)strtol(optarg, NULL, 10);
break;
case 'r':
rate_matching_size = (int)strtol(optarg, NULL, 10);
break; break;
case 'm': case 'k':
message_size = (int)strtol(optarg, NULL, 10); K = (int)strtol(optarg, NULL, 10);
break; break;
case 'p': case 'n':
parity_set_size = (int)strtol(optarg, NULL, 10); nMax = (int)strtol(optarg, NULL, 10);
break; break;
case 'w': case 'i':
nWmPC = (int)strtol(optarg, NULL, 10); bil = (int)strtol(optarg, NULL, 10);
break; break;
case 's': case 's':
snr_db = strtof(optarg, NULL); snr_db = strtof(optarg, NULL);
@ -146,15 +136,6 @@ void parse_args(int argc, char** argv)
case 'o': case 'o':
print_output = (int)strtol(optarg, NULL, 10); print_output = (int)strtol(optarg, NULL, 10);
break; break;
case 'B':
batch_size = (int)strtol(optarg, NULL, 10);
break;
case 'N':
max_n_batch = (int)strtol(optarg, NULL, 10);
break;
case 'E':
req_errors = (int)strtol(optarg, NULL, 10);
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
@ -177,6 +158,13 @@ int main(int argc, char** argv)
uint8_t* output_enc = NULL; // output encoder uint8_t* output_enc = NULL; // output encoder
uint8_t* output_enc_avx2 = NULL; // output encoder uint8_t* output_enc_avx2 = NULL; // output encoder
uint8_t* rm_codeword = NULL; // output rate-matcher
float* rm_llr = NULL; // rate-matched llr
int16_t* rm_llr_s = NULL; // rate-matched llr
int8_t* rm_llr_c = NULL; // rate-matched llr
int8_t* rm_llr_c_avx2 = NULL; // rate-matched llr
float* llr = NULL; // input decoder float* llr = NULL; // input decoder
int16_t* llr_s = NULL; // input decoder int16_t* llr_s = NULL; // input decoder
int8_t* llr_c = NULL; // input decoder int8_t* llr_c = NULL; // input decoder
@ -190,17 +178,17 @@ int main(int argc, char** argv)
double var[SNR_POINTS + 1]; double var[SNR_POINTS + 1];
double snr_db_vec[SNR_POINTS + 1]; double snr_db_vec[SNR_POINTS + 1];
int i = 0;
int reportinfo = 0;
int j = 0; int j = 0;
int snr_points = 0; int snr_points = 0;
int errors_symb = 0; int errors_symb = 0;
int errors_symb_s = 0; int errors_symb_s = 0;
int errors_symb_c = 0; int errors_symb_c = 0;
#ifdef LV_HAVE_AVX
int errors_symb_c_avx2 = 0; int errors_symb_c_avx2 = 0;
#endif // LV_HAVE_AVX
int n_error_words[SNR_POINTS + 1]; int n_error_words[SNR_POINTS + 1];
int n_error_words_s[SNR_POINTS + 1]; int n_error_words_s[SNR_POINTS + 1];
@ -219,20 +207,22 @@ int main(int argc, char** argv)
double elapsed_time_enc_avx2[SNR_POINTS + 1]; double elapsed_time_enc_avx2[SNR_POINTS + 1];
// 16-bit quantizer // 16-bit quantizer
int16_t inf16 = (1U << 15U) - 1; int16_t inf16 = (1U << 15U) - 1;
int8_t inf8 = (1U << 7U) - 1; int8_t inf8 = (1U << 7U) - 1;
float gain_s = NAN; float gain_s = NAN;
float gain_c = NAN; float gain_c = NAN;
#ifdef LV_HAVE_AVX float gain_c_avx2 = NAN;
float gain_c_avx2 = NAN;
#endif // LV_HAVE_AVX2
srslte_polar_sets_t sets; srslte_polar_code_t code;
srslte_subchn_alloc_t subch;
srslte_polar_encoder_t enc; srslte_polar_encoder_t enc;
srslte_polar_decoder_t dec; srslte_polar_decoder_t dec;
srslte_polar_decoder_t dec_s; // 16-bit srslte_polar_decoder_t dec_s; // 16-bit
srslte_polar_decoder_t dec_c; // 8-bit srslte_polar_decoder_t dec_c; // 8-bit
srslte_polar_rm_t rm_tx;
srslte_polar_rm_t rm_rx_f;
srslte_polar_rm_t rm_rx_s;
srslte_polar_rm_t rm_rx_c;
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
srslte_polar_encoder_t enc_avx2; srslte_polar_encoder_t enc_avx2;
srslte_polar_decoder_t dec_c_avx2; // 8-bit srslte_polar_decoder_t dec_c_avx2; // 8-bit
@ -240,45 +230,40 @@ int main(int argc, char** argv)
parse_args(argc, argv); parse_args(argc, argv);
uint16_t code_size = 1U << code_size_log; // uinitialize polar code
srslte_polar_code_init(&code);
printf("Test POLAR chain:\n"); // initialize encoder pipeline
printf(" Final code bits -> E = %d\n", rate_matching_size); srslte_polar_encoder_init(&enc, SRSLTE_POLAR_ENCODER_PIPELINED, nMax);
printf(" Code bits -> N = %d\n", code_size);
printf(" CRC + Data bits -> K = %d\n", message_size);
printf(" Parity Check bits -> PC = %d \n", parity_set_size);
printf(" Code rate -> (K + PC)/N = (%d + %d)/%d = %.2f\n",
message_size,
parity_set_size,
code_size,
(double)(message_size + parity_set_size) / code_size);
// read polar index sets from a file // initialize rate-matcher
srslte_polar_code_sets_read(&sets, message_size, code_size_log, rate_matching_size, parity_set_size, nWmPC); srslte_polar_rm_tx_init(&rm_tx);
// subchannel allocation // initialize rate-matcher
srslte_subchannel_allocation_init(&subch, code_size_log, message_size, sets.message_set); srslte_polar_rm_rx_init_f(&rm_rx_f);
// initialize encoder pipeline // initialize rate-matcher
srslte_polar_encoder_init(&enc, SRSLTE_POLAR_ENCODER_PIPELINED, code_size_log); srslte_polar_rm_rx_init_s(&rm_rx_s);
// initialize rate-matcher
srslte_polar_rm_rx_init_c(&rm_rx_c);
// initialize a POLAR decoder (float) // initialize a POLAR decoder (float)
srslte_polar_decoder_init(&dec, SRSLTE_POLAR_DECODER_SSC_F, code_size_log, sets.frozen_set, sets.frozen_set_size); srslte_polar_decoder_init(&dec, SRSLTE_POLAR_DECODER_SSC_F, nMax);
// initialize a POLAR decoder (16 bit) // initialize a POLAR decoder (16 bit)
srslte_polar_decoder_init(&dec_s, SRSLTE_POLAR_DECODER_SSC_S, code_size_log, sets.frozen_set, sets.frozen_set_size); srslte_polar_decoder_init(&dec_s, SRSLTE_POLAR_DECODER_SSC_S, nMax);
// initialize a POLAR decoder (8 bit) // initialize a POLAR decoder (8 bit)
srslte_polar_decoder_init(&dec_c, SRSLTE_POLAR_DECODER_SSC_C, code_size_log, sets.frozen_set, sets.frozen_set_size); srslte_polar_decoder_init(&dec_c, SRSLTE_POLAR_DECODER_SSC_C, nMax);
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
// initialize encoder avx2 // initialize encoder avx2
srslte_polar_encoder_init(&enc_avx2, SRSLTE_POLAR_ENCODER_AVX2, code_size_log); srslte_polar_encoder_init(&enc_avx2, SRSLTE_POLAR_ENCODER_AVX2, nMax);
// initialize a POLAR decoder (8 bit, avx2) // initialize a POLAR decoder (8 bit, avx2)
srslte_polar_decoder_init( srslte_polar_decoder_init(&dec_c_avx2, SRSLTE_POLAR_DECODER_SSC_C_AVX2, nMax);
&dec_c_avx2, SRSLTE_POLAR_DECODER_SSC_C_AVX2, code_size_log, sets.frozen_set, sets.frozen_set_size);
#endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX2
#ifdef DATA_ALL_ONES #ifdef DATA_ALL_ONES
@ -286,29 +271,36 @@ int main(int argc, char** argv)
srslte_random_t random_gen = srslte_random_init(0); srslte_random_t random_gen = srslte_random_init(0);
#endif #endif
data_tx = srslte_vec_u8_malloc(message_size * batch_size); data_tx = srslte_vec_u8_malloc(K * BATCH_SIZE);
data_rx = srslte_vec_u8_malloc(message_size * batch_size); data_rx = srslte_vec_u8_malloc(K * BATCH_SIZE);
data_rx_s = srslte_vec_u8_malloc(message_size * batch_size); data_rx_s = srslte_vec_u8_malloc(K * BATCH_SIZE);
data_rx_c = srslte_vec_u8_malloc(message_size * batch_size); data_rx_c = srslte_vec_u8_malloc(K * BATCH_SIZE);
data_rx_c_avx2 = srslte_vec_u8_malloc(message_size * batch_size); data_rx_c_avx2 = srslte_vec_u8_malloc(K * BATCH_SIZE);
input_enc = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
output_enc = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
output_enc_avx2 = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
input_enc = srslte_vec_u8_malloc(code_size * batch_size); rm_codeword = srslte_vec_u8_malloc(E * BATCH_SIZE);
output_enc = srslte_vec_u8_malloc(code_size * batch_size);
output_enc_avx2 = srslte_vec_u8_malloc(code_size * batch_size);
llr = srslte_vec_f_malloc(code_size * batch_size); rm_llr = srslte_vec_f_malloc(E * BATCH_SIZE);
llr_s = srslte_vec_i16_malloc(code_size * batch_size); rm_llr_s = srslte_vec_i16_malloc(E * BATCH_SIZE);
llr_c = srslte_vec_i8_malloc(code_size * batch_size); rm_llr_c = srslte_vec_i8_malloc(E * BATCH_SIZE);
llr_c_avx2 = srslte_vec_i8_malloc(code_size * batch_size); rm_llr_c_avx2 = srslte_vec_i8_malloc(E * BATCH_SIZE);
output_dec = srslte_vec_u8_malloc(code_size * batch_size); llr = srslte_vec_f_malloc(NMAX * BATCH_SIZE);
output_dec_s = srslte_vec_u8_malloc(code_size * batch_size); llr_s = srslte_vec_i16_malloc(NMAX * BATCH_SIZE);
output_dec_c = srslte_vec_u8_malloc(code_size * batch_size); llr_c = srslte_vec_i8_malloc(NMAX * BATCH_SIZE);
output_dec_c_avx2 = srslte_vec_u8_malloc(code_size * batch_size); llr_c_avx2 = srslte_vec_i8_malloc(NMAX * BATCH_SIZE);
output_dec = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
output_dec_s = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
output_dec_c = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
output_dec_c_avx2 = srslte_vec_u8_malloc(NMAX * BATCH_SIZE);
if (!data_tx || !data_rx || !data_rx_s || !data_rx_c || !data_rx_c_avx2 || !input_enc || !output_enc || if (!data_tx || !data_rx || !data_rx_s || !data_rx_c || !data_rx_c_avx2 || !input_enc || !output_enc ||
!output_enc_avx2 || !llr || !llr_s || !llr_c || !llr_c_avx2 || !output_dec || !output_dec_s || !output_dec_c || !output_enc_avx2 || !rm_codeword || !rm_llr || !rm_llr_s || !rm_llr_c || !rm_llr_c_avx2 || !llr || !llr_s ||
!output_dec_c_avx2) { !llr_c || !llr_c_avx2 || !output_dec || !output_dec_s || !output_dec_c || !output_dec_c_avx2) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
@ -364,9 +356,14 @@ int main(int argc, char** argv)
int i_batch = 0; int i_batch = 0;
printf("\nBatch:\n "); printf("\nBatch:\n ");
int req_errors = 0;
int max_n_batch = 0;
if (snr_db_vec[i_snr] == 101) { if (snr_db_vec[i_snr] == 101) {
req_errors = 1; req_errors = 1;
max_n_batch = 1; max_n_batch = 1;
} else {
req_errors = REQ_ERRORS;
max_n_batch = MAX_N_BATCH;
} }
while ((n_error_words[i_snr] < req_errors) && (i_batch < max_n_batch)) { while ((n_error_words[i_snr] < req_errors) && (i_batch < max_n_batch)) {
@ -381,76 +378,104 @@ int main(int argc, char** argv)
// generate data_tx // generate data_tx
#ifdef DATA_ALL_ONES #ifdef DATA_ALL_ONES
for (i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
for (j = 0; j < message_size; j++) { for (j = 0; j < K; j++) {
data_tx[i * message_size + j] = 1; data_tx[i * K + j] = 1;
} }
} }
#else #else
for (uint32_t i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
for (j = 0; j < message_size; j++) { for (j = 0; j < K; j++) {
data_tx[i * message_size + j] = srslte_random_uniform_int_dist(random_gen, 0, 1); data_tx[i * K + j] = srslte_random_uniform_int_dist(random_gen, 0, 1);
} }
} }
#endif #endif
// get polar code, compute frozen_set (F_set), message_set (K_set) and parity bit set (PC_set)
if (srslte_polar_code_get(&code, K, E, nMax) == -1) {
return -1;
}
if (reportinfo == 0) {
reportinfo = 1;
printf("Test POLAR chain:\n");
printf(" Final code bits -> E = %d\n", E);
printf(" Code bits -> N = %d\n", code.N);
printf(" CRC + Data bits -> K = %d\n", K);
printf(" Parity Check bits -> PC = %d \n", code.nPC);
printf(" Code rate -> (K + PC)/N = (%d + %d)/%d = %.2f\n",
K,
code.nPC,
code.N,
(double)(K + code.nPC) / code.N);
}
// subchannel_allocation block // subchannel_allocation block
for (uint32_t i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
srslte_subchannel_allocation(&subch, data_tx + i * message_size, input_enc + i * code_size); srslte_polar_chanalloc_tx(
data_tx + i * K, input_enc + i * code.N, code.N, code.K, code.nPC, code.K_set, code.PC_set);
} }
// encoding pipeline // encoding pipeline
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_encoder_encode(&enc, input_enc + j * code_size, output_enc + j * code_size, code_size_log); srslte_polar_encoder_encode(&enc, input_enc + j * code.N, output_enc + j * code.N, code.n);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
elapsed_time_enc[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec; elapsed_time_enc[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// rate matcher
for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_rm_tx(&rm_tx, output_enc + j * code.N, rm_codeword + j * E, code.n, E, K, bil);
}
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
// encoding avx2 // encoding avx2
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_encoder_encode( srslte_polar_encoder_encode(&enc_avx2, input_enc + j * code.N, output_enc_avx2 + j * code.N, code.n);
&enc_avx2, input_enc + j * code_size, output_enc_avx2 + j * code_size, code_size_log);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
elapsed_time_enc_avx2[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec; elapsed_time_enc_avx2[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// check encoders have the same output.
// check errors with respect the output of the pipeline encoder // check errors with respect the output of the pipeline encoder
for (uint32_t i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
if (srslte_bit_diff(output_enc + i * code_size, output_enc_avx2 + i * code_size, code_size) != 0) { if (srslte_bit_diff(output_enc + i * code.N, output_enc_avx2 + i * code.N, code.N) != 0) {
printf("ERROR: Wrong avx2 encoder output. SNR= %f, Batch: %d\n", snr_db_vec[i_snr], i); printf("ERROR: Wrong avx2 encoder output. SNR= %f, Batch: %d\n", snr_db_vec[i_snr], i);
exit(-1); exit(-1);
} }
} }
#endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX2
for (j = 0; j < code_size * batch_size; j++) { for (j = 0; j < E * BATCH_SIZE; j++) {
llr[j] = output_enc[j] ? -1 : 1; rm_llr[j] = rm_codeword[j] ? -1 : 1;
} }
// add noise // add noise
if (snr_db_vec[i_snr] != 101) { if (snr_db_vec[i_snr] != 101) {
srslte_ch_awgn_f(llr, llr, var[i_snr], batch_size * code_size); srslte_ch_awgn_f(rm_llr, rm_llr, var[i_snr], BATCH_SIZE * E);
// Convert symbols into LLRs // Convert symbols into LLRs
for (j = 0; j < batch_size * code_size; j++) { for (j = 0; j < BATCH_SIZE * code.N; j++) {
llr[j] *= 2 / (var[i_snr] * var[i_snr]); rm_llr[j] *= 2 / (var[i_snr] * var[i_snr]);
} }
} }
// rate-Dematcher
for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_rm_rx_f(&rm_rx_f, rm_llr + j * E, llr + j * code.N, E, code.n, K, bil);
}
// decoding float point // decoding float point
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_decoder_decode_f(&dec, llr + j * code_size, output_dec + j * code_size); srslte_polar_decoder_decode_f(
&dec, llr + j * code.N, output_dec + j * code.N, code.n, code.F_set, code.F_set_size);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
@ -458,13 +483,16 @@ int main(int argc, char** argv)
elapsed_time_dec[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec; elapsed_time_dec[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// extract message bits - float decoder // extract message bits - float decoder
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_subchannel_deallocation(&subch, output_dec + j * code_size, data_rx + j * message_size); srslte_polar_chanalloc_rx(output_dec + j * code.N, data_rx + j * K, code.K, code.nPC, code.K_set, code.PC_set);
} }
// check errors - float decpder // check errors - float decpder
for (uint32_t i = 0; i < batch_size; i++) { #ifdef debug
errors_symb = srslte_bit_diff(data_tx + i * message_size, data_rx + i * message_size, message_size); int i_error = 0;
#endif
for (i = 0; i < BATCH_SIZE; i++) {
errors_symb = srslte_bit_diff(data_tx + i * K, data_rx + i * K, K);
if (errors_symb != 0) { if (errors_symb != 0) {
n_error_words[i_snr]++; n_error_words[i_snr]++;
@ -474,16 +502,23 @@ int main(int argc, char** argv)
// decoding 16-bit // decoding 16-bit
// 16-quantization // 16-quantization
if (snr_db_vec[i_snr] == 101) { if (snr_db_vec[i_snr] == 101) {
srslte_vec_quant_fs(llr, llr_s, 8192, 0, 32767, batch_size * code_size); srslte_vec_quant_fs(rm_llr, rm_llr_s, 8192, 0, 32767, BATCH_SIZE * E);
} else { } else {
gain_s = inf16 * var[i_snr] / 20 / (1 / var[i_snr] + 2); gain_s = inf16 * var[i_snr] / 20 / (1 / var[i_snr] + 2);
srslte_vec_quant_fs(llr, llr_s, gain_s, 0, inf16, batch_size * code_size); // printf("gain_s: %f, inf16:%d\n", gain_s, inf16);
srslte_vec_quant_fs(rm_llr, rm_llr_s, gain_s, 0, inf16, BATCH_SIZE * E);
}
// Rate dematcher
for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_rm_rx_s(&rm_rx_s, rm_llr_s + j * E, llr_s + j * code.N, E, code.n, K, bil);
} }
// decoding 16-bit // decoding 16-bit
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_decoder_decode_s(&dec_s, llr_s + j * code_size, output_dec_s + j * code_size); srslte_polar_decoder_decode_s(
&dec_s, llr_s + j * code.N, output_dec_s + j * code.N, code.n, code.F_set, code.F_set_size);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
@ -491,13 +526,14 @@ int main(int argc, char** argv)
elapsed_time_dec_s[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec; elapsed_time_dec_s[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// extract message bits 16-bit decoder // extract message bits 16-bit decoder
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_subchannel_deallocation(&subch, output_dec_s + j * code_size, data_rx_s + j * message_size); srslte_polar_chanalloc_rx(
output_dec_s + j * code.N, data_rx_s + j * K, code.K, code.nPC, code.K_set, code.PC_set);
} }
// check errors 16-bit decoder // check errors 16-bit decoder
for (uint32_t i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
errors_symb_s = srslte_bit_diff(data_tx + i * message_size, data_rx_s + i * message_size, message_size); errors_symb_s = srslte_bit_diff(data_tx + i * K, data_rx_s + i * K, K);
if (errors_symb_s != 0) { if (errors_symb_s != 0) {
n_error_words_s[i_snr]++; n_error_words_s[i_snr]++;
@ -507,29 +543,37 @@ int main(int argc, char** argv)
// 8-bit decoding // 8-bit decoding
// 8-bit quantization // 8-bit quantization
if (snr_db_vec[i_snr] == 101) { if (snr_db_vec[i_snr] == 101) {
srslte_vec_quant_fc(llr, llr_c, 32, 0, 127, batch_size * code_size); srslte_vec_quant_fc(rm_llr, rm_llr_c, 32, 0, 127, BATCH_SIZE * E);
} else { } else {
gain_c = inf8 * var[i_snr] / 20 / (1 / var[i_snr] + 2); gain_c = inf8 * var[i_snr] / 20 / (1 / var[i_snr] + 2);
srslte_vec_quant_fc(llr, llr_c, gain_c, 0, inf8, batch_size * code_size); srslte_vec_quant_fc(rm_llr, rm_llr_c, gain_c, 0, inf8, BATCH_SIZE * E);
}
// Rate dematcher
for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_rm_rx_c(&rm_rx_c, rm_llr_c + j * E, llr_c + j * code.N, E, code.n, K, bil);
} }
// Decoding
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_decoder_decode_c(&dec_c, llr_c + j * code_size, output_dec_c + j * code_size); srslte_polar_decoder_decode_c(
&dec_c, llr_c + j * code.N, output_dec_c + j * code.N, code.n, code.F_set, code.F_set_size);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
elapsed_time_dec_c[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec; elapsed_time_dec_c[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// extract message bits // extract message bits
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_subchannel_deallocation(&subch, output_dec_c + j * code_size, data_rx_c + j * message_size); srslte_polar_chanalloc_rx(
output_dec_c + j * code.N, data_rx_c + j * K, code.K, code.nPC, code.K_set, code.PC_set);
} }
// check errors 8-bits decoder // check errors 8-bits decoder
for (uint32_t i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
errors_symb_c = srslte_bit_diff(data_tx + i * message_size, data_rx_c + i * message_size, message_size); errors_symb_c = srslte_bit_diff(data_tx + i * K, data_rx_c + i * K, K);
if (errors_symb_c != 0) { if (errors_symb_c != 0) {
n_error_words_c[i_snr]++; n_error_words_c[i_snr]++;
@ -540,30 +584,36 @@ int main(int argc, char** argv)
// 8-bit avx2 decoding // 8-bit avx2 decoding
// 8-bit quantization // 8-bit quantization
if (snr_db_vec[i_snr] == 101) { if (snr_db_vec[i_snr] == 101) {
srslte_vec_quant_fc(llr, llr_c_avx2, 32, 0, 127, batch_size * code_size); srslte_vec_quant_fc(rm_llr, rm_llr_c_avx2, 32, 0, 127, BATCH_SIZE * E);
} else { } else {
gain_c_avx2 = inf8 * var[i_snr] / 20 / (1 / var[i_snr] + 2); gain_c_avx2 = inf8 * var[i_snr] / 20 / (1 / var[i_snr] + 2);
srslte_vec_quant_fc(llr, llr_c_avx2, gain_c_avx2, 0, inf8, batch_size * code_size); srslte_vec_quant_fc(rm_llr, rm_llr_c_avx2, gain_c_avx2, 0, inf8, BATCH_SIZE * E);
}
// Rate dematcher
for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_rm_rx_c(&rm_rx_c, rm_llr_c_avx2 + j * E, llr_c_avx2 + j * code.N, E, code.n, K, bil);
} }
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_polar_decoder_decode_c(&dec_c_avx2, llr_c_avx2 + j * code_size, output_dec_c_avx2 + j * code_size); srslte_polar_decoder_decode_c(
&dec_c_avx2, llr_c_avx2 + j * code.N, output_dec_c_avx2 + j * code.N, code.n, code.F_set, code.F_set_size);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
elapsed_time_dec_c_avx2[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec; elapsed_time_dec_c_avx2[i_snr] += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// extract message bits // extract message bits
for (j = 0; j < batch_size; j++) { for (j = 0; j < BATCH_SIZE; j++) {
srslte_subchannel_deallocation(&subch, output_dec_c_avx2 + j * code_size, data_rx_c_avx2 + j * message_size); srslte_polar_chanalloc_rx(
output_dec_c_avx2 + j * code.N, data_rx_c_avx2 + j * K, code.K, code.nPC, code.K_set, code.PC_set);
} }
// check errors 8-bits decoder // check errors 8-bits decoder
for (uint32_t i = 0; i < batch_size; i++) { for (i = 0; i < BATCH_SIZE; i++) {
errors_symb_c_avx2 = errors_symb_c_avx2 = srslte_bit_diff(data_tx + i * K, data_rx_c_avx2 + i * K, K);
srslte_bit_diff(data_tx + i * message_size, data_rx_c_avx2 + i * message_size, message_size);
if (errors_symb_c_avx2 != 0) { if (errors_symb_c_avx2 != 0) {
n_error_words_c_avx2[i_snr]++; n_error_words_c_avx2[i_snr]++;
@ -587,26 +637,26 @@ int main(int argc, char** argv)
printf("];\n"); printf("];\n");
printf("WER=["); printf("WER=[");
for (int i_snr = 0; i_snr < snr_points; i_snr++) { for (int i_snr = 0; i_snr < snr_points; i_snr++) {
printf("%e ", (float)n_error_words[i_snr] / last_i_batch[i_snr] / batch_size); printf("%e ", (float)n_error_words[i_snr] / last_i_batch[i_snr] / BATCH_SIZE);
} }
printf("];\n"); printf("];\n");
printf("WER_16=["); printf("WER_16=[");
for (int i_snr = 0; i_snr < snr_points; i_snr++) { for (int i_snr = 0; i_snr < snr_points; i_snr++) {
printf("%e ", (float)n_error_words_s[i_snr] / last_i_batch[i_snr] / batch_size); printf("%e ", (float)n_error_words_s[i_snr] / last_i_batch[i_snr] / BATCH_SIZE);
} }
printf("];\n"); printf("];\n");
printf("WER_8=["); printf("WER_8=[");
for (int i_snr = 0; i_snr < snr_points; i_snr++) { for (int i_snr = 0; i_snr < snr_points; i_snr++) {
printf("%e ", (float)n_error_words_c[i_snr] / last_i_batch[i_snr] / batch_size); printf("%e ", (float)n_error_words_c[i_snr] / last_i_batch[i_snr] / BATCH_SIZE);
} }
printf("];\n"); printf("];\n");
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
printf("WER_8_AVX2=["); printf("WER_8_AVX2=[");
for (int i_snr = 0; i_snr < snr_points; i_snr++) { for (int i_snr = 0; i_snr < snr_points; i_snr++) {
printf("%e ", (float)n_error_words_c_avx2[i_snr] / last_i_batch[i_snr] / batch_size); printf("%e ", (float)n_error_words_c_avx2[i_snr] / last_i_batch[i_snr] / BATCH_SIZE);
} }
printf("];\n"); printf("];\n");
#endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX2
@ -616,34 +666,34 @@ int main(int argc, char** argv)
printf("SNR: %3.1f\t enc_pipe_thrpt(Mbps): %.2f\t enc_avx2_thrpt(Mbps): " printf("SNR: %3.1f\t enc_pipe_thrpt(Mbps): %.2f\t enc_avx2_thrpt(Mbps): "
"%.2f\n", "%.2f\n",
snr_db_vec[i_snr], snr_db_vec[i_snr],
last_i_batch[i_snr] * batch_size * code_size / (1000000 * elapsed_time_enc[i_snr]), last_i_batch[i_snr] * BATCH_SIZE * code.N / (1000000 * elapsed_time_enc[i_snr]),
last_i_batch[i_snr] * batch_size * code_size / (1000000 * elapsed_time_enc_avx2[i_snr])); last_i_batch[i_snr] * BATCH_SIZE * code.N / (1000000 * elapsed_time_enc_avx2[i_snr]));
printf("SNR: %3.1f\t FLOAT WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n", printf("SNR: %3.1f\t FLOAT WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n",
snr_db_vec[i_snr], snr_db_vec[i_snr],
(double)n_error_words[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words[i_snr], n_error_words[i_snr],
last_i_batch[i_snr] * batch_size * code_size, last_i_batch[i_snr] * BATCH_SIZE * code.N,
last_i_batch[i_snr] * batch_size * code_size / (1000000 * elapsed_time_dec[i_snr])); last_i_batch[i_snr] * BATCH_SIZE * code.N / (1000000 * elapsed_time_dec[i_snr]));
printf("SNR: %3.1f\t INT16 WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n", printf("SNR: %3.1f\t INT16 WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n",
snr_db_vec[i_snr], snr_db_vec[i_snr],
(double)n_error_words_s[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words_s[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words_s[i_snr], n_error_words_s[i_snr],
last_i_batch[i_snr] * batch_size * code_size, last_i_batch[i_snr] * BATCH_SIZE * code.N,
last_i_batch[i_snr] * batch_size * code_size / (1000000 * elapsed_time_dec_s[i_snr])); last_i_batch[i_snr] * BATCH_SIZE * code.N / (1000000 * elapsed_time_dec_s[i_snr]));
printf("SNR: %3.1f\t INT8 WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n", printf("SNR: %3.1f\t INT8 WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n",
snr_db_vec[i_snr], snr_db_vec[i_snr],
(double)n_error_words_c[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words_c[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words_c[i_snr], n_error_words_c[i_snr],
last_i_batch[i_snr] * batch_size * code_size, last_i_batch[i_snr] * BATCH_SIZE * code.N,
last_i_batch[i_snr] * batch_size * code_size / (1000000 * elapsed_time_dec_c[i_snr])); last_i_batch[i_snr] * BATCH_SIZE * code.N / (1000000 * elapsed_time_dec_c[i_snr]));
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
printf("SNR: %3.1f\t INT8-AVX2 WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n", printf("SNR: %3.1f\t INT8-AVX2 WER: %.8f %d/%d \t dec_thrput(Mbps): %.2f\n",
snr_db_vec[i_snr], snr_db_vec[i_snr],
(double)n_error_words_c_avx2[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words_c_avx2[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words_c_avx2[i_snr], n_error_words_c_avx2[i_snr],
last_i_batch[i_snr] * batch_size * code_size, last_i_batch[i_snr] * BATCH_SIZE * code.N,
last_i_batch[i_snr] * batch_size * code_size / (1000000 * elapsed_time_dec_c_avx2[i_snr])); last_i_batch[i_snr] * BATCH_SIZE * code.N / (1000000 * elapsed_time_dec_c_avx2[i_snr]));
#endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX2
printf("\n"); printf("\n");
} }
@ -654,97 +704,108 @@ int main(int argc, char** argv)
for (int i_snr = 0; i_snr < snr_points; i_snr++) { for (int i_snr = 0; i_snr < snr_points; i_snr++) {
printf("**** PIPELINE ENCODER ****\n"); printf("**** PIPELINE ENCODER ****\n");
printf("Estimated throughput:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n", printf("Estimated throughput:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
last_i_batch[i_snr] * batch_size / elapsed_time_enc[i_snr], last_i_batch[i_snr] * BATCH_SIZE / elapsed_time_enc[i_snr],
last_i_batch[i_snr] * batch_size * message_size / elapsed_time_enc[i_snr], last_i_batch[i_snr] * BATCH_SIZE * K / elapsed_time_enc[i_snr],
last_i_batch[i_snr] * batch_size * code_size / elapsed_time_enc[i_snr]); last_i_batch[i_snr] * BATCH_SIZE * code.N / elapsed_time_enc[i_snr]);
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
printf("\n**** AVX2 ENCODER ****\n"); printf("\n**** AVX2 ENCODER ****\n");
printf("Estimated throughput:\n %e word/s\n %e bit/s (information)\n %e bit/s " printf("Estimated throughput:\n %e word/s\n %e bit/s (information)\n %e bit/s "
"(encoded)\n", "(encoded)\n",
last_i_batch[i_snr] * batch_size / elapsed_time_enc_avx2[i_snr], last_i_batch[i_snr] * BATCH_SIZE / elapsed_time_enc_avx2[i_snr],
last_i_batch[i_snr] * batch_size * message_size / elapsed_time_enc_avx2[i_snr], last_i_batch[i_snr] * BATCH_SIZE * K / elapsed_time_enc_avx2[i_snr],
last_i_batch[i_snr] * batch_size * code_size / elapsed_time_enc_avx2[i_snr]); last_i_batch[i_snr] * BATCH_SIZE * code.N / elapsed_time_enc_avx2[i_snr]);
#endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX2
printf("\n**** FLOATING POINT ****"); printf("\n**** FLOATING POINT ****");
printf("\nEstimated word error rate:\n %e (%d errors)\n", printf("\nEstimated word error rate:\n %e (%d errors)\n",
(double)n_error_words[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words[i_snr]); n_error_words[i_snr]);
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n", printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
last_i_batch[i_snr] * batch_size / elapsed_time_dec[i_snr], last_i_batch[i_snr] * BATCH_SIZE / elapsed_time_dec[i_snr],
last_i_batch[i_snr] * batch_size * message_size / elapsed_time_dec[i_snr], last_i_batch[i_snr] * BATCH_SIZE * K / elapsed_time_dec[i_snr],
last_i_batch[i_snr] * batch_size * code_size / elapsed_time_dec[i_snr]); last_i_batch[i_snr] * BATCH_SIZE * code.N / elapsed_time_dec[i_snr]);
printf("\n**** FIXED POINT (16 bits) ****"); printf("\n**** FIXED POINT (16 bits) ****");
printf("\nEstimated word error rate:\n %e (%d errors)\n", printf("\nEstimated word error rate:\n %e (%d errors)\n",
(double)n_error_words_s[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words_s[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words_s[i_snr]); n_error_words_s[i_snr]);
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n", printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
last_i_batch[i_snr] * batch_size / elapsed_time_dec_s[i_snr], last_i_batch[i_snr] * BATCH_SIZE / elapsed_time_dec_s[i_snr],
last_i_batch[i_snr] * batch_size * message_size / elapsed_time_dec_s[i_snr], last_i_batch[i_snr] * BATCH_SIZE * K / elapsed_time_dec_s[i_snr],
last_i_batch[i_snr] * batch_size * code_size / elapsed_time_dec_s[i_snr]); last_i_batch[i_snr] * BATCH_SIZE * code.N / elapsed_time_dec_s[i_snr]);
printf("\n**** FIXED POINT (8 bits) ****"); printf("\n**** FIXED POINT (8 bits) ****");
printf("\nEstimated word error rate:\n %e (%d errors)\n", printf("\nEstimated word error rate:\n %e (%d errors)\n",
(double)n_error_words_c[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words_c[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words_c[i_snr]); n_error_words_c[i_snr]);
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n", printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
last_i_batch[i_snr] * batch_size / elapsed_time_dec_c[i_snr], last_i_batch[i_snr] * BATCH_SIZE / elapsed_time_dec_c[i_snr],
last_i_batch[i_snr] * batch_size * message_size / elapsed_time_dec_c[i_snr], last_i_batch[i_snr] * BATCH_SIZE * K / elapsed_time_dec_c[i_snr],
last_i_batch[i_snr] * batch_size * code_size / elapsed_time_dec_c[i_snr]); last_i_batch[i_snr] * BATCH_SIZE * code.N / elapsed_time_dec_c[i_snr]);
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
printf("\n**** FIXED POINT (8 bits, AVX2) ****"); printf("\n**** FIXED POINT (8 bits, AVX2) ****");
printf("\nEstimated word error rate:\n %e (%d errors)\n", printf("\nEstimated word error rate:\n %e (%d errors)\n",
(double)n_error_words_c_avx2[i_snr] / last_i_batch[i_snr] / batch_size, (double)n_error_words_c_avx2[i_snr] / last_i_batch[i_snr] / BATCH_SIZE,
n_error_words_c_avx2[i_snr]); n_error_words_c_avx2[i_snr]);
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n", printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
last_i_batch[i_snr] * batch_size / elapsed_time_dec_c_avx2[i_snr], last_i_batch[i_snr] * BATCH_SIZE / elapsed_time_dec_c_avx2[i_snr],
last_i_batch[i_snr] * batch_size * message_size / elapsed_time_dec_c_avx2[i_snr], last_i_batch[i_snr] * BATCH_SIZE * K / elapsed_time_dec_c_avx2[i_snr],
last_i_batch[i_snr] * batch_size * code_size / elapsed_time_dec_c_avx2[i_snr]); last_i_batch[i_snr] * BATCH_SIZE * code.N / elapsed_time_dec_c_avx2[i_snr]);
#endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX2
printf("\n"); printf("\n");
} }
break; break;
} }
free(data_tx); free(data_tx);
free(data_rx); free(data_rx);
free(data_rx_s); free(data_rx_s);
free(data_rx_c); free(data_rx_c);
free(data_rx_c_avx2);
free(input_enc); free(input_enc);
free(output_enc); free(output_enc);
free(output_enc_avx2);
free(rm_codeword);
free(rm_llr);
free(rm_llr_s);
free(rm_llr_c);
free(rm_llr_c_avx2);
free(llr); free(llr);
free(llr_s); free(llr_s);
free(llr_c); free(llr_c);
free(llr_c_avx2); free(llr_c_avx2);
free(output_dec); free(output_dec);
free(output_dec_s); free(output_dec_s);
free(output_dec_c); free(output_dec_c);
free(output_dec_c_avx2); free(output_dec_c_avx2);
free(output_enc_avx2);
free(data_rx_c_avx2);
#ifdef DATA_ALL_ONES #ifdef DATA_ALL_ONES
#else #else
srslte_random_free(random_gen); srslte_random_free(random_gen);
#endif #endif
// free sets // free code
srslte_polar_code_sets_free(&sets); srslte_polar_code_free(&code);
srslte_polar_encoder_free(&enc); srslte_polar_encoder_free(&enc);
srslte_polar_decoder_free(&dec); srslte_polar_decoder_free(&dec);
srslte_polar_decoder_free(&dec_s); srslte_polar_decoder_free(&dec_s);
srslte_polar_decoder_free(&dec_c); srslte_polar_decoder_free(&dec_c);
srslte_polar_rm_rx_free_f(&rm_rx_f);
srslte_polar_rm_rx_free_s(&rm_rx_s);
srslte_polar_rm_rx_free_c(&rm_rx_c);
srslte_polar_rm_tx_free(&rm_tx);
#ifdef LV_HAVE_AVX2 #ifdef LV_HAVE_AVX2
srslte_polar_encoder_free(&enc_avx2); srslte_polar_encoder_free(&enc_avx2);
srslte_polar_decoder_free(&dec_c_avx2); srslte_polar_decoder_free(&dec_c_avx2);
@ -791,7 +852,7 @@ int main(int argc, char** argv)
); );
} else { } else {
for (i_snr = 0; i_snr < snr_points; i_snr++) { for (int i_snr = 0; i_snr < snr_points; i_snr++) {
if (n_error_words_s[i_snr] > 10 * n_error_words[i_snr]) { if (n_error_words_s[i_snr] > 10 * n_error_words[i_snr]) {
perror("16-bit performance at SNR = %d too low!"); perror("16-bit performance at SNR = %d too low!");
exit(-1); exit(-1);

Loading…
Cancel
Save