Agora  1.2.0
Agora project
utils_ldpc.h
Go to the documentation of this file.
1 #ifndef UTILS_LDPC_H_
2 #define UTILS_LDPC_H_
3 
4 #include <cstdlib> /* for std::aligned_alloc */
5 
6 #include "encoder.h"
7 #include "iobuffer.h"
8 #include "phy_ldpc_encoder_5gnr.h"
9 #include "symbols.h"
10 #include "utils.h"
11 
12 // Since the LDPC helper function input parameter undergoes 32byte read/write it
13 // is necessary to pad the input buffers 32 bytes max (ie 32 will work for all
14 // configurations)
15 
16 LDPC_ADAPTER_P LdpcSelectAdapterFunc(uint16_t zcSize, uint8_t num_ways);
17 
18 template <typename T>
19 T* AlignedMalloc(const int size, const unsigned alignment) {
20 #ifdef _BBLIB_DPDK_
21  return reinterpret_cast<T*>(rte_malloc(NULL, sizeof(T) * size, alignment));
22 #else
23 #ifndef _WIN64
24  return reinterpret_cast<T*>(std::aligned_alloc(alignment, sizeof(T) * size));
25 #else
26  return reinterpret_cast<T*>(_aligned_malloc(sizeof(T) * size, alignment));
27 #endif
28 #endif
29 }
30 
31 #ifndef __has_builtin
32 #define __has_builtin(x) 0
33 #endif
34 
35 static inline uint8_t Bitreverse8(uint8_t x) {
36 #if __has_builtin(__builtin_bireverse8)
37  return (__builtin_bitreverse8(x));
38 #else
39  x = (x << 4) | (x >> 4);
40  x = ((x & 0x33) << 2) | ((x >> 2) & 0x33);
41  x = ((x & 0x55) << 1) | ((x >> 1) & 0x55);
42  return (x);
43 #endif
44 }
45 
60 static inline void AdaptBitsForMod(const uint8_t* bit_seq_in,
61  uint8_t* bytes_out, size_t len,
62  size_t mod_type) {
63  uint16_t bits = 0; // Bits collected from the input
64  size_t bits_avail = 0; // Number of valid bits filled into [bits]
65  for (size_t i = 0; i < len; i++) {
66  bits |= static_cast<uint32_t>(Bitreverse8(bit_seq_in[i]))
67  << (8 - bits_avail);
68  bits_avail += 8;
69  while (bits_avail >= mod_type) {
70  *bytes_out++ = bits >> (16 - mod_type);
71  bits <<= mod_type;
72  bits_avail -= mod_type;
73  }
74  }
75 
76  if (bits_avail > 0) {
77  *bytes_out++ = bits >> (16 - mod_type);
78  }
79 }
80 
81 /*
82  * Copy packed, bit-reversed 8-bit fields stored in
83  * vec_in[0..len-1] into unpacked m-bit vec_out (m == mod_type).
84  * Storage at vec_out must be at least (m*len+7)/8 bytes.
85  */
86 static inline void AdaptBitsFromMod(const uint8_t* vec_in, uint8_t* vec_out,
87  int len, int mod_type) {
88  int bits_avail = 0;
89  uint16_t bits = 0;
90  for (int i = 0; i < len; i++) {
91  bits |= (Bitreverse8(vec_in[i]) >> (8 - mod_type)) << bits_avail;
92  bits_avail += mod_type;
93  while (bits_avail >= 8) {
94  *vec_out++ = bits & 0xff;
95  bits >>= 8;
96  bits_avail -= 8;
97  }
98  }
99 }
100 
101 static inline uint8_t SelectBaseMatrixEntry(uint16_t Zc) {
102  uint8_t i_ls;
103  if ((Zc % 15) == 0) {
104  i_ls = 7;
105  } else if ((Zc % 13) == 0) {
106  i_ls = 6;
107  } else if ((Zc % 11) == 0) {
108  i_ls = 5;
109  } else if ((Zc % 9) == 0) {
110  i_ls = 4;
111  } else if ((Zc % 7) == 0) {
112  i_ls = 3;
113  } else if ((Zc % 5) == 0) {
114  i_ls = 2;
115  } else if ((Zc % 3) == 0) {
116  i_ls = 1;
117  } else {
118  i_ls = 0;
119  }
120  return i_ls;
121 }
122 
123 // Return the number of bytes needed to store n_bits bits
124 static inline size_t BitsToBytes(size_t n_bits) { return (n_bits + 7) / 8; }
125 
126 // Return the number of non-expanded base graph columns used for information
127 // bits for this base graph
128 static inline size_t LdpcNumInputCols(size_t base_graph) {
129  return (base_graph == 1 ? BG1_COL_INF_NUM : BG2_COL_INF_NUM);
130 }
131 
132 // Return the maximum number of rows in this non-expanded base graph
133 static inline size_t LdpcMaxNumRows(size_t base_graph) {
134  return (base_graph == 1 ? BG1_ROW_TOTAL : BG2_ROW_TOTAL);
135 }
136 
137 // Return the number of input information bits per codeword with this base
138 // graph and expansion factor
139 static inline size_t LdpcNumInputBits(size_t base_graph, size_t zc) {
140  return zc * LdpcNumInputCols(base_graph);
141 }
142 
143 // Return the number of parity bits per codeword with this base graph and
144 // expansion factor
145 static inline size_t LdpcMaxNumParityBits(size_t base_graph, size_t zc) {
146  return zc * LdpcMaxNumRows(base_graph);
147 }
148 
149 // Return the maximum number of total bits per code block with this base graph
150 // and expansion factor
151 static inline size_t LdpcMaxNumEncodedBits(size_t base_graph, size_t zc) {
152  static size_t num_punctured_cols = 2;
153  return zc * (base_graph == 1 ? (BG1_COL_TOTAL - num_punctured_cols)
154  : (BG2_COL_TOTAL - num_punctured_cols));
155 }
156 
157 // Return the number of total bits per codeword (i.e., including both input
158 // bits and parity bits) with this base graph and expansion factor
159 static inline size_t LdpcNumEncodedBits(size_t base_graph, size_t zc,
160  size_t nRows) {
161  static size_t num_punctured_cols = 2;
162  return zc * (LdpcNumInputCols(base_graph) + nRows - num_punctured_cols);
163 }
164 
165 // Return the number of bytes required in the input buffer used for LDPC
166 // encoding
167 static inline size_t LdpcEncodingInputBufSize(size_t base_graph, size_t zc) {
168  // We add kMaxProcBytes as padding for the encoder's scatter function
169  return BitsToBytes(LdpcNumInputBits(base_graph, zc)) + kMaxProcBytes;
170 }
171 
172 // Return the number of bytes required in the parity buffer used for LDPC
173 // encoding
174 static inline size_t LdpcEncodingParityBufSize(size_t base_graph, size_t zc) {
175  // We add kMaxProcBytes as padding for the encoder's gather function
176  return BitsToBytes(LdpcMaxNumParityBits(base_graph, zc)) + kMaxProcBytes;
177 }
178 
179 // Return the number of bytes required in the output encoded codeword buffer
180 // used for LDPC encoding
181 static inline size_t LdpcEncodingEncodedBufSize(size_t base_graph, size_t zc) {
182  // We add kMaxProcBytes as padding for the encoder's gather function
183  return BitsToBytes(LdpcMaxNumEncodedBits(base_graph, zc)) + kMaxProcBytes;
184 }
185 
186 // Return the minimum LDPC expansion factor supported
187 static inline size_t LdpcGetMinZc() { return kUseAVX2Encoder ? 2 : 6; }
188 
189 // Return the maximum LDPC expansion factor supported
190 static inline size_t LdpcGetMaxZc() {
192 }
193 
194 // Generate the codeword output and parity buffer for this input buffer
195 static inline void LdpcEncodeHelper(size_t base_graph, size_t zc, size_t nRows,
196  int8_t* encoded_buffer,
197  int8_t* parity_buffer,
198  const int8_t* input_buffer) {
199  const size_t num_input_bits = LdpcNumInputBits(base_graph, zc);
200  const size_t num_parity_bits = nRows * zc;
201 
202  bblib_ldpc_encoder_5gnr_request req;
203  bblib_ldpc_encoder_5gnr_response resp;
204  req.baseGraph = base_graph;
205  req.nRows = kUseAVX2Encoder ? LdpcMaxNumRows(base_graph) : nRows;
206  req.Zc = zc;
207  req.nRows = nRows;
208  req.numberCodeblocks = 1;
209  req.input[0] = const_cast<int8_t*>(input_buffer);
210  resp.output[0] = parity_buffer;
211 
213  : bblib_ldpc_encoder_5gnr(&req, &resp);
214 
215  // Copy punctured input bits from the encoding request, and parity bits from
216  // the encoding response into encoded_buffer
217  static size_t k_num_punctured_cols = 2;
218  if (zc % 4 == 0) {
219  // In this case, the start and end of punctured input bits is
220  // byte-aligned, so we can std::memcpy
221  const size_t num_punctured_bytes = BitsToBytes(zc * k_num_punctured_cols);
222  const size_t num_input_bytes_to_copy =
223  BitsToBytes(num_input_bits) - num_punctured_bytes;
224 
225  std::memcpy(encoded_buffer, input_buffer + num_punctured_bytes,
226  num_input_bytes_to_copy);
227  std::memcpy(encoded_buffer + num_input_bytes_to_copy, parity_buffer,
228  BitsToBytes(num_parity_bits));
229  } else {
230  // Otherwise, we need to std::memcpy from/to byte-unaligned locations. A
231  // simple but perhaps inefficient way to do this is to use the encoder's
232  // internal scatter/gather functions. We don't have access to these
233  // functions for FlexRAN's internal AVX-512 encoder.
234  if (zc >= avx2enc::kProcBytes * 8) {
235  std::fprintf(stderr,
236  "Zc values >= %zu that are not multiples of four are not "
237  "supported yet.\n",
238  zc);
239  throw std::runtime_error(
240  "Zc values >= values that are not multiples of four");
241  }
242 
244  int8_t internal_buffer0[BG1_COL_INF_NUM * avx2enc::kProcBytes] = {0};
246  int8_t internal_buffer1[BG1_ROW_TOTAL * avx2enc::kProcBytes] = {0};
248  int8_t internal_buffer2[BG1_COL_TOTAL * avx2enc::kProcBytes] = {0};
249 
250  auto adapter_func = avx2enc::LdpcSelectAdapterFunc(zc);
251 
252  // Scatter input and parity into zc-bit chunks
253  adapter_func((int8_t*)input_buffer, internal_buffer0, zc, num_input_bits,
254  1);
255  adapter_func(parity_buffer, internal_buffer1, zc, num_parity_bits, 1);
256 
257  // Concactenate the chunks for input and parity
258  std::memcpy(internal_buffer2,
259  internal_buffer0 + k_num_punctured_cols * avx2enc::kProcBytes,
260  (LdpcNumInputCols(base_graph) - k_num_punctured_cols) *
262  std::memcpy(internal_buffer2 +
263  (LdpcNumInputCols(base_graph) - k_num_punctured_cols) *
265  internal_buffer1,
266  LdpcMaxNumRows(base_graph) * avx2enc::kProcBytes);
267 
268  // Gather the concatenated chunks to create the encoded buffer
269  adapter_func(encoded_buffer, internal_buffer2, zc,
270  LdpcNumEncodedBits(base_graph, zc, nRows), 0);
271  }
272 }
273 
274 #endif // UTILS_LDPC_H_
__attribute__
class RadioSocket __attribute__
encoder.h
Definitions for Agora's AVX2-based LDPC encoder.
LdpcEncodingInputBufSize
static size_t LdpcEncodingInputBufSize(size_t base_graph, size_t zc)
Definition: utils_ldpc.h:167
avx2enc::LdpcSelectAdapterFunc
LDPC_ADAPTER_P LdpcSelectAdapterFunc(uint16_t zc_size)
Definition: iobuffer.cc:228
iobuffer.h
Declaration for for the avx2enc iobuffer functions.
AdaptBitsFromMod
static void AdaptBitsFromMod(const uint8_t *vec_in, uint8_t *vec_out, int len, int mod_type)
Definition: utils_ldpc.h:86
size
end IFFT Reshape the symbol vector into two different spatial streams size
Definition: generate_data.m:73
kMaxProcBytes
static constexpr size_t kMaxProcBytes
Definition: encoder.h:30
LdpcEncodeHelper
static void LdpcEncodeHelper(size_t base_graph, size_t zc, size_t nRows, int8_t *encoded_buffer, int8_t *parity_buffer, const int8_t *input_buffer)
Definition: utils_ldpc.h:195
LdpcNumEncodedBits
static size_t LdpcNumEncodedBits(size_t base_graph, size_t zc, size_t nRows)
Definition: utils_ldpc.h:159
BG1_COL_TOTAL
#define BG1_COL_TOTAL
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:90
BG1_COL_INF_NUM
#define BG1_COL_INF_NUM
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:92
BitsToBytes
static size_t BitsToBytes(size_t n_bits)
Definition: utils_ldpc.h:124
BG2_COL_INF_NUM
#define BG2_COL_INF_NUM
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:97
LDPC_ADAPTER_P
void(*)(int8_t **, int8_t *, uint16_t, uint32_t, int8_t) LDPC_ADAPTER_P
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:83
x
x
Definition: simulate_performance.m:69
LdpcEncodingEncodedBufSize
static size_t LdpcEncodingEncodedBufSize(size_t base_graph, size_t zc)
Definition: utils_ldpc.h:181
avx2enc::kProcBytes
static constexpr size_t kProcBytes
Definition: encoder.h:22
LdpcNumInputCols
static size_t LdpcNumInputCols(size_t base_graph)
Definition: utils_ldpc.h:128
LdpcMaxNumEncodedBits
static size_t LdpcMaxNumEncodedBits(size_t base_graph, size_t zc)
Definition: utils_ldpc.h:151
AlignedMalloc
T * AlignedMalloc(const int size, const unsigned alignment)
Definition: utils_ldpc.h:19
T
T
Definition: simulate_performance.m:4
ZC_MAX
#define ZC_MAX
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:88
avx2enc::BblibLdpcEncoder5gnr
int32_t BblibLdpcEncoder5gnr(struct bblib_ldpc_encoder_5gnr_request *request, struct bblib_ldpc_encoder_5gnr_response *response)
Definition: encoder.cc:239
LdpcMaxNumRows
static size_t LdpcMaxNumRows(size_t base_graph)
Definition: utils_ldpc.h:133
LdpcSelectAdapterFunc
LDPC_ADAPTER_P LdpcSelectAdapterFunc(uint16_t zcSize, uint8_t num_ways)
LdpcGetMinZc
static size_t LdpcGetMinZc()
Definition: utils_ldpc.h:187
len
uint16_t len
Definition: eth_common.h:62
i
for i
Definition: generate_data.m:107
SelectBaseMatrixEntry
static uint8_t SelectBaseMatrixEntry(uint16_t Zc)
Definition: utils_ldpc.h:101
BG2_ROW_TOTAL
#define BG2_ROW_TOTAL
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:96
LdpcMaxNumParityBits
static size_t LdpcMaxNumParityBits(size_t base_graph, size_t zc)
Definition: utils_ldpc.h:145
fmt::v8::fprintf
auto fprintf(std::FILE *f, const S &fmt, const T &... args) -> int
Definition: printf.h:607
kUseAVX2Encoder
static constexpr bool kUseAVX2Encoder
Definition: symbols.h:350
avx2enc::kZcMax
static constexpr size_t kZcMax
Definition: encoder.h:20
BG1_ROW_TOTAL
#define BG1_ROW_TOTAL
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:91
BG2_COL_TOTAL
#define BG2_COL_TOTAL
Definition: gcc_phy_ldpc_encoder_5gnr_internal.h:95
symbols.h
LdpcGetMaxZc
static size_t LdpcGetMaxZc()
Definition: utils_ldpc.h:190
Bitreverse8
static uint8_t Bitreverse8(uint8_t x)
Definition: utils_ldpc.h:35
LdpcNumInputBits
static size_t LdpcNumInputBits(size_t base_graph, size_t zc)
Definition: utils_ldpc.h:139
utils.h
Utility functions for file and text processing.
LdpcEncodingParityBufSize
static size_t LdpcEncodingParityBufSize(size_t base_graph, size_t zc)
Definition: utils_ldpc.h:174
AdaptBitsForMod
static void AdaptBitsForMod(const uint8_t *bit_seq_in, uint8_t *bytes_out, size_t len, size_t mod_type)
Fill-in the bytes of bytes_out with mod_type bits per byte, taken from the bit sequence bit_seq_in.
Definition: utils_ldpc.h:60