free5GRAN  V1.0
transport_channel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Telecom Paris
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16 
17 #include "transport_channel.h"
18 #include "../../variables/common_variables/common_variables.h"
19 #include "../../variables/common_matrices/common_matrices.h"
20 #include "../../variables/ldpc_matrices/ldpc_matrices.h"
21 #include "../libphy/libphy.h"
22 #include "../../utils/sequence_generator/sequence_generator.h"
23 #include "../../asn1c/nr_rrc/BCCH-DL-SCH-Message.h"
24 #include "../../utils/common_utils/common_utils.h"
25 #include <math.h>
26 #include <iostream>
27 #include <vector>
28 #include <cmath>
29 #include <thread>
30 #include <limits>
31 #include <algorithm>
32 #include <fstream>
33 #include <boost/log/core.hpp>
34 #include <boost/log/trivial.hpp>
35 #include <boost/log/expressions.hpp>
36 #include <boost/log/utility/setup/file.hpp>
37 #include <boost/log/utility/setup/common_attributes.hpp>
38 
39 using namespace std;
40 
53  int n1, n2;
54  float rmin = 1.0/8.0;
55  if (E <= (9.0/8.0) * pow(2,ceil(log2(E))-1) && (float) K / (float) E < 9.0/16.0){
56  n1 = ceil(log2(E))-1;
57  }else{
58  n1 = ceil(log2(E));
59  }
60  n2 = ceil(log2((float) K / rmin));
61  if (nmax < 5 && n1 < 5 && n2 < 5){
62  return 5;
63  }else {
64  if (n1 < n2 && n1 < nmax){
65  return n1;
66  }else if (n2 < n1 && n2 < nmax){
67  return n2;
68  }else {
69  return nmax;
70  }
71  }
72 }
73 
74 void free5GRAN::phy::transport_channel::rate_recover(int *input_bits, int *output_bits, int i_bil, int E, int N, int K) {
87  int e[E], y[N];
88  /*
89  * Coded bit-interleaving/de-interleaving TS38.212 5.4.1.3
90  * No coded-bits interleaving
91  */
92  if (i_bil == 0){
93  for (int n = 0; n < E; n ++){
94  e[n] = input_bits[n];
95  }
96  }
97  /*
98  * Bit de-selection TS38.212 5.4.1.2
99  */
100  if (E >= N){
101  for (int n = 0; n < N; n ++){
102  y[n] = e[n];
103  }
104  }else {
105  if ((float) K / (float) E <= 7.0/16.0){
106  for (int n = 0; n < N - E; n ++){
107  y[n] = 0;
108  }
109  for (int n = 0; n < E; n ++){
110  y[n + N - E] = e[n];
111  }
112  }
113  }
114 
115  /*
116  * Sub-block de-interleaving TS38.212 5.4.1.1
117  */
118  for (int n = 0; n < N; n++){
119  int i = floor(32 * (double) n / (double) N );
120  int j_n = free5GRAN::SUB_BLOCK_INTERLEAVER_PATTERN[i] * N / 32 + n % (N / 32);
121  output_bits[j_n] = y[n];
122  }
123 }
124 
125 void free5GRAN::phy::transport_channel::polar_decode(int *input_bits, int *output_bits, int N, int K, int nmax, int i_il, int n_pc,
126  int n_wm_pc, int E) {
149  int q_0_n_1[N], count_seq, q_i_n[K + n_pc], c_p[K], pi_seq[K], j_n, u[N];
150  int K_max = 164;
151  bool found;
152 
153  /*
154  * polar decoding using Gn inverse matrix (TS38.212 5.3.1.2)
155  */
156  switch(N) {
157  case 32: {
158  for (int n = 0; n < N; n++){
159  u[n] = 0;
160  for (int p = 0 ; p < N; p++){
161  u[n] ^= (input_bits[p] * free5GRAN::G5_INV[p][n]);
162  }
163  }
164  };
165  case 64: {
166  for (int n = 0; n < N; n++){
167  u[n] = 0;
168  for (int p = 0 ; p < N; p++){
169  u[n] ^= (input_bits[p] * free5GRAN::G6_INV[p][n]);
170  }
171  }
172  };
173  case 128: {
174  for (int n = 0; n < N; n++){
175  u[n] = 0;
176  for (int p = 0 ; p < N; p++){
177  u[n] ^= (input_bits[p] * free5GRAN::G7_INV[p][n]);
178  }
179  }
180  };
181  case 256: {
182  for (int n = 0; n < N; n++){
183  u[n] = 0;
184  for (int p = 0 ; p < N; p++){
185  u[n] ^= (input_bits[p] * free5GRAN::G8_INV[p][n]);
186  }
187  }
188  };
189  case 512: {
190  for (int n = 0; n < N; n++){
191  u[n] = 0;
192  for (int p = 0 ; p < N; p++){
193  u[n] ^= (input_bits[p] * free5GRAN::G9_INV[p][n]);
194  }
195  }
196  };
197  case 1024: {
198  for (int n = 0; n < N; n++){
199  u[n] = 0;
200  for (int p = 0 ; p < N; p++){
201  u[n] ^= (input_bits[p] * free5GRAN::G10_INV[p][n]);
202  }
203  }
204  };
205  }
206 
207  count_seq = 0;
208  vector<int> q_ftmp_n, q_itmp_n;
209 
210  /*
211  * Computing q_0_n_1 (TS38.212 5.3.1.2)
212  */
213  for (int n = 0; n < 1024; n++){
215  q_0_n_1[count_seq] = free5GRAN::POLAR_SEQUENCE_QNMAX_AND_RELIABILITY[n];
216  count_seq++;
217  }
218  }
219 
220 
221  if (E < N){
222  if ((float) K / (float) E <= 7.0/16.0){
223  for (int n = 0; n < N - E; n ++){
224  int i = floor(32 * (double) n / (double) N );
225  j_n = free5GRAN::SUB_BLOCK_INTERLEAVER_PATTERN[i] * N / 32 + n % (N / 32);
226  q_ftmp_n.push_back(j_n);
227  }
228  if (E >= 3.0 * (float) N / 4.0){
229  for (int n = 0; n < ceil(3.0 * (float) N / 4.0 - (float) E / 2.0); n ++){
230  q_ftmp_n.push_back(n);
231  }
232  }else {
233  for (int n = 0; n < ceil(9.0 * (float) N / 16.0 - (float) E / 4.0); n ++){
234  q_ftmp_n.push_back(n);
235  }
236  }
237  }
238  }
239 
240  for (int n = 0; n < N; n++){
241  found = false;
242  for (int x = 0; x < q_ftmp_n.size(); x ++){
243  if (q_0_n_1[n] == q_ftmp_n[x]){
244  found = true;
245  break;
246  }
247  }
248  if (!found){
249  q_itmp_n.push_back(q_0_n_1[n]);
250  }
251  }
252  /*
253  * Computing q_i_n (TS38.212 5.3.1.2)
254  */
255  for (int n = 0; n < K + n_pc; n++){
256  q_i_n[n] = q_itmp_n[q_itmp_n.size() - ( K + n_pc) + n];
257  }
258  count_seq = 0;
259  /*
260  * Recovering c' from u_n (TS38.212 5.3.1.2)
261  */
262  for (int n = 0; n < N; n++){
263  found = false;
264  for (int p = 0; p < K + n_pc; p ++){
265  if (q_i_n[p] == n){
266  found = true;
267  break;
268  }
269  }
270  if (found){
271  c_p[count_seq] = u[n];
272  count_seq ++;
273  }
274  }
275  count_seq = 0;
276  /*
277  * generating pi sequence (TS38.212 5.3.1.1)
278  */
279  for (int m = 0; m < K_max; m++){
280  if (free5GRAN::INTERLEAVING_PATTERN[m] >= K_max - K){
281  pi_seq[count_seq] = free5GRAN::INTERLEAVING_PATTERN[m] - (K_max - K);
282  count_seq++;
283  }
284  }
285  /*
286  * de-interleaving c' to recover output sequence (TS38.212 5.3.1.1)
287  */
288  for (int k = 0; k < K ; k ++){
289  output_bits[pi_seq[k]] = c_p[k];
290  }
291 
292 
293 }
294 
295 
296 
297 void free5GRAN::phy::transport_channel::crc_validate(int *input_bits, int *crc_polynom, int *remainder, int length_input, int length_crc) {
310  int num_steps, seq1[length_crc];
311 
312  /*
313  * Getting index of first 1 in input_bits
314  */
315  int index_0 = -1;
316  for (int i = 0; i < length_input; i ++){
317  if (input_bits[i] == 1){
318  index_0 = i;
319  break;
320  }
321  }
322  /*
323  * Creating a new input called temp_input by removing all 0 from the beginning of input_bits
324  */
325  int temp_input[length_input - index_0];
326  for (int i = 0; i < length_input - index_0; i ++){
327  temp_input[i] = input_bits[index_0 + i];
328  }
329  length_input = length_input - index_0;
330  num_steps = length_input - length_crc + 1;
331 
332  /*
333  * seq1 is the variable that will be XORed with crc_polynom step after step
334  * Initializing seq1 variable to the first bits of temp_input
335  */
336  for (int i = 0; i < length_crc; i ++){
337  seq1[i] = temp_input[i];
338  }
339 
340  int i = 0;
341 
342  /*
343  * Iterate until the polynom reaches the end of temp_input
344  */
345  while(i <num_steps){
346  /*
347  * XORing seq1 and crc_polynom
348  */
349  for (int j = 0; j < length_crc; j ++){
350  remainder[j] = seq1[j] ^ crc_polynom[j];
351  }
352  /*
353  * Checing if the remainder is equal to 0. If true, algorithm ends
354  */
355  bool validated = true;
356  for (int j = 1; j < length_crc; j ++){
357  if (remainder[j] ==1){
358  validated = false;
359  break;
360  }
361  }
362  if (validated){
363  break;
364  }
365  /*
366  * Searching first 1 index in remainder
367  */
368  int index_1 = -1;
369  for (int j = 1; j < length_crc; j ++){
370  if (remainder[j] == 1){
371  index_1 = j;
372  break;
373  }
374  }
375  /*
376  * seq1 is updated to be the remainder shifted until finding the first 1
377  */
378  for (int j = 0; j < length_crc - index_1; j ++){
379  seq1[j] = remainder[j + index_1];
380  }
381  /*
382  * Adding new entries from temp_input to fill seq1
383  */
384  for (int j = 0; j < index_1; j ++){
385  seq1[length_crc - index_1 + j] = temp_input[length_crc + i + j];
386  }
387  i += index_1;
388  }
389 
390 }
391 
392 void free5GRAN::phy::transport_channel::compute_crc(int *input_bits, int *crc_polynom, int *remainder, int length_input, int length_crc) {
405  int num_steps, *seq1;
406 
407  /*
408  * Getting index of first 1 in input_bits
409  */
410  int index_0 = -1;
411  for (int i = 0; i < length_input; i ++){
412  if (input_bits[i] == 1){
413  index_0 = i;
414  break;
415  }
416  }
417  /*
418  * Creating a new input called temp_input by removing all 0 from the beginning of input_bits
419  * Adding (length_crc - 1) zeros to complete temp_input
420  */
421  int temp_input[length_input - index_0 + length_crc - 1];
422  for (int i = 0; i < length_input - index_0; i ++){
423  temp_input[i] = input_bits[index_0 + i];
424  }
425  for (int i = 0; i < length_crc - 1; i ++){
426  temp_input[length_input - index_0 + i] = 0;
427  }
428  length_input = length_input - index_0;
429  num_steps = length_input;
430 
431  /*
432  * Iterate until the polynom reaches the end of temp_input
433  */
434  int i = 0;
435  while(i <num_steps){
436  /*
437  * XORing temp_input and crc_polynom
438  */
439  for (int j = 0; j < length_crc; j ++){
440  temp_input[i + j] ^= crc_polynom[j];
441  }
442  /*
443  * Checing if temp_input (for the first length_input bits) is equal to 0. If true, algorithm ends
444  */
445  bool finished = true;
446  for (int j = 0; j < length_input; j ++){
447  if (temp_input[j] == 1){
448  finished = false;
449  break;
450  }
451  }
452  if (finished){
453  break;
454  }
455  /*
456  * Shifting until finding a 1 (at least once)
457  */
458  i++;
459  while (temp_input[i] != 1){
460  i++;
461  }
462  }
463  /*
464  * Remainder corresponds to the (length_crc - 1) last bits of temp_input
465  */
466  for (int j = 0; j < length_crc - 1; j ++){
467  remainder[j] = temp_input[length_input + j];
468  }
469 }
470 
481  if (A <= 292 || (A <= 3824 && R <= 0.67) || R <= 0.25){
482  graph = 2;
483  }else {
484  graph = 1;
485  }
486 }
487 
488 void free5GRAN::phy::transport_channel::compute_transport_block_size(int n_re, float R, int mod_order, int num_layers, int nrb, int &tbs){
503  long nre = (long) min(156, n_re) * nrb;
504  double n_info = (double) nre * R * mod_order * num_layers;
505  if (n_info <= 3824){
506  long n = (int) max(3.0, floor(log2(n_info)) - 6);
507  long n_p_info = max(24.0, pow(2,n) * floor((double) n_info/pow(2,n)));
508  for (int i =0; i < 93; i ++){
509  if (free5GRAN::TS_38_214_TABLE_5_1_3_2_1[i] >= n_p_info ){
511  break;
512  }
513  }
514  }else {
515  cout << "N INFO not supported !" << endl;
516  }
517 
518 }
519 
520 /*
521  * TS 38 212 5.2.2
522  */
523 void free5GRAN::phy::transport_channel::compute_Zc_dl_sch(int kb, float k_p, int &Zc, int &i_ls){
534  Zc = 512;
535  for (int i = 0; i < 8; i ++){
536  for (int j = 0; j < 8; j ++){
537  if (TS_38_212_TABLE_5_3_2_1[i][j] < Zc && TS_38_212_TABLE_5_3_2_1[i][j] >= (k_p / (float) kb)){
538  Zc = TS_38_212_TABLE_5_3_2_1[i][j];
539  i_ls = i;
540  }
541  }
542  }
543 }
544 
545 void free5GRAN::phy::transport_channel::compute_code_block_segmentation_info_ldpc(int graph, int B, int &Zc, int &K, int &i_ls, int &L, int &C, int &N, int &K_p){
561  int k_b, B_p;
562  int k_cb = (graph == 1) ? 8448 : 3840;
563  if (B <= k_cb){
564  L = 0;
565  C = 1;
566  B_p = B;
567  }else {
568  L = 24;
569  C = ceil(B / (k_cb - L));
570  B_p = B + C * L;
571  }
572  float k_p = (float) B_p / (float) C;
573  if (graph == 1){
574  k_b = 22;
575  }else {
576  if (B > 640){
577  k_b = 10;
578  }else if (B > 560){
579  k_b = 9;
580  }else if (B > 192){
581  k_b = 8;
582  }else {
583  k_b = 6;
584  }
585  }
586  compute_Zc_dl_sch(k_b, k_p, Zc, i_ls);
587  K = (graph == 1) ? 22 * Zc : 10 * Zc;
588  N = (graph == 1) ? 66 * Zc : 50 * Zc;
589  K_p = (int) k_p;
590 }
591 
592 void free5GRAN::phy::transport_channel::rate_recover_ldpc(int *input_bits, int N, int i_lbrm, int E, int id_rv, int mod_order, int C, int Zc, int graph, int K, int K_p, int *output_sequence){
611  int N_cb = (i_lbrm == 0) ? N : min(N, 25344);
612  int e[E];
613  int E_Q = (int) ((float) E / (float) mod_order);
614  /*
615  * Input de-interleaving
616  */
617  for (int j = 0; j < E_Q; j ++){
618  for (int i = 0; i < mod_order; i ++){
619  e[i * (E_Q) +j] = input_bits[i + j * mod_order];
620  }
621  }
622  /*
623  * Compute k0
624  */
625  int k0, k, j;
626  if (id_rv == 0){
627  k0 = 0;
628  }else if (id_rv == 1){
629  k0 = (graph == 1) ? floor((17.0 * N_cb) / (66.0 * Zc)) * Zc : floor((13.0 * N_cb) / (50.0 * Zc)) * Zc;
630  }else if (id_rv == 2){
631  k0 = (graph == 1) ? floor((33.0 * N_cb) / (66.0 * Zc)) * Zc : floor((25.0 * N_cb) / (50.0 * Zc)) * Zc;
632  }else if (id_rv == 3){
633  k0 = (graph == 1) ? floor((56.0 * N_cb) / (66.0 * Zc)) * Zc : floor((43.0 * N_cb) / (50.0 * Zc)) * Zc;
634  }
635 
636  /*
637  * rate recovering
638  */
639  j = 0;
640  k = 0;
641  while(k < E){
642  int index = (k0 + j) % N_cb;
643  if (index >= K_p - 2 * Zc && index < K - 2 * Zc){
644  output_sequence[index] = -1;
645  }else {
646  output_sequence[index] = e[k];
647  k ++;
648  }
649  j ++;
650  }
651 }
652 
653 void free5GRAN::phy::transport_channel::rate_recover_ldpc(double *input_bits, int N, int i_lbrm, int E, int id_rv, int mod_order, int C, int Zc, int graph, int K, int K_p, double *output_sequence){
672  int N_cb = (i_lbrm == 0) ? N : min(N, 25344);
673  double e[E];
674  int E_Q = (int) ((float) E / (float) mod_order);
675  /*
676  * Input de-interleaving
677  */
678  for (int j = 0; j < E_Q; j ++){
679  for (int i = 0; i < mod_order; i ++){
680  e[i * (E_Q) +j] = input_bits[i + j * mod_order];
681  }
682  }
683 
684  int k0, k, index, j;
685  if (id_rv == 0){
686  k0 = 0;
687  }else if (id_rv == 1){
688  k0 = (graph == 1) ? floor((17.0 * N_cb) / (66.0 * Zc)) * Zc : floor((13.0 * N_cb) / (50.0 * Zc)) * Zc;
689  }else if (id_rv == 2){
690  k0 = (graph == 1) ? floor((33.0 * N_cb) / (66.0 * Zc)) * Zc : floor((25.0 * N_cb) / (50.0 * Zc)) * Zc;
691  }else if (id_rv == 3){
692  k0 = (graph == 1) ? floor((56.0 * N_cb) / (66.0 * Zc)) * Zc : floor((43.0 * N_cb) / (50.0 * Zc)) * Zc;
693  }
694 
695  vector<int> seen_indexes;
696  /*
697  * rate recovering
698  */
699  j = 0;
700  k = 0;
701  while(k < E){
702  index = (k0 + j) % N_cb;
703  if (find(seen_indexes.begin(), seen_indexes.end(), index) == seen_indexes.end()){
704  seen_indexes.push_back(index);
705  if (index >= K_p - 2 * Zc && index < K - 2 * Zc){
706  output_sequence[index] = numeric_limits<double>::infinity();;
707  }else {
708  output_sequence[index] = e[k];
709  k ++;
710  }
711  }
712  j ++;
713 
714  }
715 
716 }
717 
726  for (int i = 0; i < size; i ++){
727  for (int j = 0; j < size; j ++){
728  matrix[i][j] = 0;
729  }
730  matrix[i][(i + offset) % size] = 1;
731  }
732 }
733 
734 
735 void free5GRAN::phy::transport_channel::ldpc_decode_one_bit(vector<vector<int>> R, double *soft_bits, int i, double &new_bit){
744  double r_p1[R.size()], r_prop, q_p1, q_m1, n_q_p1, n_q_m1;
745  /*
746  * Compute rj for each element in R
747  */
748  for (int j = 0; j < R.size(); j ++){
749  r_p1[j] = 1;
750  for (int i_p = 0; i_p < R[j].size(); i_p ++){
751  r_prop = 1 / (1 + exp(2 * soft_bits[R[j][i_p]]));
752  r_p1[j] *= 1 - 2 * r_prop;
753  }
754  r_p1[j] = 0.5 + 0.5 * r_p1[j];
755  }
756  /*
757  * Compute updated bit probabilities
758  */
759  q_m1 = 1;
760  q_p1 = 1;
761  for (int j = 0; j < R.size(); j ++){
762  q_p1 *= r_p1[j];
763  q_m1 *= (1 - r_p1[j]);
764  }
765  r_prop = 1 / (1 + exp(2 * soft_bits[i]));
766  q_m1 = r_prop * q_m1;
767  q_p1 = (1 - r_prop) * q_p1;
768  /*
769  * Normalization
770  */
771  n_q_p1 = q_p1 / (q_p1 + q_m1);
772  n_q_m1 = q_m1 / (q_p1 + q_m1);
773  /*
774  * Update bit value depending on max probability
775  */
776  if (n_q_p1 > n_q_m1){
777  new_bit = - 0.5 * log((1/n_q_p1) - 1);
778  }else {
779  new_bit = 0.5 * log((1/n_q_m1) - 1);
780  }
781 
782 }
783 
784 
785 
786 void free5GRAN::phy::transport_channel::compute_H_matrix_ldpc(int Zc, int graph, int i_ls, vector<vector<int>> &matrix, int &size_i, int &size_j){
799  if (graph == 1){
800  size_i = 46;
801  size_j = 68;
802  }else {
803  size_i = 42;
804  size_j = 52;
805  }
806 
807  vector<int*> ldpc_table;
808  if (graph == 1){
810  }else {
812  }
813  for (int p = 0; p < ldpc_table.size(); p ++){
814  int index_i = ldpc_table[p][0];
815  int index_j = ldpc_table[p][1];
816  int v_ij = ldpc_table[p][i_ls + 2];
817  matrix[index_i][index_j] = v_ij;
818  }
819 }
820 
821 void free5GRAN::phy::transport_channel::ldpc_decode(double *input_bits, int N, int Zc, int graph, int K, int i_ls, int*output_sequence){
844  /*
845  * H matrix generation
846  */
847  int size_i, size_j;
848  size_i = 52;
849  size_j = 42;
850  vector<vector<int>> H(size_j, vector<int>(size_i, -1));
851  compute_H_matrix_ldpc(Zc, graph, i_ls, H, size_j, size_i);
852 
853  double ldpc_input_bits[N + 2 * Zc];
854  for (int i = 0; i < 2 * Zc; i ++){
855  ldpc_input_bits[i] = 0;
856  }
857  for (int k = 2 * Zc; k < N + 2 * Zc; k ++){
858  ldpc_input_bits[k] = input_bits[k - 2 * Zc];
859  }
860  double new_bits[N + 2 * Zc];
861  vector<vector<int>> R[N + 2 * Zc], R_tot;
862  vector<int> new_vec, new_vec_tot;
863 
864  /*
865  * Generate rows and columns matrices
866  */
867  for (int j = 0; j < size_j * Zc; j++) {
868  new_vec_tot.clear();
869  for (int i = 0; i < size_i; i++) {
870  if (H[j/Zc][i] != -1) {
871  new_vec_tot.push_back(((j % Zc + H[j/Zc][i]) % Zc) + i * Zc);
872  }
873  }
874  R_tot.push_back(new_vec_tot);
875  }
876  int index_l,inter_ind;
877  for (int i = 0; i < N + 2 * Zc; i ++) {
878  for (int j = 0; j < size_j; j++) {
879  if (H[j][i/Zc] != -1) {
880  new_vec.clear();
881  inter_ind = ((i % Zc - H[j][i/Zc]) % Zc);
882  if (inter_ind < 0){
883  inter_ind = Zc + inter_ind;
884  }
885  index_l = inter_ind + j * Zc;
886 
887  for (int p =0; p < R_tot[index_l].size(); p ++){
888  if (R_tot[index_l][p] != i){
889  new_vec.push_back(R_tot[index_l][p]);
890  }
891  }
892  R[i].push_back(new_vec);
893  }
894  }
895  }
896  int rest, final_bit[N + 2 * Zc];
897  /*
898  * Looping over iteration
899  */
900  for (int iter = 0; iter < 10; iter ++){
901  /*
902  * Decode bits
903  */
904  for (int i = 0; i < N + 2 * Zc; i ++){
905  ldpc_decode_one_bit( R[i], &ldpc_input_bits[0], i, ref(new_bits[i]));
906  }
907  for (int i = 0; i < N + 2 * Zc; i ++){
908  ldpc_input_bits[i] = new_bits[i];
909  final_bit[i] = (ldpc_input_bits[i] < 0) ? 1 : 0;
910  if (i < K){
911  output_sequence[i] = final_bit[i];
912  }
913  }
914 
915  bool validated = true;
916  for (int j = 0; j < size_j * Zc; j ++){
917  rest = 0;
918  for (int i = 0; i < R_tot[j].size(); i ++){
919  rest ^= final_bit[R_tot[j][i]];
920  }
921  if (rest == 1){
922  validated = false;
923  break;
924  }
925  }
926  if (validated){
927  BOOST_LOG_TRIVIAL(trace) << "LDPC VALIDATED";
928  break;
929  }
930 
931 
932  }
933 }
934 
935 
936 void free5GRAN::phy::transport_channel::decode_bch(int *bch_bits, bool &crc_validated, int*mib_bits, int pci) {
956  int N = pow(2,n);
957  int rate_recovered_bits[N], polar_decoded_bits[free5GRAN::SIZE_PBCH_POLAR_DECODED], remainder[free5GRAN::BCH_CRC_LENGTH + 1], bch_payload[free5GRAN::BCH_PAYLOAD_SIZE], bch_crc_recomputed[free5GRAN::BCH_CRC_LENGTH], bch_crc[free5GRAN::BCH_CRC_LENGTH], crc_masq[free5GRAN::BCH_CRC_LENGTH];
958  // Rate recover bch_bits to rate_recovered_bits
960  // Polar decode rate_recovered_bits to polar_decoded_bits
962  // Validate polar_decoded_bits CRC (compute the remainder and check that t is equal to 0)
964  crc_validated = true;
965  for (int i = 1; i < free5GRAN::BCH_CRC_LENGTH + 1; i ++){
966  if (remainder[i] ==1){
967  crc_validated = false;
968  break;
969  }
970  }
971  // Split polar_decoded_bits into bch_payload and bch_crc
972  for (int i = 0; i < free5GRAN::BCH_PAYLOAD_SIZE; i ++){
973  bch_payload[i] = polar_decoded_bits[i];
974  }
975  for (int i = 0; i < free5GRAN::BCH_CRC_LENGTH; i ++){
976  bch_crc[i] = polar_decoded_bits[free5GRAN::BCH_PAYLOAD_SIZE + i];
977  }
978  // Re-compute the bch_payload CRC
979  free5GRAN::phy::transport_channel::compute_crc(bch_payload, free5GRAN::G_CRC_24_C, bch_crc_recomputed, 32, 25);
980 
981  // XOR recomputed CRC with received CRC to determine CRC masq
982  for (int i = 0; i < free5GRAN::BCH_CRC_LENGTH; i ++){
983  crc_masq[i] = bch_crc[i] ^ bch_crc_recomputed[i];
984  }
985 
986  /*
987  * PBCH payload recovering (TS38.212 7.1.1)
988  */
990  int A_bar = free5GRAN::BCH_PAYLOAD_SIZE - 8;
991  int M = A - 3;
992  int s_sequence[A], bch_descrambled[free5GRAN::BCH_PAYLOAD_SIZE];
993  int sfn_bits[4][2] = {
994  {0,0},
995  {0,1},
996  {1,0},
997  {1,1}
998  };
999  // Find the correct value of v
1000  for (int v = 0 ; v < 4; v ++){
1001  // Generate de-scrambling sequence
1002  int c_seq[free5GRAN::BCH_PAYLOAD_SIZE + v * M];
1003  free5GRAN::utils::sequence_generator::generate_c_sequence(pci, free5GRAN::BCH_PAYLOAD_SIZE + v * M, c_seq,0);
1004  int j = 0;
1005  // Generate s sequence
1006  for (int i = 0; i < A; i ++){
1007  if ( i == 0 || i == 6 || i == 24){
1008  s_sequence[i] = 0;
1009  }else {
1010  s_sequence[i] = c_seq[j + v * M];
1011  j ++;
1012  }
1013  }
1014  // De-scramble bch_payload to bch_descrambled
1015  free5GRAN::utils::common_utils::scramble(bch_payload, s_sequence, bch_descrambled, free5GRAN::BCH_PAYLOAD_SIZE, 0);
1016 
1017  // BCH payload de-interleaving
1018  int j_sfn = 0;
1019  int j_hrf = 10;
1020  int j_ssb = 11;
1021  int j_other = 14;
1022  for (int i = 0; i < 32; i ++){
1023  if (i == 24 || i == 25 || i == 26 || i ==27|| i==1||i==2||i==3||i==4||i==5||i==6){
1024  mib_bits[i] = bch_descrambled[free5GRAN::PBCH_PAYLOAD_INTERLEAVER[j_sfn]];
1025  j_sfn ++;
1026  }else if (i == 28){
1027  mib_bits[i] = bch_descrambled[free5GRAN::PBCH_PAYLOAD_INTERLEAVER[j_hrf]];
1028  }else if ( i >= A_bar + 5 && i <= A_bar + 7){
1029  mib_bits[i] = bch_descrambled[free5GRAN::PBCH_PAYLOAD_INTERLEAVER[j_ssb]];
1030  j_ssb ++;
1031  }else {
1032  mib_bits[i] = bch_descrambled[free5GRAN::PBCH_PAYLOAD_INTERLEAVER[j_other]];
1033  j_other ++;
1034  }
1035  }
1036  // If final bits correspond to 3rd and 2nd LSB of SFN, correct v was found
1037  if (sfn_bits[v][0] == mib_bits[25] && sfn_bits[v][1] == mib_bits[26]){
1038  break;
1039  }
1040 
1041  }
1042 }
1043 
1044 void free5GRAN::phy::transport_channel::decode_dci(int *dci_bits, int E, int K, int *rnti, bool &validated, int * decoded_dci_bits) {
1065  int n = compute_N_polar_code(E,K,9);
1066  int N = pow(2,n);
1067 
1068  BOOST_LOG_TRIVIAL(trace) << "(n, N) = ("+ to_string(n)+", "+to_string(N)+")";
1069  BOOST_LOG_TRIVIAL(trace) << "E = "+to_string(E) ;
1070  BOOST_LOG_TRIVIAL(trace) << "K = "+to_string(K);
1071 
1072  int rate_recovered[N], polar_decoded[K], remainder[25], descrambled[K + 24];
1073 
1074  int A = K-24;
1075  /*
1076  * rate recovering
1077  */
1078  rate_recover(dci_bits, rate_recovered, 0, E, N, K);
1079  /*
1080  * Polar decoding
1081  */
1082  polar_decode(rate_recovered,polar_decoded,N,K,9,1,0,0, E);
1083  /*
1084  * RNTI de-masking and CRC validation
1085  */
1086  for (int i = 0; i < 24; i ++){
1087  descrambled[i] = 1;
1088  }
1089  for (int i = 0; i < K; i ++){
1090  if (i < A+8){
1091  descrambled[i + 24] = polar_decoded[i];
1092  }
1093  else {
1094  descrambled[i + 24] = (polar_decoded[i] + rnti[i - A - 8]) % 2;
1095  }
1096  }
1097  crc_validate(descrambled, free5GRAN::G_CRC_24_C, remainder, K+24, 25);
1098  validated = true;
1099  for (int i = 0; i < 25; i ++){
1100  if (remainder[i] ==1){
1101  validated = false;
1102  break;
1103  }
1104  }
1105  BOOST_LOG_TRIVIAL(trace) << "## CRC " << ((validated) ? "validated" : "not validated");
1106 
1107  for (int i = 0; i < A; i ++){
1108  decoded_dci_bits[i] = polar_decoded[i];
1109  }
1110 }
1111 
1112 vector<int> free5GRAN::phy::transport_channel::decode_dl_sch(double *dl_sch_bits, int n_re, float R, int nrb, int E, bool &validated, free5GRAN::dci_1_0_si_rnti dci_1_0_si_rnti){
1134  /*
1135  * Compute code block segmentation information
1136  */
1137  int graph, A, N, K, Zc, i_ls, L_cb, C,B,L, K_p;
1138  compute_transport_block_size(n_re, R, 2, 1, nrb, A);
1139  compute_ldpc_base_graph(A, R, graph);
1140  L = (A > 3824) ? 24 : 16;
1141  B = A + L;
1142  compute_code_block_segmentation_info_ldpc(graph, B, Zc, K, i_ls, L_cb, C, N,K_p);
1143 
1144  BOOST_LOG_TRIVIAL(trace) << "(TBS, graph) = " << A << ", " << graph;
1145  BOOST_LOG_TRIVIAL(trace) << "B = " << B;
1146  BOOST_LOG_TRIVIAL(trace) << "Zc = " << Zc;
1147  BOOST_LOG_TRIVIAL(trace) << "K = " << K;
1148  BOOST_LOG_TRIVIAL(trace) << "i_ls = " << i_ls;
1149  BOOST_LOG_TRIVIAL(trace) << "L = " << L;
1150  BOOST_LOG_TRIVIAL(trace) << "C = " << C;
1151  BOOST_LOG_TRIVIAL(trace) << "N = " << N;
1152  BOOST_LOG_TRIVIAL(trace) << "L_cb = " << L_cb;
1153  BOOST_LOG_TRIVIAL(trace) << "K_p = " << K_p;
1154  BOOST_LOG_TRIVIAL(trace) << "E = " << E;
1155 
1156  /*
1157  * Rate recovering
1158  */
1159  double *rate_recovered = new double[N];
1160  rate_recover_ldpc(dl_sch_bits, N, 1, E, dci_1_0_si_rnti.rv, 2, C, Zc, graph, K, K_p, rate_recovered);
1161 
1162  /*
1163  * LDPC decoding
1164  */
1165  int ldpc_decoded[K];
1166  auto start = chrono::steady_clock::now();
1167  ldpc_decode(rate_recovered, N, Zc, graph, K, i_ls, ldpc_decoded);
1168  auto end = chrono::steady_clock::now();
1169  auto diff = end - start;
1170  BOOST_LOG_TRIVIAL(trace) << "## LDPC execution time " << chrono::duration <double, milli> (diff).count() << "ms";
1171 
1172  int desegmented[B];
1173  for (int i = 0; i < B; i ++){
1174  desegmented[i] = ldpc_decoded[i];
1175  }
1176 
1177  /*
1178  * CRC validation
1179  */
1180  int remainder[L];
1181  if (L == 24){
1182  crc_validate(desegmented, free5GRAN::G_CRC_24_C, remainder, B, L+1);
1183  }else {
1184  crc_validate(desegmented, free5GRAN::G_CRC_16, remainder, B, L+1);
1185  }
1186 
1187  validated = true;
1188  for (int i = 0; i < L+1; i ++){
1189  if (remainder[i] ==1){
1190  validated = false;
1191  break;
1192  }
1193  }
1194  vector<int> output_bits(A);
1195 
1196  for (int i = 0; i < A; i ++){
1197  output_bits[i] = desegmented[i];
1198  }
1199 
1200  BOOST_LOG_TRIVIAL(trace) << "## CRC " << ((validated) ? "validated" : "not validated");
1201 
1202  return output_bits;
1203 }
void compute_H_matrix_ldpc(int Zc, int graph, int i_ls, vector< vector< int >> &matrix, int &size_i, int &size_j)
void scramble(int *input_bits, int *c_seq, int *output_bits, int length, int offset)
int compute_N_polar_code(int E, int K, int nmax)
int TS_38_212_TABLE_5_3_2_1[8][8]
int SIZE_PBCH_POLAR_DECODED
void compute_circular_permutation_matrix(int size, int offset, int **matrix)
int PBCH_PAYLOAD_INTERLEAVER[32]
int G8_INV[256][256]
int POLAR_SEQUENCE_QNMAX_AND_RELIABILITY[1024]
void ldpc_decode(double *input_bits, int N, int Zc, int graph, int K, int i_ls, int *output_sequence)
int SUB_BLOCK_INTERLEAVER_PATTERN[32]
int G10_INV[1024][1024]
int G7_INV[128][128]
void compute_ldpc_base_graph(int A, float R, int &graph)
int SIZE_SSB_PBCH_SYMBOLS
int G_CRC_16[27]
void compute_code_block_segmentation_info_ldpc(int graph, int B, int &Zc, int &K, int &i_ls, int &L, int &C, int &N, int &K_p)
vector< int > decode_dl_sch(double *dl_sch_bits, int n_re, float R, int nrb, int E, bool &validated, free5GRAN::dci_1_0_si_rnti dci_1_0_si_rnti)
int G9_INV[512][512]
void rate_recover(int *input_bits, int *output_bits, int i_bil, int E, int N, int K)
std::vector< int * > TS_38_212_TABLE_5_3_2_2
void polar_decode(int *input_bits, int *output_bits, int N, int K, int nmax, int i_il, int n_pc, int n_wm_pc, int E)
int TS_38_214_TABLE_5_1_3_2_1[93]
void crc_validate(int *input_bits, int *crc_polynom, int *remainder, int length_input, int length_crc)
void compute_transport_block_size(int n_re, float R, int mod_order, int num_layers, int nrb, int &tbs)
void decode_dci(int *dci_bits, int E, int K, int *rnti, bool &validated, int *decoded_dci_bits)
int INTERLEAVING_PATTERN[164]
int G5_INV[32][32]
void compute_Zc_dl_sch(int kb, float k_p, int &Zc, int &i_ls)
void ldpc_decode_one_bit(vector< vector< int >> R, double *soft_bits, int i, double &new_bit)
void compute_crc(int *input_bits, int *crc_polynom, int *remainder, int length_input, int length_crc)
void decode_bch(int *bch_bits, bool &crc_validated, int *mib_bits, int pci)
void rate_recover_ldpc(int *input_bits, int N, int i_lbrm, int E, int id_rv, int mod_order, int C, int Zc, int graph, int K, int K_p, int *output_sequence)
void generate_c_sequence(long c_init, int length, int *output_sequence, int demod_type)
int G6_INV[64][64]
std::vector< int * > TS_38_212_TABLE_5_3_2_3
int G_CRC_24_C[25]