1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
3 */
4
5 #include <stdio.h>
6 #include <inttypes.h>
7 #include <math.h>
8
9 #include <rte_eal.h>
10 #include <rte_common.h>
11 #include <rte_dev.h>
12 #include <rte_launch.h>
13 #include <rte_bbdev.h>
14 #include <rte_cycles.h>
15 #include <rte_lcore.h>
16 #include <rte_malloc.h>
17 #include <rte_random.h>
18 #include <rte_hexdump.h>
19 #include <rte_interrupts.h>
20
21 #include "main.h"
22 #include "test_bbdev_vector.h"
23
24 #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
25
26 #define MAX_QUEUES RTE_MAX_LCORE
27 #define TEST_REPETITIONS 100
28 #define WAIT_OFFLOAD_US 1000
29
30 #ifdef RTE_BASEBAND_FPGA_LTE_FEC
31 #include <fpga_lte_fec.h>
32 #define FPGA_LTE_PF_DRIVER_NAME ("intel_fpga_lte_fec_pf")
33 #define FPGA_LTE_VF_DRIVER_NAME ("intel_fpga_lte_fec_vf")
34 #define VF_UL_4G_QUEUE_VALUE 4
35 #define VF_DL_4G_QUEUE_VALUE 4
36 #define UL_4G_BANDWIDTH 3
37 #define DL_4G_BANDWIDTH 3
38 #define UL_4G_LOAD_BALANCE 128
39 #define DL_4G_LOAD_BALANCE 128
40 #define FLR_4G_TIMEOUT 610
41 #endif
42
43 #ifdef RTE_BASEBAND_FPGA_5GNR_FEC
44 #include <rte_pmd_fpga_5gnr_fec.h>
45 #define FPGA_5GNR_PF_DRIVER_NAME ("intel_fpga_5gnr_fec_pf")
46 #define FPGA_5GNR_VF_DRIVER_NAME ("intel_fpga_5gnr_fec_vf")
47 #define VF_UL_5G_QUEUE_VALUE 4
48 #define VF_DL_5G_QUEUE_VALUE 4
49 #define UL_5G_BANDWIDTH 3
50 #define DL_5G_BANDWIDTH 3
51 #define UL_5G_LOAD_BALANCE 128
52 #define DL_5G_LOAD_BALANCE 128
53 #define FLR_5G_TIMEOUT 610
54 #endif
55
56 #ifdef RTE_BASEBAND_ACC100
57 #include <rte_acc100_cfg.h>
58 #define ACC100PF_DRIVER_NAME ("intel_acc100_pf")
59 #define ACC100VF_DRIVER_NAME ("intel_acc100_vf")
60 #define ACC100_QMGR_NUM_AQS 16
61 #define ACC100_QMGR_NUM_QGS 2
62 #define ACC100_QMGR_AQ_DEPTH 5
63 #define ACC100_QMGR_INVALID_IDX -1
64 #define ACC100_QMGR_RR 1
65 #define ACC100_QOS_GBR 0
66 #endif
67
68 #define OPS_CACHE_SIZE 256U
69 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
70
71 #define SYNC_WAIT 0
72 #define SYNC_START 1
73 #define INVALID_OPAQUE -1
74
75 #define INVALID_QUEUE_ID -1
76 /* Increment for next code block in external HARQ memory */
77 #define HARQ_INCR 32768
78 /* Headroom for filler LLRs insertion in HARQ buffer */
79 #define FILLER_HEADROOM 1024
80 /* Constants from K0 computation from 3GPP 38.212 Table 5.4.2.1-2 */
81 #define N_ZC_1 66 /* N = 66 Zc for BG 1 */
82 #define N_ZC_2 50 /* N = 50 Zc for BG 2 */
83 #define K0_1_1 17 /* K0 fraction numerator for rv 1 and BG 1 */
84 #define K0_1_2 13 /* K0 fraction numerator for rv 1 and BG 2 */
85 #define K0_2_1 33 /* K0 fraction numerator for rv 2 and BG 1 */
86 #define K0_2_2 25 /* K0 fraction numerator for rv 2 and BG 2 */
87 #define K0_3_1 56 /* K0 fraction numerator for rv 3 and BG 1 */
88 #define K0_3_2 43 /* K0 fraction numerator for rv 3 and BG 2 */
89
90 static struct test_bbdev_vector test_vector;
91
92 /* Switch between PMD and Interrupt for throughput TC */
93 static bool intr_enabled;
94
95 /* LLR arithmetic representation for numerical conversion */
96 static int ldpc_llr_decimals;
97 static int ldpc_llr_size;
98 /* Keep track of the LDPC decoder device capability flag */
99 static uint32_t ldpc_cap_flags;
100
101 /* Represents tested active devices */
102 static struct active_device {
103 const char *driver_name;
104 uint8_t dev_id;
105 uint16_t supported_ops;
106 uint16_t queue_ids[MAX_QUEUES];
107 uint16_t nb_queues;
108 struct rte_mempool *ops_mempool;
109 struct rte_mempool *in_mbuf_pool;
110 struct rte_mempool *hard_out_mbuf_pool;
111 struct rte_mempool *soft_out_mbuf_pool;
112 struct rte_mempool *harq_in_mbuf_pool;
113 struct rte_mempool *harq_out_mbuf_pool;
114 } active_devs[RTE_BBDEV_MAX_DEVS];
115
116 static uint8_t nb_active_devs;
117
118 /* Data buffers used by BBDEV ops */
119 struct test_buffers {
120 struct rte_bbdev_op_data *inputs;
121 struct rte_bbdev_op_data *hard_outputs;
122 struct rte_bbdev_op_data *soft_outputs;
123 struct rte_bbdev_op_data *harq_inputs;
124 struct rte_bbdev_op_data *harq_outputs;
125 };
126
127 /* Operation parameters specific for given test case */
128 struct test_op_params {
129 struct rte_mempool *mp;
130 struct rte_bbdev_dec_op *ref_dec_op;
131 struct rte_bbdev_enc_op *ref_enc_op;
132 uint16_t burst_sz;
133 uint16_t num_to_process;
134 uint16_t num_lcores;
135 int vector_mask;
136 rte_atomic16_t sync;
137 struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
138 };
139
140 /* Contains per lcore params */
141 struct thread_params {
142 uint8_t dev_id;
143 uint16_t queue_id;
144 uint32_t lcore_id;
145 uint64_t start_time;
146 double ops_per_sec;
147 double mbps;
148 uint8_t iter_count;
149 double iter_average;
150 double bler;
151 rte_atomic16_t nb_dequeued;
152 rte_atomic16_t processing_status;
153 rte_atomic16_t burst_sz;
154 struct test_op_params *op_params;
155 struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
156 struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
157 };
158
159 #ifdef RTE_BBDEV_OFFLOAD_COST
160 /* Stores time statistics */
161 struct test_time_stats {
162 /* Stores software enqueue total working time */
163 uint64_t enq_sw_total_time;
164 /* Stores minimum value of software enqueue working time */
165 uint64_t enq_sw_min_time;
166 /* Stores maximum value of software enqueue working time */
167 uint64_t enq_sw_max_time;
168 /* Stores turbo enqueue total working time */
169 uint64_t enq_acc_total_time;
170 /* Stores minimum value of accelerator enqueue working time */
171 uint64_t enq_acc_min_time;
172 /* Stores maximum value of accelerator enqueue working time */
173 uint64_t enq_acc_max_time;
174 /* Stores dequeue total working time */
175 uint64_t deq_total_time;
176 /* Stores minimum value of dequeue working time */
177 uint64_t deq_min_time;
178 /* Stores maximum value of dequeue working time */
179 uint64_t deq_max_time;
180 };
181 #endif
182
183 typedef int (test_case_function)(struct active_device *ad,
184 struct test_op_params *op_params);
185
186 static inline void
mbuf_reset(struct rte_mbuf * m)187 mbuf_reset(struct rte_mbuf *m)
188 {
189 m->pkt_len = 0;
190
191 do {
192 m->data_len = 0;
193 m = m->next;
194 } while (m != NULL);
195 }
196
197 /* Read flag value 0/1 from bitmap */
198 static inline bool
check_bit(uint32_t bitmap,uint32_t bitmask)199 check_bit(uint32_t bitmap, uint32_t bitmask)
200 {
201 return bitmap & bitmask;
202 }
203
204 static inline void
set_avail_op(struct active_device * ad,enum rte_bbdev_op_type op_type)205 set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
206 {
207 ad->supported_ops |= (1 << op_type);
208 }
209
210 static inline bool
is_avail_op(struct active_device * ad,enum rte_bbdev_op_type op_type)211 is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
212 {
213 return ad->supported_ops & (1 << op_type);
214 }
215
216 static inline bool
flags_match(uint32_t flags_req,uint32_t flags_present)217 flags_match(uint32_t flags_req, uint32_t flags_present)
218 {
219 return (flags_req & flags_present) == flags_req;
220 }
221
222 static void
clear_soft_out_cap(uint32_t * op_flags)223 clear_soft_out_cap(uint32_t *op_flags)
224 {
225 *op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
226 *op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
227 *op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
228 }
229
230 static int
check_dev_cap(const struct rte_bbdev_info * dev_info)231 check_dev_cap(const struct rte_bbdev_info *dev_info)
232 {
233 unsigned int i;
234 unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs,
235 nb_harq_inputs, nb_harq_outputs;
236 const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
237
238 nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
239 nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
240 nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
241 nb_harq_inputs = test_vector.entries[DATA_HARQ_INPUT].nb_segments;
242 nb_harq_outputs = test_vector.entries[DATA_HARQ_OUTPUT].nb_segments;
243
244 for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
245 if (op_cap->type != test_vector.op_type)
246 continue;
247
248 if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
249 const struct rte_bbdev_op_cap_turbo_dec *cap =
250 &op_cap->cap.turbo_dec;
251 /* Ignore lack of soft output capability, just skip
252 * checking if soft output is valid.
253 */
254 if ((test_vector.turbo_dec.op_flags &
255 RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
256 !(cap->capability_flags &
257 RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
258 printf(
259 "INFO: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
260 dev_info->dev_name);
261 clear_soft_out_cap(
262 &test_vector.turbo_dec.op_flags);
263 }
264
265 if (!flags_match(test_vector.turbo_dec.op_flags,
266 cap->capability_flags))
267 return TEST_FAILED;
268 if (nb_inputs > cap->num_buffers_src) {
269 printf("Too many inputs defined: %u, max: %u\n",
270 nb_inputs, cap->num_buffers_src);
271 return TEST_FAILED;
272 }
273 if (nb_soft_outputs > cap->num_buffers_soft_out &&
274 (test_vector.turbo_dec.op_flags &
275 RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
276 printf(
277 "Too many soft outputs defined: %u, max: %u\n",
278 nb_soft_outputs,
279 cap->num_buffers_soft_out);
280 return TEST_FAILED;
281 }
282 if (nb_hard_outputs > cap->num_buffers_hard_out) {
283 printf(
284 "Too many hard outputs defined: %u, max: %u\n",
285 nb_hard_outputs,
286 cap->num_buffers_hard_out);
287 return TEST_FAILED;
288 }
289 if (intr_enabled && !(cap->capability_flags &
290 RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
291 printf(
292 "Dequeue interrupts are not supported!\n");
293 return TEST_FAILED;
294 }
295
296 return TEST_SUCCESS;
297 } else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
298 const struct rte_bbdev_op_cap_turbo_enc *cap =
299 &op_cap->cap.turbo_enc;
300
301 if (!flags_match(test_vector.turbo_enc.op_flags,
302 cap->capability_flags))
303 return TEST_FAILED;
304 if (nb_inputs > cap->num_buffers_src) {
305 printf("Too many inputs defined: %u, max: %u\n",
306 nb_inputs, cap->num_buffers_src);
307 return TEST_FAILED;
308 }
309 if (nb_hard_outputs > cap->num_buffers_dst) {
310 printf(
311 "Too many hard outputs defined: %u, max: %u\n",
312 nb_hard_outputs, cap->num_buffers_dst);
313 return TEST_FAILED;
314 }
315 if (intr_enabled && !(cap->capability_flags &
316 RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
317 printf(
318 "Dequeue interrupts are not supported!\n");
319 return TEST_FAILED;
320 }
321
322 return TEST_SUCCESS;
323 } else if (op_cap->type == RTE_BBDEV_OP_LDPC_ENC) {
324 const struct rte_bbdev_op_cap_ldpc_enc *cap =
325 &op_cap->cap.ldpc_enc;
326
327 if (!flags_match(test_vector.ldpc_enc.op_flags,
328 cap->capability_flags)){
329 printf("Flag Mismatch\n");
330 return TEST_FAILED;
331 }
332 if (nb_inputs > cap->num_buffers_src) {
333 printf("Too many inputs defined: %u, max: %u\n",
334 nb_inputs, cap->num_buffers_src);
335 return TEST_FAILED;
336 }
337 if (nb_hard_outputs > cap->num_buffers_dst) {
338 printf(
339 "Too many hard outputs defined: %u, max: %u\n",
340 nb_hard_outputs, cap->num_buffers_dst);
341 return TEST_FAILED;
342 }
343 if (intr_enabled && !(cap->capability_flags &
344 RTE_BBDEV_LDPC_ENC_INTERRUPTS)) {
345 printf(
346 "Dequeue interrupts are not supported!\n");
347 return TEST_FAILED;
348 }
349
350 return TEST_SUCCESS;
351 } else if (op_cap->type == RTE_BBDEV_OP_LDPC_DEC) {
352 const struct rte_bbdev_op_cap_ldpc_dec *cap =
353 &op_cap->cap.ldpc_dec;
354
355 if (!flags_match(test_vector.ldpc_dec.op_flags,
356 cap->capability_flags)){
357 printf("Flag Mismatch\n");
358 return TEST_FAILED;
359 }
360 if (nb_inputs > cap->num_buffers_src) {
361 printf("Too many inputs defined: %u, max: %u\n",
362 nb_inputs, cap->num_buffers_src);
363 return TEST_FAILED;
364 }
365 if (nb_hard_outputs > cap->num_buffers_hard_out) {
366 printf(
367 "Too many hard outputs defined: %u, max: %u\n",
368 nb_hard_outputs,
369 cap->num_buffers_hard_out);
370 return TEST_FAILED;
371 }
372 if (nb_harq_inputs > cap->num_buffers_hard_out) {
373 printf(
374 "Too many HARQ inputs defined: %u, max: %u\n",
375 nb_hard_outputs,
376 cap->num_buffers_hard_out);
377 return TEST_FAILED;
378 }
379 if (nb_harq_outputs > cap->num_buffers_hard_out) {
380 printf(
381 "Too many HARQ outputs defined: %u, max: %u\n",
382 nb_hard_outputs,
383 cap->num_buffers_hard_out);
384 return TEST_FAILED;
385 }
386 if (intr_enabled && !(cap->capability_flags &
387 RTE_BBDEV_LDPC_DEC_INTERRUPTS)) {
388 printf(
389 "Dequeue interrupts are not supported!\n");
390 return TEST_FAILED;
391 }
392 if (intr_enabled && (test_vector.ldpc_dec.op_flags &
393 (RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
394 RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
395 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK
396 ))) {
397 printf("Skip loop-back with interrupt\n");
398 return TEST_FAILED;
399 }
400 return TEST_SUCCESS;
401 }
402 }
403
404 if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
405 return TEST_SUCCESS; /* Special case for NULL device */
406
407 return TEST_FAILED;
408 }
409
410 /* calculates optimal mempool size not smaller than the val */
411 static unsigned int
optimal_mempool_size(unsigned int val)412 optimal_mempool_size(unsigned int val)
413 {
414 return rte_align32pow2(val + 1) - 1;
415 }
416
417 /* allocates mbuf mempool for inputs and outputs */
418 static struct rte_mempool *
create_mbuf_pool(struct op_data_entries * entries,uint8_t dev_id,int socket_id,unsigned int mbuf_pool_size,const char * op_type_str)419 create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
420 int socket_id, unsigned int mbuf_pool_size,
421 const char *op_type_str)
422 {
423 unsigned int i;
424 uint32_t max_seg_sz = 0;
425 char pool_name[RTE_MEMPOOL_NAMESIZE];
426
427 /* find max input segment size */
428 for (i = 0; i < entries->nb_segments; ++i)
429 if (entries->segments[i].length > max_seg_sz)
430 max_seg_sz = entries->segments[i].length;
431
432 snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
433 dev_id);
434 return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
435 RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM
436 + FILLER_HEADROOM,
437 (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
438 }
439
440 static int
create_mempools(struct active_device * ad,int socket_id,enum rte_bbdev_op_type org_op_type,uint16_t num_ops)441 create_mempools(struct active_device *ad, int socket_id,
442 enum rte_bbdev_op_type org_op_type, uint16_t num_ops)
443 {
444 struct rte_mempool *mp;
445 unsigned int ops_pool_size, mbuf_pool_size = 0;
446 char pool_name[RTE_MEMPOOL_NAMESIZE];
447 const char *op_type_str;
448 enum rte_bbdev_op_type op_type = org_op_type;
449
450 struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
451 struct op_data_entries *hard_out =
452 &test_vector.entries[DATA_HARD_OUTPUT];
453 struct op_data_entries *soft_out =
454 &test_vector.entries[DATA_SOFT_OUTPUT];
455 struct op_data_entries *harq_in =
456 &test_vector.entries[DATA_HARQ_INPUT];
457 struct op_data_entries *harq_out =
458 &test_vector.entries[DATA_HARQ_OUTPUT];
459
460 /* allocate ops mempool */
461 ops_pool_size = optimal_mempool_size(RTE_MAX(
462 /* Ops used plus 1 reference op */
463 RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
464 /* Minimal cache size plus 1 reference op */
465 (unsigned int)(1.5 * rte_lcore_count() *
466 OPS_CACHE_SIZE + 1)),
467 OPS_POOL_SIZE_MIN));
468
469 if (org_op_type == RTE_BBDEV_OP_NONE)
470 op_type = RTE_BBDEV_OP_TURBO_ENC;
471
472 op_type_str = rte_bbdev_op_type_str(op_type);
473 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
474
475 snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
476 ad->dev_id);
477 mp = rte_bbdev_op_pool_create(pool_name, op_type,
478 ops_pool_size, OPS_CACHE_SIZE, socket_id);
479 TEST_ASSERT_NOT_NULL(mp,
480 "ERROR Failed to create %u items ops pool for dev %u on socket %u.",
481 ops_pool_size,
482 ad->dev_id,
483 socket_id);
484 ad->ops_mempool = mp;
485
486 /* Do not create inputs and outputs mbufs for BaseBand Null Device */
487 if (org_op_type == RTE_BBDEV_OP_NONE)
488 return TEST_SUCCESS;
489
490 /* Inputs */
491 if (in->nb_segments > 0) {
492 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
493 in->nb_segments);
494 mp = create_mbuf_pool(in, ad->dev_id, socket_id,
495 mbuf_pool_size, "in");
496 TEST_ASSERT_NOT_NULL(mp,
497 "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
498 mbuf_pool_size,
499 ad->dev_id,
500 socket_id);
501 ad->in_mbuf_pool = mp;
502 }
503
504 /* Hard outputs */
505 if (hard_out->nb_segments > 0) {
506 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
507 hard_out->nb_segments);
508 mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id,
509 mbuf_pool_size,
510 "hard_out");
511 TEST_ASSERT_NOT_NULL(mp,
512 "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
513 mbuf_pool_size,
514 ad->dev_id,
515 socket_id);
516 ad->hard_out_mbuf_pool = mp;
517 }
518
519 /* Soft outputs */
520 if (soft_out->nb_segments > 0) {
521 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
522 soft_out->nb_segments);
523 mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id,
524 mbuf_pool_size,
525 "soft_out");
526 TEST_ASSERT_NOT_NULL(mp,
527 "ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
528 mbuf_pool_size,
529 ad->dev_id,
530 socket_id);
531 ad->soft_out_mbuf_pool = mp;
532 }
533
534 /* HARQ inputs */
535 if (harq_in->nb_segments > 0) {
536 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
537 harq_in->nb_segments);
538 mp = create_mbuf_pool(harq_in, ad->dev_id, socket_id,
539 mbuf_pool_size,
540 "harq_in");
541 TEST_ASSERT_NOT_NULL(mp,
542 "ERROR Failed to create %uB harq input pktmbuf pool for dev %u on socket %u.",
543 mbuf_pool_size,
544 ad->dev_id,
545 socket_id);
546 ad->harq_in_mbuf_pool = mp;
547 }
548
549 /* HARQ outputs */
550 if (harq_out->nb_segments > 0) {
551 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
552 harq_out->nb_segments);
553 mp = create_mbuf_pool(harq_out, ad->dev_id, socket_id,
554 mbuf_pool_size,
555 "harq_out");
556 TEST_ASSERT_NOT_NULL(mp,
557 "ERROR Failed to create %uB harq output pktmbuf pool for dev %u on socket %u.",
558 mbuf_pool_size,
559 ad->dev_id,
560 socket_id);
561 ad->harq_out_mbuf_pool = mp;
562 }
563
564 return TEST_SUCCESS;
565 }
566
567 static int
add_bbdev_dev(uint8_t dev_id,struct rte_bbdev_info * info,struct test_bbdev_vector * vector)568 add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
569 struct test_bbdev_vector *vector)
570 {
571 int ret;
572 unsigned int queue_id;
573 struct rte_bbdev_queue_conf qconf;
574 struct active_device *ad = &active_devs[nb_active_devs];
575 unsigned int nb_queues;
576 enum rte_bbdev_op_type op_type = vector->op_type;
577
578 /* Configure fpga lte fec with PF & VF values
579 * if '-i' flag is set and using fpga device
580 */
581 #ifdef RTE_BASEBAND_FPGA_LTE_FEC
582 if ((get_init_device() == true) &&
583 (!strcmp(info->drv.driver_name, FPGA_LTE_PF_DRIVER_NAME))) {
584 struct rte_fpga_lte_fec_conf conf;
585 unsigned int i;
586
587 printf("Configure FPGA LTE FEC Driver %s with default values\n",
588 info->drv.driver_name);
589
590 /* clear default configuration before initialization */
591 memset(&conf, 0, sizeof(struct rte_fpga_lte_fec_conf));
592
593 /* Set PF mode :
594 * true if PF is used for data plane
595 * false for VFs
596 */
597 conf.pf_mode_en = true;
598
599 for (i = 0; i < FPGA_LTE_FEC_NUM_VFS; ++i) {
600 /* Number of UL queues per VF (fpga supports 8 VFs) */
601 conf.vf_ul_queues_number[i] = VF_UL_4G_QUEUE_VALUE;
602 /* Number of DL queues per VF (fpga supports 8 VFs) */
603 conf.vf_dl_queues_number[i] = VF_DL_4G_QUEUE_VALUE;
604 }
605
606 /* UL bandwidth. Needed for schedule algorithm */
607 conf.ul_bandwidth = UL_4G_BANDWIDTH;
608 /* DL bandwidth */
609 conf.dl_bandwidth = DL_4G_BANDWIDTH;
610
611 /* UL & DL load Balance Factor to 64 */
612 conf.ul_load_balance = UL_4G_LOAD_BALANCE;
613 conf.dl_load_balance = DL_4G_LOAD_BALANCE;
614
615 /**< FLR timeout value */
616 conf.flr_time_out = FLR_4G_TIMEOUT;
617
618 /* setup FPGA PF with configuration information */
619 ret = rte_fpga_lte_fec_configure(info->dev_name, &conf);
620 TEST_ASSERT_SUCCESS(ret,
621 "Failed to configure 4G FPGA PF for bbdev %s",
622 info->dev_name);
623 }
624 #endif
625 #ifdef RTE_BASEBAND_FPGA_5GNR_FEC
626 if ((get_init_device() == true) &&
627 (!strcmp(info->drv.driver_name, FPGA_5GNR_PF_DRIVER_NAME))) {
628 struct rte_fpga_5gnr_fec_conf conf;
629 unsigned int i;
630
631 printf("Configure FPGA 5GNR FEC Driver %s with default values\n",
632 info->drv.driver_name);
633
634 /* clear default configuration before initialization */
635 memset(&conf, 0, sizeof(struct rte_fpga_5gnr_fec_conf));
636
637 /* Set PF mode :
638 * true if PF is used for data plane
639 * false for VFs
640 */
641 conf.pf_mode_en = true;
642
643 for (i = 0; i < FPGA_5GNR_FEC_NUM_VFS; ++i) {
644 /* Number of UL queues per VF (fpga supports 8 VFs) */
645 conf.vf_ul_queues_number[i] = VF_UL_5G_QUEUE_VALUE;
646 /* Number of DL queues per VF (fpga supports 8 VFs) */
647 conf.vf_dl_queues_number[i] = VF_DL_5G_QUEUE_VALUE;
648 }
649
650 /* UL bandwidth. Needed for schedule algorithm */
651 conf.ul_bandwidth = UL_5G_BANDWIDTH;
652 /* DL bandwidth */
653 conf.dl_bandwidth = DL_5G_BANDWIDTH;
654
655 /* UL & DL load Balance Factor to 64 */
656 conf.ul_load_balance = UL_5G_LOAD_BALANCE;
657 conf.dl_load_balance = DL_5G_LOAD_BALANCE;
658
659 /**< FLR timeout value */
660 conf.flr_time_out = FLR_5G_TIMEOUT;
661
662 /* setup FPGA PF with configuration information */
663 ret = rte_fpga_5gnr_fec_configure(info->dev_name, &conf);
664 TEST_ASSERT_SUCCESS(ret,
665 "Failed to configure 5G FPGA PF for bbdev %s",
666 info->dev_name);
667 }
668 #endif
669 #ifdef RTE_BASEBAND_ACC100
670 if ((get_init_device() == true) &&
671 (!strcmp(info->drv.driver_name, ACC100PF_DRIVER_NAME))) {
672 struct rte_acc100_conf conf;
673 unsigned int i;
674
675 printf("Configure ACC100 FEC Driver %s with default values\n",
676 info->drv.driver_name);
677
678 /* clear default configuration before initialization */
679 memset(&conf, 0, sizeof(struct rte_acc100_conf));
680
681 /* Always set in PF mode for built-in configuration */
682 conf.pf_mode_en = true;
683 for (i = 0; i < RTE_ACC100_NUM_VFS; ++i) {
684 conf.arb_dl_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
685 conf.arb_dl_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
686 conf.arb_dl_4g[i].round_robin_weight = ACC100_QMGR_RR;
687 conf.arb_ul_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
688 conf.arb_ul_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
689 conf.arb_ul_4g[i].round_robin_weight = ACC100_QMGR_RR;
690 conf.arb_dl_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
691 conf.arb_dl_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
692 conf.arb_dl_5g[i].round_robin_weight = ACC100_QMGR_RR;
693 conf.arb_ul_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
694 conf.arb_ul_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
695 conf.arb_ul_5g[i].round_robin_weight = ACC100_QMGR_RR;
696 }
697
698 conf.input_pos_llr_1_bit = true;
699 conf.output_pos_llr_1_bit = true;
700 conf.num_vf_bundles = 1; /**< Number of VF bundles to setup */
701
702 conf.q_ul_4g.num_qgroups = ACC100_QMGR_NUM_QGS;
703 conf.q_ul_4g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
704 conf.q_ul_4g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
705 conf.q_ul_4g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
706 conf.q_dl_4g.num_qgroups = ACC100_QMGR_NUM_QGS;
707 conf.q_dl_4g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
708 conf.q_dl_4g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
709 conf.q_dl_4g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
710 conf.q_ul_5g.num_qgroups = ACC100_QMGR_NUM_QGS;
711 conf.q_ul_5g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
712 conf.q_ul_5g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
713 conf.q_ul_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
714 conf.q_dl_5g.num_qgroups = ACC100_QMGR_NUM_QGS;
715 conf.q_dl_5g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
716 conf.q_dl_5g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
717 conf.q_dl_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
718
719 /* setup PF with configuration information */
720 ret = rte_acc100_configure(info->dev_name, &conf);
721 TEST_ASSERT_SUCCESS(ret,
722 "Failed to configure ACC100 PF for bbdev %s",
723 info->dev_name);
724 }
725 #endif
726 /* Let's refresh this now this is configured */
727 rte_bbdev_info_get(dev_id, info);
728 nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
729 nb_queues = RTE_MIN(nb_queues, (unsigned int) MAX_QUEUES);
730
731 /* setup device */
732 ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
733 if (ret < 0) {
734 printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
735 dev_id, nb_queues, info->socket_id, ret);
736 return TEST_FAILED;
737 }
738
739 /* configure interrupts if needed */
740 if (intr_enabled) {
741 ret = rte_bbdev_intr_enable(dev_id);
742 if (ret < 0) {
743 printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
744 ret);
745 return TEST_FAILED;
746 }
747 }
748
749 /* setup device queues */
750 qconf.socket = info->socket_id;
751 qconf.queue_size = info->drv.default_queue_conf.queue_size;
752 qconf.priority = 0;
753 qconf.deferred_start = 0;
754 qconf.op_type = op_type;
755
756 for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
757 ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
758 if (ret != 0) {
759 printf(
760 "Allocated all queues (id=%u) at prio%u on dev%u\n",
761 queue_id, qconf.priority, dev_id);
762 qconf.priority++;
763 ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
764 &qconf);
765 }
766 if (ret != 0) {
767 printf("All queues on dev %u allocated: %u\n",
768 dev_id, queue_id);
769 break;
770 }
771 ad->queue_ids[queue_id] = queue_id;
772 }
773 TEST_ASSERT(queue_id != 0,
774 "ERROR Failed to configure any queues on dev %u",
775 dev_id);
776 ad->nb_queues = queue_id;
777
778 set_avail_op(ad, op_type);
779
780 return TEST_SUCCESS;
781 }
782
783 static int
add_active_device(uint8_t dev_id,struct rte_bbdev_info * info,struct test_bbdev_vector * vector)784 add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
785 struct test_bbdev_vector *vector)
786 {
787 int ret;
788
789 active_devs[nb_active_devs].driver_name = info->drv.driver_name;
790 active_devs[nb_active_devs].dev_id = dev_id;
791
792 ret = add_bbdev_dev(dev_id, info, vector);
793 if (ret == TEST_SUCCESS)
794 ++nb_active_devs;
795 return ret;
796 }
797
798 static uint8_t
populate_active_devices(void)799 populate_active_devices(void)
800 {
801 int ret;
802 uint8_t dev_id;
803 uint8_t nb_devs_added = 0;
804 struct rte_bbdev_info info;
805
806 RTE_BBDEV_FOREACH(dev_id) {
807 rte_bbdev_info_get(dev_id, &info);
808
809 if (check_dev_cap(&info)) {
810 printf(
811 "Device %d (%s) does not support specified capabilities\n",
812 dev_id, info.dev_name);
813 continue;
814 }
815
816 ret = add_active_device(dev_id, &info, &test_vector);
817 if (ret != 0) {
818 printf("Adding active bbdev %s skipped\n",
819 info.dev_name);
820 continue;
821 }
822 nb_devs_added++;
823 }
824
825 return nb_devs_added;
826 }
827
828 static int
read_test_vector(void)829 read_test_vector(void)
830 {
831 int ret;
832
833 memset(&test_vector, 0, sizeof(test_vector));
834 printf("Test vector file = %s\n", get_vector_filename());
835 ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
836 TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
837 get_vector_filename());
838
839 return TEST_SUCCESS;
840 }
841
842 static int
testsuite_setup(void)843 testsuite_setup(void)
844 {
845 TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
846
847 if (populate_active_devices() == 0) {
848 printf("No suitable devices found!\n");
849 return TEST_SKIPPED;
850 }
851
852 return TEST_SUCCESS;
853 }
854
855 static int
interrupt_testsuite_setup(void)856 interrupt_testsuite_setup(void)
857 {
858 TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
859
860 /* Enable interrupts */
861 intr_enabled = true;
862
863 /* Special case for NULL device (RTE_BBDEV_OP_NONE) */
864 if (populate_active_devices() == 0 ||
865 test_vector.op_type == RTE_BBDEV_OP_NONE) {
866 intr_enabled = false;
867 printf("No suitable devices found!\n");
868 return TEST_SKIPPED;
869 }
870
871 return TEST_SUCCESS;
872 }
873
874 static void
testsuite_teardown(void)875 testsuite_teardown(void)
876 {
877 uint8_t dev_id;
878
879 /* Unconfigure devices */
880 RTE_BBDEV_FOREACH(dev_id)
881 rte_bbdev_close(dev_id);
882
883 /* Clear active devices structs. */
884 memset(active_devs, 0, sizeof(active_devs));
885 nb_active_devs = 0;
886
887 /* Disable interrupts */
888 intr_enabled = false;
889 }
890
891 static int
ut_setup(void)892 ut_setup(void)
893 {
894 uint8_t i, dev_id;
895
896 for (i = 0; i < nb_active_devs; i++) {
897 dev_id = active_devs[i].dev_id;
898 /* reset bbdev stats */
899 TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
900 "Failed to reset stats of bbdev %u", dev_id);
901 /* start the device */
902 TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
903 "Failed to start bbdev %u", dev_id);
904 }
905
906 return TEST_SUCCESS;
907 }
908
909 static void
ut_teardown(void)910 ut_teardown(void)
911 {
912 uint8_t i, dev_id;
913 struct rte_bbdev_stats stats;
914
915 for (i = 0; i < nb_active_devs; i++) {
916 dev_id = active_devs[i].dev_id;
917 /* read stats and print */
918 rte_bbdev_stats_get(dev_id, &stats);
919 /* Stop the device */
920 rte_bbdev_stop(dev_id);
921 }
922 }
923
924 static int
init_op_data_objs(struct rte_bbdev_op_data * bufs,struct op_data_entries * ref_entries,struct rte_mempool * mbuf_pool,const uint16_t n,enum op_data_type op_type,uint16_t min_alignment)925 init_op_data_objs(struct rte_bbdev_op_data *bufs,
926 struct op_data_entries *ref_entries,
927 struct rte_mempool *mbuf_pool, const uint16_t n,
928 enum op_data_type op_type, uint16_t min_alignment)
929 {
930 int ret;
931 unsigned int i, j;
932 bool large_input = false;
933
934 for (i = 0; i < n; ++i) {
935 char *data;
936 struct op_data_buf *seg = &ref_entries->segments[0];
937 struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
938 TEST_ASSERT_NOT_NULL(m_head,
939 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
940 op_type, n * ref_entries->nb_segments,
941 mbuf_pool->size);
942
943 if (seg->length > RTE_BBDEV_LDPC_E_MAX_MBUF) {
944 /*
945 * Special case when DPDK mbuf cannot handle
946 * the required input size
947 */
948 printf("Warning: Larger input size than DPDK mbuf %d\n",
949 seg->length);
950 large_input = true;
951 }
952 bufs[i].data = m_head;
953 bufs[i].offset = 0;
954 bufs[i].length = 0;
955
956 if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) {
957 if ((op_type == DATA_INPUT) && large_input) {
958 /* Allocate a fake overused mbuf */
959 data = rte_malloc(NULL, seg->length, 0);
960 memcpy(data, seg->addr, seg->length);
961 m_head->buf_addr = data;
962 m_head->buf_iova = rte_malloc_virt2iova(data);
963 m_head->data_off = 0;
964 m_head->data_len = seg->length;
965 } else {
966 data = rte_pktmbuf_append(m_head, seg->length);
967 TEST_ASSERT_NOT_NULL(data,
968 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
969 seg->length, op_type);
970
971 TEST_ASSERT(data == RTE_PTR_ALIGN(
972 data, min_alignment),
973 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
974 data, min_alignment);
975 rte_memcpy(data, seg->addr, seg->length);
976 }
977
978 bufs[i].length += seg->length;
979
980 for (j = 1; j < ref_entries->nb_segments; ++j) {
981 struct rte_mbuf *m_tail =
982 rte_pktmbuf_alloc(mbuf_pool);
983 TEST_ASSERT_NOT_NULL(m_tail,
984 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
985 op_type,
986 n * ref_entries->nb_segments,
987 mbuf_pool->size);
988 seg += 1;
989
990 data = rte_pktmbuf_append(m_tail, seg->length);
991 TEST_ASSERT_NOT_NULL(data,
992 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
993 seg->length, op_type);
994
995 TEST_ASSERT(data == RTE_PTR_ALIGN(data,
996 min_alignment),
997 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
998 data, min_alignment);
999 rte_memcpy(data, seg->addr, seg->length);
1000 bufs[i].length += seg->length;
1001
1002 ret = rte_pktmbuf_chain(m_head, m_tail);
1003 TEST_ASSERT_SUCCESS(ret,
1004 "Couldn't chain mbufs from %d data type mbuf pool",
1005 op_type);
1006 }
1007 } else {
1008
1009 /* allocate chained-mbuf for output buffer */
1010 for (j = 1; j < ref_entries->nb_segments; ++j) {
1011 struct rte_mbuf *m_tail =
1012 rte_pktmbuf_alloc(mbuf_pool);
1013 TEST_ASSERT_NOT_NULL(m_tail,
1014 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
1015 op_type,
1016 n * ref_entries->nb_segments,
1017 mbuf_pool->size);
1018
1019 ret = rte_pktmbuf_chain(m_head, m_tail);
1020 TEST_ASSERT_SUCCESS(ret,
1021 "Couldn't chain mbufs from %d data type mbuf pool",
1022 op_type);
1023 }
1024 }
1025 }
1026
1027 return 0;
1028 }
1029
1030 static int
allocate_buffers_on_socket(struct rte_bbdev_op_data ** buffers,const int len,const int socket)1031 allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
1032 const int socket)
1033 {
1034 int i;
1035
1036 *buffers = rte_zmalloc_socket(NULL, len, 0, socket);
1037 if (*buffers == NULL) {
1038 printf("WARNING: Failed to allocate op_data on socket %d\n",
1039 socket);
1040 /* try to allocate memory on other detected sockets */
1041 for (i = 0; i < socket; i++) {
1042 *buffers = rte_zmalloc_socket(NULL, len, 0, i);
1043 if (*buffers != NULL)
1044 break;
1045 }
1046 }
1047
1048 return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
1049 }
1050
1051 static void
limit_input_llr_val_range(struct rte_bbdev_op_data * input_ops,const uint16_t n,const int8_t max_llr_modulus)1052 limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
1053 const uint16_t n, const int8_t max_llr_modulus)
1054 {
1055 uint16_t i, byte_idx;
1056
1057 for (i = 0; i < n; ++i) {
1058 struct rte_mbuf *m = input_ops[i].data;
1059 while (m != NULL) {
1060 int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
1061 input_ops[i].offset);
1062 for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
1063 ++byte_idx)
1064 llr[byte_idx] = round((double)max_llr_modulus *
1065 llr[byte_idx] / INT8_MAX);
1066
1067 m = m->next;
1068 }
1069 }
1070 }
1071
1072 /*
1073 * We may have to insert filler bits
1074 * when they are required by the HARQ assumption
1075 */
1076 static void
ldpc_add_filler(struct rte_bbdev_op_data * input_ops,const uint16_t n,struct test_op_params * op_params)1077 ldpc_add_filler(struct rte_bbdev_op_data *input_ops,
1078 const uint16_t n, struct test_op_params *op_params)
1079 {
1080 struct rte_bbdev_op_ldpc_dec dec = op_params->ref_dec_op->ldpc_dec;
1081
1082 if (input_ops == NULL)
1083 return;
1084 /* No need to add filler if not required by device */
1085 if (!(ldpc_cap_flags &
1086 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS))
1087 return;
1088 /* No need to add filler for loopback operation */
1089 if (dec.op_flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
1090 return;
1091
1092 uint16_t i, j, parity_offset;
1093 for (i = 0; i < n; ++i) {
1094 struct rte_mbuf *m = input_ops[i].data;
1095 int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
1096 input_ops[i].offset);
1097 parity_offset = (dec.basegraph == 1 ? 20 : 8)
1098 * dec.z_c - dec.n_filler;
1099 uint16_t new_hin_size = input_ops[i].length + dec.n_filler;
1100 m->data_len = new_hin_size;
1101 input_ops[i].length = new_hin_size;
1102 for (j = new_hin_size - 1; j >= parity_offset + dec.n_filler;
1103 j--)
1104 llr[j] = llr[j - dec.n_filler];
1105 uint16_t llr_max_pre_scaling = (1 << (ldpc_llr_size - 1)) - 1;
1106 for (j = 0; j < dec.n_filler; j++)
1107 llr[parity_offset + j] = llr_max_pre_scaling;
1108 }
1109 }
1110
1111 static void
ldpc_input_llr_scaling(struct rte_bbdev_op_data * input_ops,const uint16_t n,const int8_t llr_size,const int8_t llr_decimals)1112 ldpc_input_llr_scaling(struct rte_bbdev_op_data *input_ops,
1113 const uint16_t n, const int8_t llr_size,
1114 const int8_t llr_decimals)
1115 {
1116 if (input_ops == NULL)
1117 return;
1118
1119 uint16_t i, byte_idx;
1120
1121 int16_t llr_max, llr_min, llr_tmp;
1122 llr_max = (1 << (llr_size - 1)) - 1;
1123 llr_min = -llr_max;
1124 for (i = 0; i < n; ++i) {
1125 struct rte_mbuf *m = input_ops[i].data;
1126 while (m != NULL) {
1127 int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
1128 input_ops[i].offset);
1129 for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
1130 ++byte_idx) {
1131
1132 llr_tmp = llr[byte_idx];
1133 if (llr_decimals == 4)
1134 llr_tmp *= 8;
1135 else if (llr_decimals == 2)
1136 llr_tmp *= 2;
1137 else if (llr_decimals == 0)
1138 llr_tmp /= 2;
1139 llr_tmp = RTE_MIN(llr_max,
1140 RTE_MAX(llr_min, llr_tmp));
1141 llr[byte_idx] = (int8_t) llr_tmp;
1142 }
1143
1144 m = m->next;
1145 }
1146 }
1147 }
1148
1149
1150
1151 static int
fill_queue_buffers(struct test_op_params * op_params,struct rte_mempool * in_mp,struct rte_mempool * hard_out_mp,struct rte_mempool * soft_out_mp,struct rte_mempool * harq_in_mp,struct rte_mempool * harq_out_mp,uint16_t queue_id,const struct rte_bbdev_op_cap * capabilities,uint16_t min_alignment,const int socket_id)1152 fill_queue_buffers(struct test_op_params *op_params,
1153 struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
1154 struct rte_mempool *soft_out_mp,
1155 struct rte_mempool *harq_in_mp, struct rte_mempool *harq_out_mp,
1156 uint16_t queue_id,
1157 const struct rte_bbdev_op_cap *capabilities,
1158 uint16_t min_alignment, const int socket_id)
1159 {
1160 int ret;
1161 enum op_data_type type;
1162 const uint16_t n = op_params->num_to_process;
1163
1164 struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
1165 in_mp,
1166 soft_out_mp,
1167 hard_out_mp,
1168 harq_in_mp,
1169 harq_out_mp,
1170 };
1171
1172 struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
1173 &op_params->q_bufs[socket_id][queue_id].inputs,
1174 &op_params->q_bufs[socket_id][queue_id].soft_outputs,
1175 &op_params->q_bufs[socket_id][queue_id].hard_outputs,
1176 &op_params->q_bufs[socket_id][queue_id].harq_inputs,
1177 &op_params->q_bufs[socket_id][queue_id].harq_outputs,
1178 };
1179
1180 for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
1181 struct op_data_entries *ref_entries =
1182 &test_vector.entries[type];
1183 if (ref_entries->nb_segments == 0)
1184 continue;
1185
1186 ret = allocate_buffers_on_socket(queue_ops[type],
1187 n * sizeof(struct rte_bbdev_op_data),
1188 socket_id);
1189 TEST_ASSERT_SUCCESS(ret,
1190 "Couldn't allocate memory for rte_bbdev_op_data structs");
1191
1192 ret = init_op_data_objs(*queue_ops[type], ref_entries,
1193 mbuf_pools[type], n, type, min_alignment);
1194 TEST_ASSERT_SUCCESS(ret,
1195 "Couldn't init rte_bbdev_op_data structs");
1196 }
1197
1198 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1199 limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
1200 capabilities->cap.turbo_dec.max_llr_modulus);
1201
1202 if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
1203 bool loopback = op_params->ref_dec_op->ldpc_dec.op_flags &
1204 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
1205 bool llr_comp = op_params->ref_dec_op->ldpc_dec.op_flags &
1206 RTE_BBDEV_LDPC_LLR_COMPRESSION;
1207 bool harq_comp = op_params->ref_dec_op->ldpc_dec.op_flags &
1208 RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
1209 ldpc_llr_decimals = capabilities->cap.ldpc_dec.llr_decimals;
1210 ldpc_llr_size = capabilities->cap.ldpc_dec.llr_size;
1211 ldpc_cap_flags = capabilities->cap.ldpc_dec.capability_flags;
1212 if (!loopback && !llr_comp)
1213 ldpc_input_llr_scaling(*queue_ops[DATA_INPUT], n,
1214 ldpc_llr_size, ldpc_llr_decimals);
1215 if (!loopback && !harq_comp)
1216 ldpc_input_llr_scaling(*queue_ops[DATA_HARQ_INPUT], n,
1217 ldpc_llr_size, ldpc_llr_decimals);
1218 if (!loopback)
1219 ldpc_add_filler(*queue_ops[DATA_HARQ_INPUT], n,
1220 op_params);
1221 }
1222
1223 return 0;
1224 }
1225
1226 static void
free_buffers(struct active_device * ad,struct test_op_params * op_params)1227 free_buffers(struct active_device *ad, struct test_op_params *op_params)
1228 {
1229 unsigned int i, j;
1230
1231 rte_mempool_free(ad->ops_mempool);
1232 rte_mempool_free(ad->in_mbuf_pool);
1233 rte_mempool_free(ad->hard_out_mbuf_pool);
1234 rte_mempool_free(ad->soft_out_mbuf_pool);
1235 rte_mempool_free(ad->harq_in_mbuf_pool);
1236 rte_mempool_free(ad->harq_out_mbuf_pool);
1237
1238 for (i = 0; i < rte_lcore_count(); ++i) {
1239 for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
1240 rte_free(op_params->q_bufs[j][i].inputs);
1241 rte_free(op_params->q_bufs[j][i].hard_outputs);
1242 rte_free(op_params->q_bufs[j][i].soft_outputs);
1243 rte_free(op_params->q_bufs[j][i].harq_inputs);
1244 rte_free(op_params->q_bufs[j][i].harq_outputs);
1245 }
1246 }
1247 }
1248
1249 static void
copy_reference_dec_op(struct rte_bbdev_dec_op ** ops,unsigned int n,unsigned int start_idx,struct rte_bbdev_op_data * inputs,struct rte_bbdev_op_data * hard_outputs,struct rte_bbdev_op_data * soft_outputs,struct rte_bbdev_dec_op * ref_op)1250 copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
1251 unsigned int start_idx,
1252 struct rte_bbdev_op_data *inputs,
1253 struct rte_bbdev_op_data *hard_outputs,
1254 struct rte_bbdev_op_data *soft_outputs,
1255 struct rte_bbdev_dec_op *ref_op)
1256 {
1257 unsigned int i;
1258 struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
1259
1260 for (i = 0; i < n; ++i) {
1261 if (turbo_dec->code_block_mode == 0) {
1262 ops[i]->turbo_dec.tb_params.ea =
1263 turbo_dec->tb_params.ea;
1264 ops[i]->turbo_dec.tb_params.eb =
1265 turbo_dec->tb_params.eb;
1266 ops[i]->turbo_dec.tb_params.k_pos =
1267 turbo_dec->tb_params.k_pos;
1268 ops[i]->turbo_dec.tb_params.k_neg =
1269 turbo_dec->tb_params.k_neg;
1270 ops[i]->turbo_dec.tb_params.c =
1271 turbo_dec->tb_params.c;
1272 ops[i]->turbo_dec.tb_params.c_neg =
1273 turbo_dec->tb_params.c_neg;
1274 ops[i]->turbo_dec.tb_params.cab =
1275 turbo_dec->tb_params.cab;
1276 ops[i]->turbo_dec.tb_params.r =
1277 turbo_dec->tb_params.r;
1278 } else {
1279 ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
1280 ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
1281 }
1282
1283 ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
1284 ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
1285 ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
1286 ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
1287 ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
1288 ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
1289 ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
1290
1291 ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
1292 ops[i]->turbo_dec.input = inputs[start_idx + i];
1293 if (soft_outputs != NULL)
1294 ops[i]->turbo_dec.soft_output =
1295 soft_outputs[start_idx + i];
1296 }
1297 }
1298
1299 static void
copy_reference_enc_op(struct rte_bbdev_enc_op ** ops,unsigned int n,unsigned int start_idx,struct rte_bbdev_op_data * inputs,struct rte_bbdev_op_data * outputs,struct rte_bbdev_enc_op * ref_op)1300 copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
1301 unsigned int start_idx,
1302 struct rte_bbdev_op_data *inputs,
1303 struct rte_bbdev_op_data *outputs,
1304 struct rte_bbdev_enc_op *ref_op)
1305 {
1306 unsigned int i;
1307 struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
1308 for (i = 0; i < n; ++i) {
1309 if (turbo_enc->code_block_mode == 0) {
1310 ops[i]->turbo_enc.tb_params.ea =
1311 turbo_enc->tb_params.ea;
1312 ops[i]->turbo_enc.tb_params.eb =
1313 turbo_enc->tb_params.eb;
1314 ops[i]->turbo_enc.tb_params.k_pos =
1315 turbo_enc->tb_params.k_pos;
1316 ops[i]->turbo_enc.tb_params.k_neg =
1317 turbo_enc->tb_params.k_neg;
1318 ops[i]->turbo_enc.tb_params.c =
1319 turbo_enc->tb_params.c;
1320 ops[i]->turbo_enc.tb_params.c_neg =
1321 turbo_enc->tb_params.c_neg;
1322 ops[i]->turbo_enc.tb_params.cab =
1323 turbo_enc->tb_params.cab;
1324 ops[i]->turbo_enc.tb_params.ncb_pos =
1325 turbo_enc->tb_params.ncb_pos;
1326 ops[i]->turbo_enc.tb_params.ncb_neg =
1327 turbo_enc->tb_params.ncb_neg;
1328 ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
1329 } else {
1330 ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
1331 ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
1332 ops[i]->turbo_enc.cb_params.ncb =
1333 turbo_enc->cb_params.ncb;
1334 }
1335 ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
1336 ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
1337 ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
1338
1339 ops[i]->turbo_enc.output = outputs[start_idx + i];
1340 ops[i]->turbo_enc.input = inputs[start_idx + i];
1341 }
1342 }
1343
1344
1345 /* Returns a random number drawn from a normal distribution
1346 * with mean of 0 and variance of 1
1347 * Marsaglia algorithm
1348 */
1349 static double
randn(int n)1350 randn(int n)
1351 {
1352 double S, Z, U1, U2, u, v, fac;
1353
1354 do {
1355 U1 = (double)rand() / RAND_MAX;
1356 U2 = (double)rand() / RAND_MAX;
1357 u = 2. * U1 - 1.;
1358 v = 2. * U2 - 1.;
1359 S = u * u + v * v;
1360 } while (S >= 1 || S == 0);
1361 fac = sqrt(-2. * log(S) / S);
1362 Z = (n % 2) ? u * fac : v * fac;
1363 return Z;
1364 }
1365
1366 static inline double
maxstar(double A,double B)1367 maxstar(double A, double B)
1368 {
1369 if (fabs(A - B) > 5)
1370 return RTE_MAX(A, B);
1371 else
1372 return RTE_MAX(A, B) + log1p(exp(-fabs(A - B)));
1373 }
1374
1375 /*
1376 * Generate Qm LLRS for Qm==8
1377 * Modulation, AWGN and LLR estimation from max log development
1378 */
1379 static void
gen_qm8_llr(int8_t * llrs,uint32_t i,double N0,double llr_max)1380 gen_qm8_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
1381 {
1382 int qm = 8;
1383 int qam = 256;
1384 int m, k;
1385 double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
1386 /* 5.1.4 of TS38.211 */
1387 const double symbols_I[256] = {
1388 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 5,
1389 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 11,
1390 11, 9, 9, 11, 11, 9, 9, 13, 13, 15, 15, 13, 13,
1391 15, 15, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13, 15,
1392 15, 13, 13, 15, 15, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3,
1393 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1,
1394 1, 3, 3, 1, 1, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13,
1395 15, 15, 13, 13, 15, 15, 11, 11, 9, 9, 11, 11, 9, 9,
1396 13, 13, 15, 15, 13, 13, 15, 15, -5, -5, -7, -7, -5,
1397 -5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -5, -5,
1398 -7, -7, -5, -5, -7, -7, -3, -3, -1, -1, -3, -3,
1399 -1, -1, -11, -11, -9, -9, -11, -11, -9, -9, -13,
1400 -13, -15, -15, -13, -13, -15, -15, -11, -11, -9,
1401 -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
1402 -13, -15, -15, -5, -5, -7, -7, -5, -5, -7, -7, -3,
1403 -3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7, -5, -5,
1404 -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -11, -11,
1405 -9, -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
1406 -13, -15, -15, -11, -11, -9, -9, -11, -11, -9, -9,
1407 -13, -13, -15, -15, -13, -13, -15, -15};
1408 const double symbols_Q[256] = {
1409 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
1410 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15, 13,
1411 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
1412 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13,
1413 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1, -5,
1414 -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13,
1415 -15, -13, -15, -11, -9, -11, -9, -13, -15, -13,
1416 -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7, -5,
1417 -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
1418 -13, -15, -11, -9, -11, -9, -13, -15, -13, -15, 5,
1419 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
1420 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15,
1421 13, 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1,
1422 3, 1, 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9,
1423 13, 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1,
1424 -5, -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9,
1425 -13, -15, -13, -15, -11, -9, -11, -9, -13, -15,
1426 -13, -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7,
1427 -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
1428 -13, -15, -11, -9, -11, -9, -13, -15, -13, -15};
1429 /* Average constellation point energy */
1430 N0 *= 170.0;
1431 for (k = 0; k < qm; k++)
1432 b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
1433 /* 5.1.4 of TS38.211 */
1434 I = (1 - 2 * b[0]) * (8 - (1 - 2 * b[2]) *
1435 (4 - (1 - 2 * b[4]) * (2 - (1 - 2 * b[6]))));
1436 Q = (1 - 2 * b[1]) * (8 - (1 - 2 * b[3]) *
1437 (4 - (1 - 2 * b[5]) * (2 - (1 - 2 * b[7]))));
1438 /* AWGN channel */
1439 I += sqrt(N0 / 2) * randn(0);
1440 Q += sqrt(N0 / 2) * randn(1);
1441 /*
1442 * Calculate the log of the probability that each of
1443 * the constellation points was transmitted
1444 */
1445 for (m = 0; m < qam; m++)
1446 log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
1447 + pow(Q - symbols_Q[m], 2.0)) / N0;
1448 /* Calculate an LLR for each of the k_64QAM bits in the set */
1449 for (k = 0; k < qm; k++) {
1450 p0 = -999999;
1451 p1 = -999999;
1452 /* For each constellation point */
1453 for (m = 0; m < qam; m++) {
1454 if ((m >> (qm - k - 1)) & 1)
1455 p1 = maxstar(p1, log_syml_prob[m]);
1456 else
1457 p0 = maxstar(p0, log_syml_prob[m]);
1458 }
1459 /* Calculate the LLR */
1460 llr_ = p0 - p1;
1461 llr_ *= (1 << ldpc_llr_decimals);
1462 llr_ = round(llr_);
1463 if (llr_ > llr_max)
1464 llr_ = llr_max;
1465 if (llr_ < -llr_max)
1466 llr_ = -llr_max;
1467 llrs[qm * i + k] = (int8_t) llr_;
1468 }
1469 }
1470
1471
1472 /*
1473 * Generate Qm LLRS for Qm==6
1474 * Modulation, AWGN and LLR estimation from max log development
1475 */
1476 static void
gen_qm6_llr(int8_t * llrs,uint32_t i,double N0,double llr_max)1477 gen_qm6_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
1478 {
1479 int qm = 6;
1480 int qam = 64;
1481 int m, k;
1482 double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
1483 /* 5.1.4 of TS38.211 */
1484 const double symbols_I[64] = {
1485 3, 3, 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7,
1486 3, 3, 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7,
1487 -3, -3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7,
1488 -5, -5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1,
1489 -5, -5, -7, -7, -5, -5, -7, -7};
1490 const double symbols_Q[64] = {
1491 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7,
1492 -3, -1, -3, -1, -5, -7, -5, -7, -3, -1, -3, -1,
1493 -5, -7, -5, -7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
1494 5, 7, 5, 7, -3, -1, -3, -1, -5, -7, -5, -7,
1495 -3, -1, -3, -1, -5, -7, -5, -7};
1496 /* Average constellation point energy */
1497 N0 *= 42.0;
1498 for (k = 0; k < qm; k++)
1499 b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
1500 /* 5.1.4 of TS38.211 */
1501 I = (1 - 2 * b[0])*(4 - (1 - 2 * b[2]) * (2 - (1 - 2 * b[4])));
1502 Q = (1 - 2 * b[1])*(4 - (1 - 2 * b[3]) * (2 - (1 - 2 * b[5])));
1503 /* AWGN channel */
1504 I += sqrt(N0 / 2) * randn(0);
1505 Q += sqrt(N0 / 2) * randn(1);
1506 /*
1507 * Calculate the log of the probability that each of
1508 * the constellation points was transmitted
1509 */
1510 for (m = 0; m < qam; m++)
1511 log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
1512 + pow(Q - symbols_Q[m], 2.0)) / N0;
1513 /* Calculate an LLR for each of the k_64QAM bits in the set */
1514 for (k = 0; k < qm; k++) {
1515 p0 = -999999;
1516 p1 = -999999;
1517 /* For each constellation point */
1518 for (m = 0; m < qam; m++) {
1519 if ((m >> (qm - k - 1)) & 1)
1520 p1 = maxstar(p1, log_syml_prob[m]);
1521 else
1522 p0 = maxstar(p0, log_syml_prob[m]);
1523 }
1524 /* Calculate the LLR */
1525 llr_ = p0 - p1;
1526 llr_ *= (1 << ldpc_llr_decimals);
1527 llr_ = round(llr_);
1528 if (llr_ > llr_max)
1529 llr_ = llr_max;
1530 if (llr_ < -llr_max)
1531 llr_ = -llr_max;
1532 llrs[qm * i + k] = (int8_t) llr_;
1533 }
1534 }
1535
1536 /*
1537 * Generate Qm LLRS for Qm==4
1538 * Modulation, AWGN and LLR estimation from max log development
1539 */
1540 static void
gen_qm4_llr(int8_t * llrs,uint32_t i,double N0,double llr_max)1541 gen_qm4_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
1542 {
1543 int qm = 4;
1544 int qam = 16;
1545 int m, k;
1546 double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
1547 /* 5.1.4 of TS38.211 */
1548 const double symbols_I[16] = {1, 1, 3, 3, 1, 1, 3, 3,
1549 -1, -1, -3, -3, -1, -1, -3, -3};
1550 const double symbols_Q[16] = {1, 3, 1, 3, -1, -3, -1, -3,
1551 1, 3, 1, 3, -1, -3, -1, -3};
1552 /* Average constellation point energy */
1553 N0 *= 10.0;
1554 for (k = 0; k < qm; k++)
1555 b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
1556 /* 5.1.4 of TS38.211 */
1557 I = (1 - 2 * b[0]) * (2 - (1 - 2 * b[2]));
1558 Q = (1 - 2 * b[1]) * (2 - (1 - 2 * b[3]));
1559 /* AWGN channel */
1560 I += sqrt(N0 / 2) * randn(0);
1561 Q += sqrt(N0 / 2) * randn(1);
1562 /*
1563 * Calculate the log of the probability that each of
1564 * the constellation points was transmitted
1565 */
1566 for (m = 0; m < qam; m++)
1567 log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
1568 + pow(Q - symbols_Q[m], 2.0)) / N0;
1569 /* Calculate an LLR for each of the k_64QAM bits in the set */
1570 for (k = 0; k < qm; k++) {
1571 p0 = -999999;
1572 p1 = -999999;
1573 /* For each constellation point */
1574 for (m = 0; m < qam; m++) {
1575 if ((m >> (qm - k - 1)) & 1)
1576 p1 = maxstar(p1, log_syml_prob[m]);
1577 else
1578 p0 = maxstar(p0, log_syml_prob[m]);
1579 }
1580 /* Calculate the LLR */
1581 llr_ = p0 - p1;
1582 llr_ *= (1 << ldpc_llr_decimals);
1583 llr_ = round(llr_);
1584 if (llr_ > llr_max)
1585 llr_ = llr_max;
1586 if (llr_ < -llr_max)
1587 llr_ = -llr_max;
1588 llrs[qm * i + k] = (int8_t) llr_;
1589 }
1590 }
1591
1592 static void
gen_qm2_llr(int8_t * llrs,uint32_t j,double N0,double llr_max)1593 gen_qm2_llr(int8_t *llrs, uint32_t j, double N0, double llr_max)
1594 {
1595 double b, b1, n;
1596 double coeff = 2.0 * sqrt(N0);
1597
1598 /* Ignore in vectors rare quasi null LLRs not to be saturated */
1599 if (llrs[j] < 8 && llrs[j] > -8)
1600 return;
1601
1602 /* Note don't change sign here */
1603 n = randn(j % 2);
1604 b1 = ((llrs[j] > 0 ? 2.0 : -2.0)
1605 + coeff * n) / N0;
1606 b = b1 * (1 << ldpc_llr_decimals);
1607 b = round(b);
1608 if (b > llr_max)
1609 b = llr_max;
1610 if (b < -llr_max)
1611 b = -llr_max;
1612 llrs[j] = (int8_t) b;
1613 }
1614
1615 /* Generate LLR for a given SNR */
1616 static void
generate_llr_input(uint16_t n,struct rte_bbdev_op_data * inputs,struct rte_bbdev_dec_op * ref_op)1617 generate_llr_input(uint16_t n, struct rte_bbdev_op_data *inputs,
1618 struct rte_bbdev_dec_op *ref_op)
1619 {
1620 struct rte_mbuf *m;
1621 uint16_t qm;
1622 uint32_t i, j, e, range;
1623 double N0, llr_max;
1624
1625 e = ref_op->ldpc_dec.cb_params.e;
1626 qm = ref_op->ldpc_dec.q_m;
1627 llr_max = (1 << (ldpc_llr_size - 1)) - 1;
1628 range = e / qm;
1629 N0 = 1.0 / pow(10.0, get_snr() / 10.0);
1630
1631 for (i = 0; i < n; ++i) {
1632 m = inputs[i].data;
1633 int8_t *llrs = rte_pktmbuf_mtod_offset(m, int8_t *, 0);
1634 if (qm == 8) {
1635 for (j = 0; j < range; ++j)
1636 gen_qm8_llr(llrs, j, N0, llr_max);
1637 } else if (qm == 6) {
1638 for (j = 0; j < range; ++j)
1639 gen_qm6_llr(llrs, j, N0, llr_max);
1640 } else if (qm == 4) {
1641 for (j = 0; j < range; ++j)
1642 gen_qm4_llr(llrs, j, N0, llr_max);
1643 } else {
1644 for (j = 0; j < e; ++j)
1645 gen_qm2_llr(llrs, j, N0, llr_max);
1646 }
1647 }
1648 }
1649
1650 static void
copy_reference_ldpc_dec_op(struct rte_bbdev_dec_op ** ops,unsigned int n,unsigned int start_idx,struct rte_bbdev_op_data * inputs,struct rte_bbdev_op_data * hard_outputs,struct rte_bbdev_op_data * soft_outputs,struct rte_bbdev_op_data * harq_inputs,struct rte_bbdev_op_data * harq_outputs,struct rte_bbdev_dec_op * ref_op)1651 copy_reference_ldpc_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
1652 unsigned int start_idx,
1653 struct rte_bbdev_op_data *inputs,
1654 struct rte_bbdev_op_data *hard_outputs,
1655 struct rte_bbdev_op_data *soft_outputs,
1656 struct rte_bbdev_op_data *harq_inputs,
1657 struct rte_bbdev_op_data *harq_outputs,
1658 struct rte_bbdev_dec_op *ref_op)
1659 {
1660 unsigned int i;
1661 struct rte_bbdev_op_ldpc_dec *ldpc_dec = &ref_op->ldpc_dec;
1662
1663 for (i = 0; i < n; ++i) {
1664 if (ldpc_dec->code_block_mode == 0) {
1665 ops[i]->ldpc_dec.tb_params.ea =
1666 ldpc_dec->tb_params.ea;
1667 ops[i]->ldpc_dec.tb_params.eb =
1668 ldpc_dec->tb_params.eb;
1669 ops[i]->ldpc_dec.tb_params.c =
1670 ldpc_dec->tb_params.c;
1671 ops[i]->ldpc_dec.tb_params.cab =
1672 ldpc_dec->tb_params.cab;
1673 ops[i]->ldpc_dec.tb_params.r =
1674 ldpc_dec->tb_params.r;
1675 } else {
1676 ops[i]->ldpc_dec.cb_params.e = ldpc_dec->cb_params.e;
1677 }
1678
1679 ops[i]->ldpc_dec.basegraph = ldpc_dec->basegraph;
1680 ops[i]->ldpc_dec.z_c = ldpc_dec->z_c;
1681 ops[i]->ldpc_dec.q_m = ldpc_dec->q_m;
1682 ops[i]->ldpc_dec.n_filler = ldpc_dec->n_filler;
1683 ops[i]->ldpc_dec.n_cb = ldpc_dec->n_cb;
1684 ops[i]->ldpc_dec.iter_max = ldpc_dec->iter_max;
1685 ops[i]->ldpc_dec.rv_index = ldpc_dec->rv_index;
1686 ops[i]->ldpc_dec.op_flags = ldpc_dec->op_flags;
1687 ops[i]->ldpc_dec.code_block_mode = ldpc_dec->code_block_mode;
1688
1689 if (hard_outputs != NULL)
1690 ops[i]->ldpc_dec.hard_output =
1691 hard_outputs[start_idx + i];
1692 if (inputs != NULL)
1693 ops[i]->ldpc_dec.input =
1694 inputs[start_idx + i];
1695 if (soft_outputs != NULL)
1696 ops[i]->ldpc_dec.soft_output =
1697 soft_outputs[start_idx + i];
1698 if (harq_inputs != NULL)
1699 ops[i]->ldpc_dec.harq_combined_input =
1700 harq_inputs[start_idx + i];
1701 if (harq_outputs != NULL)
1702 ops[i]->ldpc_dec.harq_combined_output =
1703 harq_outputs[start_idx + i];
1704 }
1705 }
1706
1707
1708 static void
copy_reference_ldpc_enc_op(struct rte_bbdev_enc_op ** ops,unsigned int n,unsigned int start_idx,struct rte_bbdev_op_data * inputs,struct rte_bbdev_op_data * outputs,struct rte_bbdev_enc_op * ref_op)1709 copy_reference_ldpc_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
1710 unsigned int start_idx,
1711 struct rte_bbdev_op_data *inputs,
1712 struct rte_bbdev_op_data *outputs,
1713 struct rte_bbdev_enc_op *ref_op)
1714 {
1715 unsigned int i;
1716 struct rte_bbdev_op_ldpc_enc *ldpc_enc = &ref_op->ldpc_enc;
1717 for (i = 0; i < n; ++i) {
1718 if (ldpc_enc->code_block_mode == 0) {
1719 ops[i]->ldpc_enc.tb_params.ea = ldpc_enc->tb_params.ea;
1720 ops[i]->ldpc_enc.tb_params.eb = ldpc_enc->tb_params.eb;
1721 ops[i]->ldpc_enc.tb_params.cab =
1722 ldpc_enc->tb_params.cab;
1723 ops[i]->ldpc_enc.tb_params.c = ldpc_enc->tb_params.c;
1724 ops[i]->ldpc_enc.tb_params.r = ldpc_enc->tb_params.r;
1725 } else {
1726 ops[i]->ldpc_enc.cb_params.e = ldpc_enc->cb_params.e;
1727 }
1728 ops[i]->ldpc_enc.basegraph = ldpc_enc->basegraph;
1729 ops[i]->ldpc_enc.z_c = ldpc_enc->z_c;
1730 ops[i]->ldpc_enc.q_m = ldpc_enc->q_m;
1731 ops[i]->ldpc_enc.n_filler = ldpc_enc->n_filler;
1732 ops[i]->ldpc_enc.n_cb = ldpc_enc->n_cb;
1733 ops[i]->ldpc_enc.rv_index = ldpc_enc->rv_index;
1734 ops[i]->ldpc_enc.op_flags = ldpc_enc->op_flags;
1735 ops[i]->ldpc_enc.code_block_mode = ldpc_enc->code_block_mode;
1736 ops[i]->ldpc_enc.output = outputs[start_idx + i];
1737 ops[i]->ldpc_enc.input = inputs[start_idx + i];
1738 }
1739 }
1740
1741 static int
check_dec_status_and_ordering(struct rte_bbdev_dec_op * op,unsigned int order_idx,const int expected_status)1742 check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
1743 unsigned int order_idx, const int expected_status)
1744 {
1745 int status = op->status;
1746 /* ignore parity mismatch false alarms for long iterations */
1747 if (get_iter_max() >= 10) {
1748 if (!(expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) &&
1749 (status & (1 << RTE_BBDEV_SYNDROME_ERROR))) {
1750 printf("WARNING: Ignore Syndrome Check mismatch\n");
1751 status -= (1 << RTE_BBDEV_SYNDROME_ERROR);
1752 }
1753 if ((expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) &&
1754 !(status & (1 << RTE_BBDEV_SYNDROME_ERROR))) {
1755 printf("WARNING: Ignore Syndrome Check mismatch\n");
1756 status += (1 << RTE_BBDEV_SYNDROME_ERROR);
1757 }
1758 }
1759
1760 TEST_ASSERT(status == expected_status,
1761 "op_status (%d) != expected_status (%d)",
1762 op->status, expected_status);
1763
1764 TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1765 "Ordering error, expected %p, got %p",
1766 (void *)(uintptr_t)order_idx, op->opaque_data);
1767
1768 return TEST_SUCCESS;
1769 }
1770
1771 static int
check_enc_status_and_ordering(struct rte_bbdev_enc_op * op,unsigned int order_idx,const int expected_status)1772 check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
1773 unsigned int order_idx, const int expected_status)
1774 {
1775 TEST_ASSERT(op->status == expected_status,
1776 "op_status (%d) != expected_status (%d)",
1777 op->status, expected_status);
1778
1779 if (op->opaque_data != (void *)(uintptr_t)INVALID_OPAQUE)
1780 TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1781 "Ordering error, expected %p, got %p",
1782 (void *)(uintptr_t)order_idx, op->opaque_data);
1783
1784 return TEST_SUCCESS;
1785 }
1786
1787 static inline int
validate_op_chain(struct rte_bbdev_op_data * op,struct op_data_entries * orig_op)1788 validate_op_chain(struct rte_bbdev_op_data *op,
1789 struct op_data_entries *orig_op)
1790 {
1791 uint8_t i;
1792 struct rte_mbuf *m = op->data;
1793 uint8_t nb_dst_segments = orig_op->nb_segments;
1794 uint32_t total_data_size = 0;
1795
1796 TEST_ASSERT(nb_dst_segments == m->nb_segs,
1797 "Number of segments differ in original (%u) and filled (%u) op",
1798 nb_dst_segments, m->nb_segs);
1799
1800 /* Validate each mbuf segment length */
1801 for (i = 0; i < nb_dst_segments; ++i) {
1802 /* Apply offset to the first mbuf segment */
1803 uint16_t offset = (i == 0) ? op->offset : 0;
1804 uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
1805 total_data_size += orig_op->segments[i].length;
1806
1807 TEST_ASSERT(orig_op->segments[i].length == data_len,
1808 "Length of segment differ in original (%u) and filled (%u) op",
1809 orig_op->segments[i].length, data_len);
1810 TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
1811 rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
1812 data_len,
1813 "Output buffers (CB=%u) are not equal", i);
1814 m = m->next;
1815 }
1816
1817 /* Validate total mbuf pkt length */
1818 uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
1819 TEST_ASSERT(total_data_size == pkt_len,
1820 "Length of data differ in original (%u) and filled (%u) op",
1821 total_data_size, pkt_len);
1822
1823 return TEST_SUCCESS;
1824 }
1825
1826 /*
1827 * Compute K0 for a given configuration for HARQ output length computation
1828 * As per definition in 3GPP 38.212 Table 5.4.2.1-2
1829 */
1830 static inline uint16_t
get_k0(uint16_t n_cb,uint16_t z_c,uint8_t bg,uint8_t rv_index)1831 get_k0(uint16_t n_cb, uint16_t z_c, uint8_t bg, uint8_t rv_index)
1832 {
1833 if (rv_index == 0)
1834 return 0;
1835 uint16_t n = (bg == 1 ? N_ZC_1 : N_ZC_2) * z_c;
1836 if (n_cb == n) {
1837 if (rv_index == 1)
1838 return (bg == 1 ? K0_1_1 : K0_1_2) * z_c;
1839 else if (rv_index == 2)
1840 return (bg == 1 ? K0_2_1 : K0_2_2) * z_c;
1841 else
1842 return (bg == 1 ? K0_3_1 : K0_3_2) * z_c;
1843 }
1844 /* LBRM case - includes a division by N */
1845 if (rv_index == 1)
1846 return (((bg == 1 ? K0_1_1 : K0_1_2) * n_cb)
1847 / n) * z_c;
1848 else if (rv_index == 2)
1849 return (((bg == 1 ? K0_2_1 : K0_2_2) * n_cb)
1850 / n) * z_c;
1851 else
1852 return (((bg == 1 ? K0_3_1 : K0_3_2) * n_cb)
1853 / n) * z_c;
1854 }
1855
1856 /* HARQ output length including the Filler bits */
1857 static inline uint16_t
compute_harq_len(struct rte_bbdev_op_ldpc_dec * ops_ld)1858 compute_harq_len(struct rte_bbdev_op_ldpc_dec *ops_ld)
1859 {
1860 uint16_t k0 = 0;
1861 uint8_t max_rv = (ops_ld->rv_index == 1) ? 3 : ops_ld->rv_index;
1862 k0 = get_k0(ops_ld->n_cb, ops_ld->z_c, ops_ld->basegraph, max_rv);
1863 /* Compute RM out size and number of rows */
1864 uint16_t parity_offset = (ops_ld->basegraph == 1 ? 20 : 8)
1865 * ops_ld->z_c - ops_ld->n_filler;
1866 uint16_t deRmOutSize = RTE_MIN(
1867 k0 + ops_ld->cb_params.e +
1868 ((k0 > parity_offset) ?
1869 0 : ops_ld->n_filler),
1870 ops_ld->n_cb);
1871 uint16_t numRows = ((deRmOutSize + ops_ld->z_c - 1)
1872 / ops_ld->z_c);
1873 uint16_t harq_output_len = numRows * ops_ld->z_c;
1874 return harq_output_len;
1875 }
1876
1877 static inline int
validate_op_harq_chain(struct rte_bbdev_op_data * op,struct op_data_entries * orig_op,struct rte_bbdev_op_ldpc_dec * ops_ld)1878 validate_op_harq_chain(struct rte_bbdev_op_data *op,
1879 struct op_data_entries *orig_op,
1880 struct rte_bbdev_op_ldpc_dec *ops_ld)
1881 {
1882 uint8_t i;
1883 uint32_t j, jj, k;
1884 struct rte_mbuf *m = op->data;
1885 uint8_t nb_dst_segments = orig_op->nb_segments;
1886 uint32_t total_data_size = 0;
1887 int8_t *harq_orig, *harq_out, abs_harq_origin;
1888 uint32_t byte_error = 0, cum_error = 0, error;
1889 int16_t llr_max = (1 << (ldpc_llr_size - ldpc_llr_decimals)) - 1;
1890 int16_t llr_max_pre_scaling = (1 << (ldpc_llr_size - 1)) - 1;
1891 uint16_t parity_offset;
1892
1893 TEST_ASSERT(nb_dst_segments == m->nb_segs,
1894 "Number of segments differ in original (%u) and filled (%u) op",
1895 nb_dst_segments, m->nb_segs);
1896
1897 /* Validate each mbuf segment length */
1898 for (i = 0; i < nb_dst_segments; ++i) {
1899 /* Apply offset to the first mbuf segment */
1900 uint16_t offset = (i == 0) ? op->offset : 0;
1901 uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
1902 total_data_size += orig_op->segments[i].length;
1903
1904 TEST_ASSERT(orig_op->segments[i].length <
1905 (uint32_t)(data_len + 64),
1906 "Length of segment differ in original (%u) and filled (%u) op",
1907 orig_op->segments[i].length, data_len);
1908 harq_orig = (int8_t *) orig_op->segments[i].addr;
1909 harq_out = rte_pktmbuf_mtod_offset(m, int8_t *, offset);
1910
1911 if (!(ldpc_cap_flags &
1912 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS
1913 ) || (ops_ld->op_flags &
1914 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
1915 data_len -= ops_ld->z_c;
1916 parity_offset = data_len;
1917 } else {
1918 /* Compute RM out size and number of rows */
1919 parity_offset = (ops_ld->basegraph == 1 ? 20 : 8)
1920 * ops_ld->z_c - ops_ld->n_filler;
1921 uint16_t deRmOutSize = compute_harq_len(ops_ld) -
1922 ops_ld->n_filler;
1923 if (data_len > deRmOutSize)
1924 data_len = deRmOutSize;
1925 if (data_len > orig_op->segments[i].length)
1926 data_len = orig_op->segments[i].length;
1927 }
1928 /*
1929 * HARQ output can have minor differences
1930 * due to integer representation and related scaling
1931 */
1932 for (j = 0, jj = 0; j < data_len; j++, jj++) {
1933 if (j == parity_offset) {
1934 /* Special Handling of the filler bits */
1935 for (k = 0; k < ops_ld->n_filler; k++) {
1936 if (harq_out[jj] !=
1937 llr_max_pre_scaling) {
1938 printf("HARQ Filler issue %d: %d %d\n",
1939 jj, harq_out[jj],
1940 llr_max);
1941 byte_error++;
1942 }
1943 jj++;
1944 }
1945 }
1946 if (!(ops_ld->op_flags &
1947 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
1948 if (ldpc_llr_decimals > 1)
1949 harq_out[jj] = (harq_out[jj] + 1)
1950 >> (ldpc_llr_decimals - 1);
1951 /* Saturated to S7 */
1952 if (harq_orig[j] > llr_max)
1953 harq_orig[j] = llr_max;
1954 if (harq_orig[j] < -llr_max)
1955 harq_orig[j] = -llr_max;
1956 }
1957 if (harq_orig[j] != harq_out[jj]) {
1958 error = (harq_orig[j] > harq_out[jj]) ?
1959 harq_orig[j] - harq_out[jj] :
1960 harq_out[jj] - harq_orig[j];
1961 abs_harq_origin = harq_orig[j] > 0 ?
1962 harq_orig[j] :
1963 -harq_orig[j];
1964 /* Residual quantization error */
1965 if ((error > 8 && (abs_harq_origin <
1966 (llr_max - 16))) ||
1967 (error > 16)) {
1968 printf("HARQ mismatch %d: exp %d act %d => %d\n",
1969 j, harq_orig[j],
1970 harq_out[jj], error);
1971 byte_error++;
1972 cum_error += error;
1973 }
1974 }
1975 }
1976 m = m->next;
1977 }
1978
1979 if (byte_error)
1980 TEST_ASSERT(byte_error <= 1,
1981 "HARQ output mismatch (%d) %d",
1982 byte_error, cum_error);
1983
1984 /* Validate total mbuf pkt length */
1985 uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
1986 TEST_ASSERT(total_data_size < pkt_len + 64,
1987 "Length of data differ in original (%u) and filled (%u) op",
1988 total_data_size, pkt_len);
1989
1990 return TEST_SUCCESS;
1991 }
1992
1993 static int
validate_dec_op(struct rte_bbdev_dec_op ** ops,const uint16_t n,struct rte_bbdev_dec_op * ref_op,const int vector_mask)1994 validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
1995 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
1996 {
1997 unsigned int i;
1998 int ret;
1999 struct op_data_entries *hard_data_orig =
2000 &test_vector.entries[DATA_HARD_OUTPUT];
2001 struct op_data_entries *soft_data_orig =
2002 &test_vector.entries[DATA_SOFT_OUTPUT];
2003 struct rte_bbdev_op_turbo_dec *ops_td;
2004 struct rte_bbdev_op_data *hard_output;
2005 struct rte_bbdev_op_data *soft_output;
2006 struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
2007
2008 for (i = 0; i < n; ++i) {
2009 ops_td = &ops[i]->turbo_dec;
2010 hard_output = &ops_td->hard_output;
2011 soft_output = &ops_td->soft_output;
2012
2013 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
2014 TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
2015 "Returned iter_count (%d) > expected iter_count (%d)",
2016 ops_td->iter_count, ref_td->iter_count);
2017 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
2018 TEST_ASSERT_SUCCESS(ret,
2019 "Checking status and ordering for decoder failed");
2020
2021 TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
2022 hard_data_orig),
2023 "Hard output buffers (CB=%u) are not equal",
2024 i);
2025
2026 if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
2027 TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
2028 soft_data_orig),
2029 "Soft output buffers (CB=%u) are not equal",
2030 i);
2031 }
2032
2033 return TEST_SUCCESS;
2034 }
2035
2036 /* Check Number of code blocks errors */
2037 static int
validate_ldpc_bler(struct rte_bbdev_dec_op ** ops,const uint16_t n)2038 validate_ldpc_bler(struct rte_bbdev_dec_op **ops, const uint16_t n)
2039 {
2040 unsigned int i;
2041 struct op_data_entries *hard_data_orig =
2042 &test_vector.entries[DATA_HARD_OUTPUT];
2043 struct rte_bbdev_op_ldpc_dec *ops_td;
2044 struct rte_bbdev_op_data *hard_output;
2045 int errors = 0;
2046 struct rte_mbuf *m;
2047
2048 for (i = 0; i < n; ++i) {
2049 ops_td = &ops[i]->ldpc_dec;
2050 hard_output = &ops_td->hard_output;
2051 m = hard_output->data;
2052 if (memcmp(rte_pktmbuf_mtod_offset(m, uint32_t *, 0),
2053 hard_data_orig->segments[0].addr,
2054 hard_data_orig->segments[0].length))
2055 errors++;
2056 }
2057 return errors;
2058 }
2059
2060 static int
validate_ldpc_dec_op(struct rte_bbdev_dec_op ** ops,const uint16_t n,struct rte_bbdev_dec_op * ref_op,const int vector_mask)2061 validate_ldpc_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
2062 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
2063 {
2064 unsigned int i;
2065 int ret;
2066 struct op_data_entries *hard_data_orig =
2067 &test_vector.entries[DATA_HARD_OUTPUT];
2068 struct op_data_entries *soft_data_orig =
2069 &test_vector.entries[DATA_SOFT_OUTPUT];
2070 struct op_data_entries *harq_data_orig =
2071 &test_vector.entries[DATA_HARQ_OUTPUT];
2072 struct rte_bbdev_op_ldpc_dec *ops_td;
2073 struct rte_bbdev_op_data *hard_output;
2074 struct rte_bbdev_op_data *harq_output;
2075 struct rte_bbdev_op_data *soft_output;
2076 struct rte_bbdev_op_ldpc_dec *ref_td = &ref_op->ldpc_dec;
2077
2078 for (i = 0; i < n; ++i) {
2079 ops_td = &ops[i]->ldpc_dec;
2080 hard_output = &ops_td->hard_output;
2081 harq_output = &ops_td->harq_combined_output;
2082 soft_output = &ops_td->soft_output;
2083
2084 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
2085 TEST_ASSERT_SUCCESS(ret,
2086 "Checking status and ordering for decoder failed");
2087 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
2088 TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
2089 "Returned iter_count (%d) > expected iter_count (%d)",
2090 ops_td->iter_count, ref_td->iter_count);
2091 /*
2092 * We can ignore output data when the decoding failed to
2093 * converge or for loop-back cases
2094 */
2095 if (!check_bit(ops[i]->ldpc_dec.op_flags,
2096 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK
2097 ) && (
2098 ops[i]->status & (1 << RTE_BBDEV_SYNDROME_ERROR
2099 )) == 0)
2100 TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
2101 hard_data_orig),
2102 "Hard output buffers (CB=%u) are not equal",
2103 i);
2104
2105 if (ref_op->ldpc_dec.op_flags & RTE_BBDEV_LDPC_SOFT_OUT_ENABLE)
2106 TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
2107 soft_data_orig),
2108 "Soft output buffers (CB=%u) are not equal",
2109 i);
2110 if (ref_op->ldpc_dec.op_flags &
2111 RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE) {
2112 TEST_ASSERT_SUCCESS(validate_op_harq_chain(harq_output,
2113 harq_data_orig, ops_td),
2114 "HARQ output buffers (CB=%u) are not equal",
2115 i);
2116 }
2117 if (ref_op->ldpc_dec.op_flags &
2118 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
2119 TEST_ASSERT_SUCCESS(validate_op_harq_chain(harq_output,
2120 harq_data_orig, ops_td),
2121 "HARQ output buffers (CB=%u) are not equal",
2122 i);
2123
2124 }
2125
2126 return TEST_SUCCESS;
2127 }
2128
2129
2130 static int
validate_enc_op(struct rte_bbdev_enc_op ** ops,const uint16_t n,struct rte_bbdev_enc_op * ref_op)2131 validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
2132 struct rte_bbdev_enc_op *ref_op)
2133 {
2134 unsigned int i;
2135 int ret;
2136 struct op_data_entries *hard_data_orig =
2137 &test_vector.entries[DATA_HARD_OUTPUT];
2138
2139 for (i = 0; i < n; ++i) {
2140 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
2141 TEST_ASSERT_SUCCESS(ret,
2142 "Checking status and ordering for encoder failed");
2143 TEST_ASSERT_SUCCESS(validate_op_chain(
2144 &ops[i]->turbo_enc.output,
2145 hard_data_orig),
2146 "Output buffers (CB=%u) are not equal",
2147 i);
2148 }
2149
2150 return TEST_SUCCESS;
2151 }
2152
2153 static int
validate_ldpc_enc_op(struct rte_bbdev_enc_op ** ops,const uint16_t n,struct rte_bbdev_enc_op * ref_op)2154 validate_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
2155 struct rte_bbdev_enc_op *ref_op)
2156 {
2157 unsigned int i;
2158 int ret;
2159 struct op_data_entries *hard_data_orig =
2160 &test_vector.entries[DATA_HARD_OUTPUT];
2161
2162 for (i = 0; i < n; ++i) {
2163 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
2164 TEST_ASSERT_SUCCESS(ret,
2165 "Checking status and ordering for encoder failed");
2166 TEST_ASSERT_SUCCESS(validate_op_chain(
2167 &ops[i]->ldpc_enc.output,
2168 hard_data_orig),
2169 "Output buffers (CB=%u) are not equal",
2170 i);
2171 }
2172
2173 return TEST_SUCCESS;
2174 }
2175
2176 static void
create_reference_dec_op(struct rte_bbdev_dec_op * op)2177 create_reference_dec_op(struct rte_bbdev_dec_op *op)
2178 {
2179 unsigned int i;
2180 struct op_data_entries *entry;
2181
2182 op->turbo_dec = test_vector.turbo_dec;
2183 entry = &test_vector.entries[DATA_INPUT];
2184 for (i = 0; i < entry->nb_segments; ++i)
2185 op->turbo_dec.input.length +=
2186 entry->segments[i].length;
2187 }
2188
2189 static void
create_reference_ldpc_dec_op(struct rte_bbdev_dec_op * op)2190 create_reference_ldpc_dec_op(struct rte_bbdev_dec_op *op)
2191 {
2192 unsigned int i;
2193 struct op_data_entries *entry;
2194
2195 op->ldpc_dec = test_vector.ldpc_dec;
2196 entry = &test_vector.entries[DATA_INPUT];
2197 for (i = 0; i < entry->nb_segments; ++i)
2198 op->ldpc_dec.input.length +=
2199 entry->segments[i].length;
2200 if (test_vector.ldpc_dec.op_flags &
2201 RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) {
2202 entry = &test_vector.entries[DATA_HARQ_INPUT];
2203 for (i = 0; i < entry->nb_segments; ++i)
2204 op->ldpc_dec.harq_combined_input.length +=
2205 entry->segments[i].length;
2206 }
2207 }
2208
2209
2210 static void
create_reference_enc_op(struct rte_bbdev_enc_op * op)2211 create_reference_enc_op(struct rte_bbdev_enc_op *op)
2212 {
2213 unsigned int i;
2214 struct op_data_entries *entry;
2215
2216 op->turbo_enc = test_vector.turbo_enc;
2217 entry = &test_vector.entries[DATA_INPUT];
2218 for (i = 0; i < entry->nb_segments; ++i)
2219 op->turbo_enc.input.length +=
2220 entry->segments[i].length;
2221 }
2222
2223 static void
create_reference_ldpc_enc_op(struct rte_bbdev_enc_op * op)2224 create_reference_ldpc_enc_op(struct rte_bbdev_enc_op *op)
2225 {
2226 unsigned int i;
2227 struct op_data_entries *entry;
2228
2229 op->ldpc_enc = test_vector.ldpc_enc;
2230 entry = &test_vector.entries[DATA_INPUT];
2231 for (i = 0; i < entry->nb_segments; ++i)
2232 op->ldpc_enc.input.length +=
2233 entry->segments[i].length;
2234 }
2235
2236 static uint32_t
calc_dec_TB_size(struct rte_bbdev_dec_op * op)2237 calc_dec_TB_size(struct rte_bbdev_dec_op *op)
2238 {
2239 uint8_t i;
2240 uint32_t c, r, tb_size = 0;
2241
2242 if (op->turbo_dec.code_block_mode) {
2243 tb_size = op->turbo_dec.tb_params.k_neg;
2244 } else {
2245 c = op->turbo_dec.tb_params.c;
2246 r = op->turbo_dec.tb_params.r;
2247 for (i = 0; i < c-r; i++)
2248 tb_size += (r < op->turbo_dec.tb_params.c_neg) ?
2249 op->turbo_dec.tb_params.k_neg :
2250 op->turbo_dec.tb_params.k_pos;
2251 }
2252 return tb_size;
2253 }
2254
2255 static uint32_t
calc_ldpc_dec_TB_size(struct rte_bbdev_dec_op * op)2256 calc_ldpc_dec_TB_size(struct rte_bbdev_dec_op *op)
2257 {
2258 uint8_t i;
2259 uint32_t c, r, tb_size = 0;
2260 uint16_t sys_cols = (op->ldpc_dec.basegraph == 1) ? 22 : 10;
2261
2262 if (op->ldpc_dec.code_block_mode) {
2263 tb_size = sys_cols * op->ldpc_dec.z_c - op->ldpc_dec.n_filler;
2264 } else {
2265 c = op->ldpc_dec.tb_params.c;
2266 r = op->ldpc_dec.tb_params.r;
2267 for (i = 0; i < c-r; i++)
2268 tb_size += sys_cols * op->ldpc_dec.z_c
2269 - op->ldpc_dec.n_filler;
2270 }
2271 return tb_size;
2272 }
2273
2274 static uint32_t
calc_enc_TB_size(struct rte_bbdev_enc_op * op)2275 calc_enc_TB_size(struct rte_bbdev_enc_op *op)
2276 {
2277 uint8_t i;
2278 uint32_t c, r, tb_size = 0;
2279
2280 if (op->turbo_enc.code_block_mode) {
2281 tb_size = op->turbo_enc.tb_params.k_neg;
2282 } else {
2283 c = op->turbo_enc.tb_params.c;
2284 r = op->turbo_enc.tb_params.r;
2285 for (i = 0; i < c-r; i++)
2286 tb_size += (r < op->turbo_enc.tb_params.c_neg) ?
2287 op->turbo_enc.tb_params.k_neg :
2288 op->turbo_enc.tb_params.k_pos;
2289 }
2290 return tb_size;
2291 }
2292
2293 static uint32_t
calc_ldpc_enc_TB_size(struct rte_bbdev_enc_op * op)2294 calc_ldpc_enc_TB_size(struct rte_bbdev_enc_op *op)
2295 {
2296 uint8_t i;
2297 uint32_t c, r, tb_size = 0;
2298 uint16_t sys_cols = (op->ldpc_enc.basegraph == 1) ? 22 : 10;
2299
2300 if (op->turbo_enc.code_block_mode) {
2301 tb_size = sys_cols * op->ldpc_enc.z_c - op->ldpc_enc.n_filler;
2302 } else {
2303 c = op->turbo_enc.tb_params.c;
2304 r = op->turbo_enc.tb_params.r;
2305 for (i = 0; i < c-r; i++)
2306 tb_size += sys_cols * op->ldpc_enc.z_c
2307 - op->ldpc_enc.n_filler;
2308 }
2309 return tb_size;
2310 }
2311
2312
2313 static int
init_test_op_params(struct test_op_params * op_params,enum rte_bbdev_op_type op_type,const int expected_status,const int vector_mask,struct rte_mempool * ops_mp,uint16_t burst_sz,uint16_t num_to_process,uint16_t num_lcores)2314 init_test_op_params(struct test_op_params *op_params,
2315 enum rte_bbdev_op_type op_type, const int expected_status,
2316 const int vector_mask, struct rte_mempool *ops_mp,
2317 uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
2318 {
2319 int ret = 0;
2320 if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
2321 op_type == RTE_BBDEV_OP_LDPC_DEC)
2322 ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
2323 &op_params->ref_dec_op, 1);
2324 else
2325 ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
2326 &op_params->ref_enc_op, 1);
2327
2328 TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
2329
2330 op_params->mp = ops_mp;
2331 op_params->burst_sz = burst_sz;
2332 op_params->num_to_process = num_to_process;
2333 op_params->num_lcores = num_lcores;
2334 op_params->vector_mask = vector_mask;
2335 if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
2336 op_type == RTE_BBDEV_OP_LDPC_DEC)
2337 op_params->ref_dec_op->status = expected_status;
2338 else if (op_type == RTE_BBDEV_OP_TURBO_ENC
2339 || op_type == RTE_BBDEV_OP_LDPC_ENC)
2340 op_params->ref_enc_op->status = expected_status;
2341 return 0;
2342 }
2343
2344 static int
run_test_case_on_device(test_case_function * test_case_func,uint8_t dev_id,struct test_op_params * op_params)2345 run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
2346 struct test_op_params *op_params)
2347 {
2348 int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
2349 unsigned int i;
2350 struct active_device *ad;
2351 unsigned int burst_sz = get_burst_sz();
2352 enum rte_bbdev_op_type op_type = test_vector.op_type;
2353 const struct rte_bbdev_op_cap *capabilities = NULL;
2354
2355 ad = &active_devs[dev_id];
2356
2357 /* Check if device supports op_type */
2358 if (!is_avail_op(ad, test_vector.op_type))
2359 return TEST_SUCCESS;
2360
2361 struct rte_bbdev_info info;
2362 rte_bbdev_info_get(ad->dev_id, &info);
2363 socket_id = GET_SOCKET(info.socket_id);
2364
2365 f_ret = create_mempools(ad, socket_id, op_type,
2366 get_num_ops());
2367 if (f_ret != TEST_SUCCESS) {
2368 printf("Couldn't create mempools");
2369 goto fail;
2370 }
2371 if (op_type == RTE_BBDEV_OP_NONE)
2372 op_type = RTE_BBDEV_OP_TURBO_ENC;
2373
2374 f_ret = init_test_op_params(op_params, test_vector.op_type,
2375 test_vector.expected_status,
2376 test_vector.mask,
2377 ad->ops_mempool,
2378 burst_sz,
2379 get_num_ops(),
2380 get_num_lcores());
2381 if (f_ret != TEST_SUCCESS) {
2382 printf("Couldn't init test op params");
2383 goto fail;
2384 }
2385
2386
2387 /* Find capabilities */
2388 const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
2389 for (i = 0; i < RTE_BBDEV_OP_TYPE_COUNT; i++) {
2390 if (cap->type == test_vector.op_type) {
2391 capabilities = cap;
2392 break;
2393 }
2394 cap++;
2395 }
2396 TEST_ASSERT_NOT_NULL(capabilities,
2397 "Couldn't find capabilities");
2398
2399 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
2400 create_reference_dec_op(op_params->ref_dec_op);
2401 } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
2402 create_reference_enc_op(op_params->ref_enc_op);
2403 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2404 create_reference_ldpc_enc_op(op_params->ref_enc_op);
2405 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2406 create_reference_ldpc_dec_op(op_params->ref_dec_op);
2407
2408 for (i = 0; i < ad->nb_queues; ++i) {
2409 f_ret = fill_queue_buffers(op_params,
2410 ad->in_mbuf_pool,
2411 ad->hard_out_mbuf_pool,
2412 ad->soft_out_mbuf_pool,
2413 ad->harq_in_mbuf_pool,
2414 ad->harq_out_mbuf_pool,
2415 ad->queue_ids[i],
2416 capabilities,
2417 info.drv.min_alignment,
2418 socket_id);
2419 if (f_ret != TEST_SUCCESS) {
2420 printf("Couldn't init queue buffers");
2421 goto fail;
2422 }
2423 }
2424
2425 /* Run test case function */
2426 t_ret = test_case_func(ad, op_params);
2427
2428 /* Free active device resources and return */
2429 free_buffers(ad, op_params);
2430 return t_ret;
2431
2432 fail:
2433 free_buffers(ad, op_params);
2434 return TEST_FAILED;
2435 }
2436
2437 /* Run given test function per active device per supported op type
2438 * per burst size.
2439 */
2440 static int
run_test_case(test_case_function * test_case_func)2441 run_test_case(test_case_function *test_case_func)
2442 {
2443 int ret = 0;
2444 uint8_t dev;
2445
2446 /* Alloc op_params */
2447 struct test_op_params *op_params = rte_zmalloc(NULL,
2448 sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
2449 TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
2450 RTE_ALIGN(sizeof(struct test_op_params),
2451 RTE_CACHE_LINE_SIZE));
2452
2453 /* For each device run test case function */
2454 for (dev = 0; dev < nb_active_devs; ++dev)
2455 ret |= run_test_case_on_device(test_case_func, dev, op_params);
2456
2457 rte_free(op_params);
2458
2459 return ret;
2460 }
2461
2462
2463 /* Push back the HARQ output from DDR to host */
2464 static void
retrieve_harq_ddr(uint16_t dev_id,uint16_t queue_id,struct rte_bbdev_dec_op ** ops,const uint16_t n)2465 retrieve_harq_ddr(uint16_t dev_id, uint16_t queue_id,
2466 struct rte_bbdev_dec_op **ops,
2467 const uint16_t n)
2468 {
2469 uint16_t j;
2470 int save_status, ret;
2471 uint32_t harq_offset = (uint32_t) queue_id * HARQ_INCR * MAX_OPS;
2472 struct rte_bbdev_dec_op *ops_deq[MAX_BURST];
2473 uint32_t flags = ops[0]->ldpc_dec.op_flags;
2474 bool loopback = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
2475 bool mem_out = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
2476 bool hc_out = flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
2477 bool h_comp = flags & RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2478 for (j = 0; j < n; ++j) {
2479 if ((loopback && mem_out) || hc_out) {
2480 save_status = ops[j]->status;
2481 ops[j]->ldpc_dec.op_flags =
2482 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK +
2483 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
2484 if (h_comp)
2485 ops[j]->ldpc_dec.op_flags +=
2486 RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2487 ops[j]->ldpc_dec.harq_combined_input.offset =
2488 harq_offset;
2489 ops[j]->ldpc_dec.harq_combined_output.offset = 0;
2490 harq_offset += HARQ_INCR;
2491 if (!loopback)
2492 ops[j]->ldpc_dec.harq_combined_input.length =
2493 ops[j]->ldpc_dec.harq_combined_output.length;
2494 rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
2495 &ops[j], 1);
2496 ret = 0;
2497 while (ret == 0)
2498 ret = rte_bbdev_dequeue_ldpc_dec_ops(
2499 dev_id, queue_id,
2500 &ops_deq[j], 1);
2501 ops[j]->ldpc_dec.op_flags = flags;
2502 ops[j]->status = save_status;
2503 }
2504 }
2505 }
2506
2507 /*
2508 * Push back the HARQ output from HW DDR to Host
2509 * Preload HARQ memory input and adjust HARQ offset
2510 */
2511 static void
preload_harq_ddr(uint16_t dev_id,uint16_t queue_id,struct rte_bbdev_dec_op ** ops,const uint16_t n,bool preload)2512 preload_harq_ddr(uint16_t dev_id, uint16_t queue_id,
2513 struct rte_bbdev_dec_op **ops, const uint16_t n,
2514 bool preload)
2515 {
2516 uint16_t j;
2517 int deq;
2518 uint32_t harq_offset = (uint32_t) queue_id * HARQ_INCR * MAX_OPS;
2519 struct rte_bbdev_op_data save_hc_in[MAX_OPS], save_hc_out[MAX_OPS];
2520 struct rte_bbdev_dec_op *ops_deq[MAX_OPS];
2521 uint32_t flags = ops[0]->ldpc_dec.op_flags;
2522 bool mem_in = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
2523 bool hc_in = flags & RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
2524 bool mem_out = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
2525 bool hc_out = flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
2526 bool h_comp = flags & RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2527 if ((mem_in || hc_in) && preload) {
2528 for (j = 0; j < n; ++j) {
2529 save_hc_in[j] = ops[j]->ldpc_dec.harq_combined_input;
2530 save_hc_out[j] = ops[j]->ldpc_dec.harq_combined_output;
2531 ops[j]->ldpc_dec.op_flags =
2532 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK +
2533 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
2534 if (h_comp)
2535 ops[j]->ldpc_dec.op_flags +=
2536 RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2537 ops[j]->ldpc_dec.harq_combined_output.offset =
2538 harq_offset;
2539 ops[j]->ldpc_dec.harq_combined_input.offset = 0;
2540 harq_offset += HARQ_INCR;
2541 }
2542 rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id, &ops[0], n);
2543 deq = 0;
2544 while (deq != n)
2545 deq += rte_bbdev_dequeue_ldpc_dec_ops(
2546 dev_id, queue_id, &ops_deq[deq],
2547 n - deq);
2548 /* Restore the operations */
2549 for (j = 0; j < n; ++j) {
2550 ops[j]->ldpc_dec.op_flags = flags;
2551 ops[j]->ldpc_dec.harq_combined_input = save_hc_in[j];
2552 ops[j]->ldpc_dec.harq_combined_output = save_hc_out[j];
2553 }
2554 }
2555 harq_offset = (uint32_t) queue_id * HARQ_INCR * MAX_OPS;
2556 for (j = 0; j < n; ++j) {
2557 /* Adjust HARQ offset when we reach external DDR */
2558 if (mem_in || hc_in)
2559 ops[j]->ldpc_dec.harq_combined_input.offset
2560 = harq_offset;
2561 if (mem_out || hc_out)
2562 ops[j]->ldpc_dec.harq_combined_output.offset
2563 = harq_offset;
2564 harq_offset += HARQ_INCR;
2565 }
2566 }
2567
2568 static void
dequeue_event_callback(uint16_t dev_id,enum rte_bbdev_event_type event,void * cb_arg,void * ret_param)2569 dequeue_event_callback(uint16_t dev_id,
2570 enum rte_bbdev_event_type event, void *cb_arg,
2571 void *ret_param)
2572 {
2573 int ret;
2574 uint16_t i;
2575 uint64_t total_time;
2576 uint16_t deq, burst_sz, num_ops;
2577 uint16_t queue_id = *(uint16_t *) ret_param;
2578 struct rte_bbdev_info info;
2579 double tb_len_bits;
2580 struct thread_params *tp = cb_arg;
2581
2582 /* Find matching thread params using queue_id */
2583 for (i = 0; i < MAX_QUEUES; ++i, ++tp)
2584 if (tp->queue_id == queue_id)
2585 break;
2586
2587 if (i == MAX_QUEUES) {
2588 printf("%s: Queue_id from interrupt details was not found!\n",
2589 __func__);
2590 return;
2591 }
2592
2593 if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
2594 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
2595 printf(
2596 "Dequeue interrupt handler called for incorrect event!\n");
2597 return;
2598 }
2599
2600 burst_sz = rte_atomic16_read(&tp->burst_sz);
2601 num_ops = tp->op_params->num_to_process;
2602
2603 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
2604 deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
2605 &tp->dec_ops[
2606 rte_atomic16_read(&tp->nb_dequeued)],
2607 burst_sz);
2608 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2609 deq = rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
2610 &tp->dec_ops[
2611 rte_atomic16_read(&tp->nb_dequeued)],
2612 burst_sz);
2613 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2614 deq = rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
2615 &tp->enc_ops[
2616 rte_atomic16_read(&tp->nb_dequeued)],
2617 burst_sz);
2618 else /*RTE_BBDEV_OP_TURBO_ENC*/
2619 deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
2620 &tp->enc_ops[
2621 rte_atomic16_read(&tp->nb_dequeued)],
2622 burst_sz);
2623
2624 if (deq < burst_sz) {
2625 printf(
2626 "After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
2627 burst_sz, deq);
2628 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
2629 return;
2630 }
2631
2632 if (rte_atomic16_read(&tp->nb_dequeued) + deq < num_ops) {
2633 rte_atomic16_add(&tp->nb_dequeued, deq);
2634 return;
2635 }
2636
2637 total_time = rte_rdtsc_precise() - tp->start_time;
2638
2639 rte_bbdev_info_get(dev_id, &info);
2640
2641 ret = TEST_SUCCESS;
2642
2643 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
2644 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
2645 ret = validate_dec_op(tp->dec_ops, num_ops, ref_op,
2646 tp->op_params->vector_mask);
2647 /* get the max of iter_count for all dequeued ops */
2648 for (i = 0; i < num_ops; ++i)
2649 tp->iter_count = RTE_MAX(
2650 tp->dec_ops[i]->turbo_dec.iter_count,
2651 tp->iter_count);
2652 rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
2653 } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC) {
2654 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
2655 ret = validate_enc_op(tp->enc_ops, num_ops, ref_op);
2656 rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
2657 } else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC) {
2658 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
2659 ret = validate_ldpc_enc_op(tp->enc_ops, num_ops, ref_op);
2660 rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
2661 } else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
2662 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
2663 ret = validate_ldpc_dec_op(tp->dec_ops, num_ops, ref_op,
2664 tp->op_params->vector_mask);
2665 rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
2666 }
2667
2668 if (ret) {
2669 printf("Buffers validation failed\n");
2670 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
2671 }
2672
2673 switch (test_vector.op_type) {
2674 case RTE_BBDEV_OP_TURBO_DEC:
2675 tb_len_bits = calc_dec_TB_size(tp->op_params->ref_dec_op);
2676 break;
2677 case RTE_BBDEV_OP_TURBO_ENC:
2678 tb_len_bits = calc_enc_TB_size(tp->op_params->ref_enc_op);
2679 break;
2680 case RTE_BBDEV_OP_LDPC_DEC:
2681 tb_len_bits = calc_ldpc_dec_TB_size(tp->op_params->ref_dec_op);
2682 break;
2683 case RTE_BBDEV_OP_LDPC_ENC:
2684 tb_len_bits = calc_ldpc_enc_TB_size(tp->op_params->ref_enc_op);
2685 break;
2686 case RTE_BBDEV_OP_NONE:
2687 tb_len_bits = 0.0;
2688 break;
2689 default:
2690 printf("Unknown op type: %d\n", test_vector.op_type);
2691 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
2692 return;
2693 }
2694
2695 tp->ops_per_sec += ((double)num_ops) /
2696 ((double)total_time / (double)rte_get_tsc_hz());
2697 tp->mbps += (((double)(num_ops * tb_len_bits)) / 1000000.0) /
2698 ((double)total_time / (double)rte_get_tsc_hz());
2699
2700 rte_atomic16_add(&tp->nb_dequeued, deq);
2701 }
2702
2703 static int
throughput_intr_lcore_ldpc_dec(void * arg)2704 throughput_intr_lcore_ldpc_dec(void *arg)
2705 {
2706 struct thread_params *tp = arg;
2707 unsigned int enqueued;
2708 const uint16_t queue_id = tp->queue_id;
2709 const uint16_t burst_sz = tp->op_params->burst_sz;
2710 const uint16_t num_to_process = tp->op_params->num_to_process;
2711 struct rte_bbdev_dec_op *ops[num_to_process];
2712 struct test_buffers *bufs = NULL;
2713 struct rte_bbdev_info info;
2714 int ret, i, j;
2715 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
2716 uint16_t num_to_enq, enq;
2717
2718 bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
2719 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
2720 bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
2721 RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
2722
2723 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2724 "BURST_SIZE should be <= %u", MAX_BURST);
2725
2726 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
2727 "Failed to enable interrupts for dev: %u, queue_id: %u",
2728 tp->dev_id, queue_id);
2729
2730 rte_bbdev_info_get(tp->dev_id, &info);
2731
2732 TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
2733 "NUM_OPS cannot exceed %u for this device",
2734 info.drv.queue_size_lim);
2735
2736 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2737
2738 rte_atomic16_clear(&tp->processing_status);
2739 rte_atomic16_clear(&tp->nb_dequeued);
2740
2741 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2742 rte_pause();
2743
2744 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
2745 num_to_process);
2746 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
2747 num_to_process);
2748 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2749 copy_reference_ldpc_dec_op(ops, num_to_process, 0, bufs->inputs,
2750 bufs->hard_outputs, bufs->soft_outputs,
2751 bufs->harq_inputs, bufs->harq_outputs, ref_op);
2752
2753 /* Set counter to validate the ordering */
2754 for (j = 0; j < num_to_process; ++j)
2755 ops[j]->opaque_data = (void *)(uintptr_t)j;
2756
2757 for (j = 0; j < TEST_REPETITIONS; ++j) {
2758 for (i = 0; i < num_to_process; ++i) {
2759 if (!loopback)
2760 rte_pktmbuf_reset(
2761 ops[i]->ldpc_dec.hard_output.data);
2762 if (hc_out || loopback)
2763 mbuf_reset(
2764 ops[i]->ldpc_dec.harq_combined_output.data);
2765 }
2766
2767 tp->start_time = rte_rdtsc_precise();
2768 for (enqueued = 0; enqueued < num_to_process;) {
2769 num_to_enq = burst_sz;
2770
2771 if (unlikely(num_to_process - enqueued < num_to_enq))
2772 num_to_enq = num_to_process - enqueued;
2773
2774 enq = 0;
2775 do {
2776 enq += rte_bbdev_enqueue_ldpc_dec_ops(
2777 tp->dev_id,
2778 queue_id, &ops[enqueued],
2779 num_to_enq);
2780 } while (unlikely(num_to_enq != enq));
2781 enqueued += enq;
2782
2783 /* Write to thread burst_sz current number of enqueued
2784 * descriptors. It ensures that proper number of
2785 * descriptors will be dequeued in callback
2786 * function - needed for last batch in case where
2787 * the number of operations is not a multiple of
2788 * burst size.
2789 */
2790 rte_atomic16_set(&tp->burst_sz, num_to_enq);
2791
2792 /* Wait until processing of previous batch is
2793 * completed
2794 */
2795 while (rte_atomic16_read(&tp->nb_dequeued) !=
2796 (int16_t) enqueued)
2797 rte_pause();
2798 }
2799 if (j != TEST_REPETITIONS - 1)
2800 rte_atomic16_clear(&tp->nb_dequeued);
2801 }
2802
2803 return TEST_SUCCESS;
2804 }
2805
2806 static int
throughput_intr_lcore_dec(void * arg)2807 throughput_intr_lcore_dec(void *arg)
2808 {
2809 struct thread_params *tp = arg;
2810 unsigned int enqueued;
2811 const uint16_t queue_id = tp->queue_id;
2812 const uint16_t burst_sz = tp->op_params->burst_sz;
2813 const uint16_t num_to_process = tp->op_params->num_to_process;
2814 struct rte_bbdev_dec_op *ops[num_to_process];
2815 struct test_buffers *bufs = NULL;
2816 struct rte_bbdev_info info;
2817 int ret, i, j;
2818 uint16_t num_to_enq, enq;
2819
2820 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2821 "BURST_SIZE should be <= %u", MAX_BURST);
2822
2823 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
2824 "Failed to enable interrupts for dev: %u, queue_id: %u",
2825 tp->dev_id, queue_id);
2826
2827 rte_bbdev_info_get(tp->dev_id, &info);
2828
2829 TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
2830 "NUM_OPS cannot exceed %u for this device",
2831 info.drv.queue_size_lim);
2832
2833 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2834
2835 rte_atomic16_clear(&tp->processing_status);
2836 rte_atomic16_clear(&tp->nb_dequeued);
2837
2838 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2839 rte_pause();
2840
2841 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
2842 num_to_process);
2843 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
2844 num_to_process);
2845 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2846 copy_reference_dec_op(ops, num_to_process, 0, bufs->inputs,
2847 bufs->hard_outputs, bufs->soft_outputs,
2848 tp->op_params->ref_dec_op);
2849
2850 /* Set counter to validate the ordering */
2851 for (j = 0; j < num_to_process; ++j)
2852 ops[j]->opaque_data = (void *)(uintptr_t)j;
2853
2854 for (j = 0; j < TEST_REPETITIONS; ++j) {
2855 for (i = 0; i < num_to_process; ++i)
2856 rte_pktmbuf_reset(ops[i]->turbo_dec.hard_output.data);
2857
2858 tp->start_time = rte_rdtsc_precise();
2859 for (enqueued = 0; enqueued < num_to_process;) {
2860 num_to_enq = burst_sz;
2861
2862 if (unlikely(num_to_process - enqueued < num_to_enq))
2863 num_to_enq = num_to_process - enqueued;
2864
2865 enq = 0;
2866 do {
2867 enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
2868 queue_id, &ops[enqueued],
2869 num_to_enq);
2870 } while (unlikely(num_to_enq != enq));
2871 enqueued += enq;
2872
2873 /* Write to thread burst_sz current number of enqueued
2874 * descriptors. It ensures that proper number of
2875 * descriptors will be dequeued in callback
2876 * function - needed for last batch in case where
2877 * the number of operations is not a multiple of
2878 * burst size.
2879 */
2880 rte_atomic16_set(&tp->burst_sz, num_to_enq);
2881
2882 /* Wait until processing of previous batch is
2883 * completed
2884 */
2885 while (rte_atomic16_read(&tp->nb_dequeued) !=
2886 (int16_t) enqueued)
2887 rte_pause();
2888 }
2889 if (j != TEST_REPETITIONS - 1)
2890 rte_atomic16_clear(&tp->nb_dequeued);
2891 }
2892
2893 return TEST_SUCCESS;
2894 }
2895
2896 static int
throughput_intr_lcore_enc(void * arg)2897 throughput_intr_lcore_enc(void *arg)
2898 {
2899 struct thread_params *tp = arg;
2900 unsigned int enqueued;
2901 const uint16_t queue_id = tp->queue_id;
2902 const uint16_t burst_sz = tp->op_params->burst_sz;
2903 const uint16_t num_to_process = tp->op_params->num_to_process;
2904 struct rte_bbdev_enc_op *ops[num_to_process];
2905 struct test_buffers *bufs = NULL;
2906 struct rte_bbdev_info info;
2907 int ret, i, j;
2908 uint16_t num_to_enq, enq;
2909
2910 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2911 "BURST_SIZE should be <= %u", MAX_BURST);
2912
2913 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
2914 "Failed to enable interrupts for dev: %u, queue_id: %u",
2915 tp->dev_id, queue_id);
2916
2917 rte_bbdev_info_get(tp->dev_id, &info);
2918
2919 TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
2920 "NUM_OPS cannot exceed %u for this device",
2921 info.drv.queue_size_lim);
2922
2923 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2924
2925 rte_atomic16_clear(&tp->processing_status);
2926 rte_atomic16_clear(&tp->nb_dequeued);
2927
2928 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2929 rte_pause();
2930
2931 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
2932 num_to_process);
2933 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
2934 num_to_process);
2935 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2936 copy_reference_enc_op(ops, num_to_process, 0, bufs->inputs,
2937 bufs->hard_outputs, tp->op_params->ref_enc_op);
2938
2939 /* Set counter to validate the ordering */
2940 for (j = 0; j < num_to_process; ++j)
2941 ops[j]->opaque_data = (void *)(uintptr_t)j;
2942
2943 for (j = 0; j < TEST_REPETITIONS; ++j) {
2944 for (i = 0; i < num_to_process; ++i)
2945 rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
2946
2947 tp->start_time = rte_rdtsc_precise();
2948 for (enqueued = 0; enqueued < num_to_process;) {
2949 num_to_enq = burst_sz;
2950
2951 if (unlikely(num_to_process - enqueued < num_to_enq))
2952 num_to_enq = num_to_process - enqueued;
2953
2954 enq = 0;
2955 do {
2956 enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
2957 queue_id, &ops[enqueued],
2958 num_to_enq);
2959 } while (unlikely(enq != num_to_enq));
2960 enqueued += enq;
2961
2962 /* Write to thread burst_sz current number of enqueued
2963 * descriptors. It ensures that proper number of
2964 * descriptors will be dequeued in callback
2965 * function - needed for last batch in case where
2966 * the number of operations is not a multiple of
2967 * burst size.
2968 */
2969 rte_atomic16_set(&tp->burst_sz, num_to_enq);
2970
2971 /* Wait until processing of previous batch is
2972 * completed
2973 */
2974 while (rte_atomic16_read(&tp->nb_dequeued) !=
2975 (int16_t) enqueued)
2976 rte_pause();
2977 }
2978 if (j != TEST_REPETITIONS - 1)
2979 rte_atomic16_clear(&tp->nb_dequeued);
2980 }
2981
2982 return TEST_SUCCESS;
2983 }
2984
2985
2986 static int
throughput_intr_lcore_ldpc_enc(void * arg)2987 throughput_intr_lcore_ldpc_enc(void *arg)
2988 {
2989 struct thread_params *tp = arg;
2990 unsigned int enqueued;
2991 const uint16_t queue_id = tp->queue_id;
2992 const uint16_t burst_sz = tp->op_params->burst_sz;
2993 const uint16_t num_to_process = tp->op_params->num_to_process;
2994 struct rte_bbdev_enc_op *ops[num_to_process];
2995 struct test_buffers *bufs = NULL;
2996 struct rte_bbdev_info info;
2997 int ret, i, j;
2998 uint16_t num_to_enq, enq;
2999
3000 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3001 "BURST_SIZE should be <= %u", MAX_BURST);
3002
3003 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
3004 "Failed to enable interrupts for dev: %u, queue_id: %u",
3005 tp->dev_id, queue_id);
3006
3007 rte_bbdev_info_get(tp->dev_id, &info);
3008
3009 TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
3010 "NUM_OPS cannot exceed %u for this device",
3011 info.drv.queue_size_lim);
3012
3013 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3014
3015 rte_atomic16_clear(&tp->processing_status);
3016 rte_atomic16_clear(&tp->nb_dequeued);
3017
3018 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
3019 rte_pause();
3020
3021 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
3022 num_to_process);
3023 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3024 num_to_process);
3025 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3026 copy_reference_ldpc_enc_op(ops, num_to_process, 0,
3027 bufs->inputs, bufs->hard_outputs,
3028 tp->op_params->ref_enc_op);
3029
3030 /* Set counter to validate the ordering */
3031 for (j = 0; j < num_to_process; ++j)
3032 ops[j]->opaque_data = (void *)(uintptr_t)j;
3033
3034 for (j = 0; j < TEST_REPETITIONS; ++j) {
3035 for (i = 0; i < num_to_process; ++i)
3036 rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
3037
3038 tp->start_time = rte_rdtsc_precise();
3039 for (enqueued = 0; enqueued < num_to_process;) {
3040 num_to_enq = burst_sz;
3041
3042 if (unlikely(num_to_process - enqueued < num_to_enq))
3043 num_to_enq = num_to_process - enqueued;
3044
3045 enq = 0;
3046 do {
3047 enq += rte_bbdev_enqueue_ldpc_enc_ops(
3048 tp->dev_id,
3049 queue_id, &ops[enqueued],
3050 num_to_enq);
3051 } while (unlikely(enq != num_to_enq));
3052 enqueued += enq;
3053
3054 /* Write to thread burst_sz current number of enqueued
3055 * descriptors. It ensures that proper number of
3056 * descriptors will be dequeued in callback
3057 * function - needed for last batch in case where
3058 * the number of operations is not a multiple of
3059 * burst size.
3060 */
3061 rte_atomic16_set(&tp->burst_sz, num_to_enq);
3062
3063 /* Wait until processing of previous batch is
3064 * completed
3065 */
3066 while (rte_atomic16_read(&tp->nb_dequeued) !=
3067 (int16_t) enqueued)
3068 rte_pause();
3069 }
3070 if (j != TEST_REPETITIONS - 1)
3071 rte_atomic16_clear(&tp->nb_dequeued);
3072 }
3073
3074 return TEST_SUCCESS;
3075 }
3076
3077 static int
throughput_pmd_lcore_dec(void * arg)3078 throughput_pmd_lcore_dec(void *arg)
3079 {
3080 struct thread_params *tp = arg;
3081 uint16_t enq, deq;
3082 uint64_t total_time = 0, start_time;
3083 const uint16_t queue_id = tp->queue_id;
3084 const uint16_t burst_sz = tp->op_params->burst_sz;
3085 const uint16_t num_ops = tp->op_params->num_to_process;
3086 struct rte_bbdev_dec_op *ops_enq[num_ops];
3087 struct rte_bbdev_dec_op *ops_deq[num_ops];
3088 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3089 struct test_buffers *bufs = NULL;
3090 int i, j, ret;
3091 struct rte_bbdev_info info;
3092 uint16_t num_to_enq;
3093
3094 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3095 "BURST_SIZE should be <= %u", MAX_BURST);
3096
3097 rte_bbdev_info_get(tp->dev_id, &info);
3098
3099 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3100 "NUM_OPS cannot exceed %u for this device",
3101 info.drv.queue_size_lim);
3102
3103 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3104
3105 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
3106 rte_pause();
3107
3108 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
3109 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
3110
3111 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3112 copy_reference_dec_op(ops_enq, num_ops, 0, bufs->inputs,
3113 bufs->hard_outputs, bufs->soft_outputs, ref_op);
3114
3115 /* Set counter to validate the ordering */
3116 for (j = 0; j < num_ops; ++j)
3117 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3118
3119 for (i = 0; i < TEST_REPETITIONS; ++i) {
3120
3121 for (j = 0; j < num_ops; ++j)
3122 mbuf_reset(ops_enq[j]->turbo_dec.hard_output.data);
3123
3124 start_time = rte_rdtsc_precise();
3125
3126 for (enq = 0, deq = 0; enq < num_ops;) {
3127 num_to_enq = burst_sz;
3128
3129 if (unlikely(num_ops - enq < num_to_enq))
3130 num_to_enq = num_ops - enq;
3131
3132 enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
3133 queue_id, &ops_enq[enq], num_to_enq);
3134
3135 deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
3136 queue_id, &ops_deq[deq], enq - deq);
3137 }
3138
3139 /* dequeue the remaining */
3140 while (deq < enq) {
3141 deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
3142 queue_id, &ops_deq[deq], enq - deq);
3143 }
3144
3145 total_time += rte_rdtsc_precise() - start_time;
3146 }
3147
3148 tp->iter_count = 0;
3149 /* get the max of iter_count for all dequeued ops */
3150 for (i = 0; i < num_ops; ++i) {
3151 tp->iter_count = RTE_MAX(ops_enq[i]->turbo_dec.iter_count,
3152 tp->iter_count);
3153 }
3154
3155 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3156 ret = validate_dec_op(ops_deq, num_ops, ref_op,
3157 tp->op_params->vector_mask);
3158 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3159 }
3160
3161 rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
3162
3163 double tb_len_bits = calc_dec_TB_size(ref_op);
3164
3165 tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3166 ((double)total_time / (double)rte_get_tsc_hz());
3167 tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
3168 1000000.0) / ((double)total_time /
3169 (double)rte_get_tsc_hz());
3170
3171 return TEST_SUCCESS;
3172 }
3173
3174 static int
bler_pmd_lcore_ldpc_dec(void * arg)3175 bler_pmd_lcore_ldpc_dec(void *arg)
3176 {
3177 struct thread_params *tp = arg;
3178 uint16_t enq, deq;
3179 uint64_t total_time = 0, start_time;
3180 const uint16_t queue_id = tp->queue_id;
3181 const uint16_t burst_sz = tp->op_params->burst_sz;
3182 const uint16_t num_ops = tp->op_params->num_to_process;
3183 struct rte_bbdev_dec_op *ops_enq[num_ops];
3184 struct rte_bbdev_dec_op *ops_deq[num_ops];
3185 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3186 struct test_buffers *bufs = NULL;
3187 int i, j, ret;
3188 float parity_bler = 0;
3189 struct rte_bbdev_info info;
3190 uint16_t num_to_enq;
3191 bool extDdr = check_bit(ldpc_cap_flags,
3192 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE);
3193 bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
3194 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
3195 bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
3196 RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
3197
3198 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3199 "BURST_SIZE should be <= %u", MAX_BURST);
3200
3201 rte_bbdev_info_get(tp->dev_id, &info);
3202
3203 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3204 "NUM_OPS cannot exceed %u for this device",
3205 info.drv.queue_size_lim);
3206
3207 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3208
3209 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
3210 rte_pause();
3211
3212 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
3213 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
3214
3215 /* For BLER tests we need to enable early termination */
3216 if (!check_bit(ref_op->ldpc_dec.op_flags,
3217 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
3218 ref_op->ldpc_dec.op_flags +=
3219 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
3220 ref_op->ldpc_dec.iter_max = get_iter_max();
3221 ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
3222
3223 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3224 copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
3225 bufs->hard_outputs, bufs->soft_outputs,
3226 bufs->harq_inputs, bufs->harq_outputs, ref_op);
3227 generate_llr_input(num_ops, bufs->inputs, ref_op);
3228
3229 /* Set counter to validate the ordering */
3230 for (j = 0; j < num_ops; ++j)
3231 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3232
3233 for (i = 0; i < 1; ++i) { /* Could add more iterations */
3234 for (j = 0; j < num_ops; ++j) {
3235 if (!loopback)
3236 mbuf_reset(
3237 ops_enq[j]->ldpc_dec.hard_output.data);
3238 if (hc_out || loopback)
3239 mbuf_reset(
3240 ops_enq[j]->ldpc_dec.harq_combined_output.data);
3241 }
3242 if (extDdr)
3243 preload_harq_ddr(tp->dev_id, queue_id, ops_enq,
3244 num_ops, true);
3245 start_time = rte_rdtsc_precise();
3246
3247 for (enq = 0, deq = 0; enq < num_ops;) {
3248 num_to_enq = burst_sz;
3249
3250 if (unlikely(num_ops - enq < num_to_enq))
3251 num_to_enq = num_ops - enq;
3252
3253 enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
3254 queue_id, &ops_enq[enq], num_to_enq);
3255
3256 deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3257 queue_id, &ops_deq[deq], enq - deq);
3258 }
3259
3260 /* dequeue the remaining */
3261 while (deq < enq) {
3262 deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3263 queue_id, &ops_deq[deq], enq - deq);
3264 }
3265
3266 total_time += rte_rdtsc_precise() - start_time;
3267 }
3268
3269 tp->iter_count = 0;
3270 tp->iter_average = 0;
3271 /* get the max of iter_count for all dequeued ops */
3272 for (i = 0; i < num_ops; ++i) {
3273 tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
3274 tp->iter_count);
3275 tp->iter_average += (double) ops_enq[i]->ldpc_dec.iter_count;
3276 if (ops_enq[i]->status & (1 << RTE_BBDEV_SYNDROME_ERROR))
3277 parity_bler += 1.0;
3278 }
3279
3280 parity_bler /= num_ops; /* This one is based on SYND */
3281 tp->iter_average /= num_ops;
3282 tp->bler = (double) validate_ldpc_bler(ops_deq, num_ops) / num_ops;
3283
3284 if (test_vector.op_type != RTE_BBDEV_OP_NONE
3285 && tp->bler == 0
3286 && parity_bler == 0
3287 && !hc_out) {
3288 ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
3289 tp->op_params->vector_mask);
3290 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3291 }
3292
3293 rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
3294
3295 double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
3296 tp->ops_per_sec = ((double)num_ops * 1) /
3297 ((double)total_time / (double)rte_get_tsc_hz());
3298 tp->mbps = (((double)(num_ops * 1 * tb_len_bits)) /
3299 1000000.0) / ((double)total_time /
3300 (double)rte_get_tsc_hz());
3301
3302 return TEST_SUCCESS;
3303 }
3304
3305 static int
throughput_pmd_lcore_ldpc_dec(void * arg)3306 throughput_pmd_lcore_ldpc_dec(void *arg)
3307 {
3308 struct thread_params *tp = arg;
3309 uint16_t enq, deq;
3310 uint64_t total_time = 0, start_time;
3311 const uint16_t queue_id = tp->queue_id;
3312 const uint16_t burst_sz = tp->op_params->burst_sz;
3313 const uint16_t num_ops = tp->op_params->num_to_process;
3314 struct rte_bbdev_dec_op *ops_enq[num_ops];
3315 struct rte_bbdev_dec_op *ops_deq[num_ops];
3316 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3317 struct test_buffers *bufs = NULL;
3318 int i, j, ret;
3319 struct rte_bbdev_info info;
3320 uint16_t num_to_enq;
3321 bool extDdr = check_bit(ldpc_cap_flags,
3322 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE);
3323 bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
3324 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
3325 bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
3326 RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
3327
3328 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3329 "BURST_SIZE should be <= %u", MAX_BURST);
3330
3331 rte_bbdev_info_get(tp->dev_id, &info);
3332
3333 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3334 "NUM_OPS cannot exceed %u for this device",
3335 info.drv.queue_size_lim);
3336
3337 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3338
3339 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
3340 rte_pause();
3341
3342 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
3343 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
3344
3345 /* For throughput tests we need to disable early termination */
3346 if (check_bit(ref_op->ldpc_dec.op_flags,
3347 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
3348 ref_op->ldpc_dec.op_flags -=
3349 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
3350 ref_op->ldpc_dec.iter_max = get_iter_max();
3351 ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
3352
3353 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3354 copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
3355 bufs->hard_outputs, bufs->soft_outputs,
3356 bufs->harq_inputs, bufs->harq_outputs, ref_op);
3357
3358 /* Set counter to validate the ordering */
3359 for (j = 0; j < num_ops; ++j)
3360 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3361
3362 for (i = 0; i < TEST_REPETITIONS; ++i) {
3363 for (j = 0; j < num_ops; ++j) {
3364 if (!loopback)
3365 mbuf_reset(
3366 ops_enq[j]->ldpc_dec.hard_output.data);
3367 if (hc_out || loopback)
3368 mbuf_reset(
3369 ops_enq[j]->ldpc_dec.harq_combined_output.data);
3370 }
3371 if (extDdr)
3372 preload_harq_ddr(tp->dev_id, queue_id, ops_enq,
3373 num_ops, true);
3374 start_time = rte_rdtsc_precise();
3375
3376 for (enq = 0, deq = 0; enq < num_ops;) {
3377 num_to_enq = burst_sz;
3378
3379 if (unlikely(num_ops - enq < num_to_enq))
3380 num_to_enq = num_ops - enq;
3381
3382 enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
3383 queue_id, &ops_enq[enq], num_to_enq);
3384
3385 deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3386 queue_id, &ops_deq[deq], enq - deq);
3387 }
3388
3389 /* dequeue the remaining */
3390 while (deq < enq) {
3391 deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3392 queue_id, &ops_deq[deq], enq - deq);
3393 }
3394
3395 total_time += rte_rdtsc_precise() - start_time;
3396 }
3397
3398 tp->iter_count = 0;
3399 /* get the max of iter_count for all dequeued ops */
3400 for (i = 0; i < num_ops; ++i) {
3401 tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
3402 tp->iter_count);
3403 }
3404 if (extDdr) {
3405 /* Read loopback is not thread safe */
3406 retrieve_harq_ddr(tp->dev_id, queue_id, ops_enq, num_ops);
3407 }
3408
3409 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3410 ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
3411 tp->op_params->vector_mask);
3412 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3413 }
3414
3415 rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
3416
3417 double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
3418
3419 tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3420 ((double)total_time / (double)rte_get_tsc_hz());
3421 tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
3422 1000000.0) / ((double)total_time /
3423 (double)rte_get_tsc_hz());
3424
3425 return TEST_SUCCESS;
3426 }
3427
3428 static int
throughput_pmd_lcore_enc(void * arg)3429 throughput_pmd_lcore_enc(void *arg)
3430 {
3431 struct thread_params *tp = arg;
3432 uint16_t enq, deq;
3433 uint64_t total_time = 0, start_time;
3434 const uint16_t queue_id = tp->queue_id;
3435 const uint16_t burst_sz = tp->op_params->burst_sz;
3436 const uint16_t num_ops = tp->op_params->num_to_process;
3437 struct rte_bbdev_enc_op *ops_enq[num_ops];
3438 struct rte_bbdev_enc_op *ops_deq[num_ops];
3439 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
3440 struct test_buffers *bufs = NULL;
3441 int i, j, ret;
3442 struct rte_bbdev_info info;
3443 uint16_t num_to_enq;
3444
3445 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3446 "BURST_SIZE should be <= %u", MAX_BURST);
3447
3448 rte_bbdev_info_get(tp->dev_id, &info);
3449
3450 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3451 "NUM_OPS cannot exceed %u for this device",
3452 info.drv.queue_size_lim);
3453
3454 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3455
3456 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
3457 rte_pause();
3458
3459 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
3460 num_ops);
3461 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3462 num_ops);
3463 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3464 copy_reference_enc_op(ops_enq, num_ops, 0, bufs->inputs,
3465 bufs->hard_outputs, ref_op);
3466
3467 /* Set counter to validate the ordering */
3468 for (j = 0; j < num_ops; ++j)
3469 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3470
3471 for (i = 0; i < TEST_REPETITIONS; ++i) {
3472
3473 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3474 for (j = 0; j < num_ops; ++j)
3475 mbuf_reset(ops_enq[j]->turbo_enc.output.data);
3476
3477 start_time = rte_rdtsc_precise();
3478
3479 for (enq = 0, deq = 0; enq < num_ops;) {
3480 num_to_enq = burst_sz;
3481
3482 if (unlikely(num_ops - enq < num_to_enq))
3483 num_to_enq = num_ops - enq;
3484
3485 enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
3486 queue_id, &ops_enq[enq], num_to_enq);
3487
3488 deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
3489 queue_id, &ops_deq[deq], enq - deq);
3490 }
3491
3492 /* dequeue the remaining */
3493 while (deq < enq) {
3494 deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
3495 queue_id, &ops_deq[deq], enq - deq);
3496 }
3497
3498 total_time += rte_rdtsc_precise() - start_time;
3499 }
3500
3501 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3502 ret = validate_enc_op(ops_deq, num_ops, ref_op);
3503 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3504 }
3505
3506 rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
3507
3508 double tb_len_bits = calc_enc_TB_size(ref_op);
3509
3510 tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3511 ((double)total_time / (double)rte_get_tsc_hz());
3512 tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
3513 / 1000000.0) / ((double)total_time /
3514 (double)rte_get_tsc_hz());
3515
3516 return TEST_SUCCESS;
3517 }
3518
3519 static int
throughput_pmd_lcore_ldpc_enc(void * arg)3520 throughput_pmd_lcore_ldpc_enc(void *arg)
3521 {
3522 struct thread_params *tp = arg;
3523 uint16_t enq, deq;
3524 uint64_t total_time = 0, start_time;
3525 const uint16_t queue_id = tp->queue_id;
3526 const uint16_t burst_sz = tp->op_params->burst_sz;
3527 const uint16_t num_ops = tp->op_params->num_to_process;
3528 struct rte_bbdev_enc_op *ops_enq[num_ops];
3529 struct rte_bbdev_enc_op *ops_deq[num_ops];
3530 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
3531 struct test_buffers *bufs = NULL;
3532 int i, j, ret;
3533 struct rte_bbdev_info info;
3534 uint16_t num_to_enq;
3535
3536 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3537 "BURST_SIZE should be <= %u", MAX_BURST);
3538
3539 rte_bbdev_info_get(tp->dev_id, &info);
3540
3541 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3542 "NUM_OPS cannot exceed %u for this device",
3543 info.drv.queue_size_lim);
3544
3545 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3546
3547 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
3548 rte_pause();
3549
3550 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
3551 num_ops);
3552 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3553 num_ops);
3554 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3555 copy_reference_ldpc_enc_op(ops_enq, num_ops, 0, bufs->inputs,
3556 bufs->hard_outputs, ref_op);
3557
3558 /* Set counter to validate the ordering */
3559 for (j = 0; j < num_ops; ++j)
3560 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3561
3562 for (i = 0; i < TEST_REPETITIONS; ++i) {
3563
3564 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3565 for (j = 0; j < num_ops; ++j)
3566 mbuf_reset(ops_enq[j]->turbo_enc.output.data);
3567
3568 start_time = rte_rdtsc_precise();
3569
3570 for (enq = 0, deq = 0; enq < num_ops;) {
3571 num_to_enq = burst_sz;
3572
3573 if (unlikely(num_ops - enq < num_to_enq))
3574 num_to_enq = num_ops - enq;
3575
3576 enq += rte_bbdev_enqueue_ldpc_enc_ops(tp->dev_id,
3577 queue_id, &ops_enq[enq], num_to_enq);
3578
3579 deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
3580 queue_id, &ops_deq[deq], enq - deq);
3581 }
3582
3583 /* dequeue the remaining */
3584 while (deq < enq) {
3585 deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
3586 queue_id, &ops_deq[deq], enq - deq);
3587 }
3588
3589 total_time += rte_rdtsc_precise() - start_time;
3590 }
3591
3592 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3593 ret = validate_ldpc_enc_op(ops_deq, num_ops, ref_op);
3594 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3595 }
3596
3597 rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
3598
3599 double tb_len_bits = calc_ldpc_enc_TB_size(ref_op);
3600
3601 tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3602 ((double)total_time / (double)rte_get_tsc_hz());
3603 tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
3604 / 1000000.0) / ((double)total_time /
3605 (double)rte_get_tsc_hz());
3606
3607 return TEST_SUCCESS;
3608 }
3609
3610 static void
print_enc_throughput(struct thread_params * t_params,unsigned int used_cores)3611 print_enc_throughput(struct thread_params *t_params, unsigned int used_cores)
3612 {
3613 unsigned int iter = 0;
3614 double total_mops = 0, total_mbps = 0;
3615
3616 for (iter = 0; iter < used_cores; iter++) {
3617 printf(
3618 "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps\n",
3619 t_params[iter].lcore_id, t_params[iter].ops_per_sec,
3620 t_params[iter].mbps);
3621 total_mops += t_params[iter].ops_per_sec;
3622 total_mbps += t_params[iter].mbps;
3623 }
3624 printf(
3625 "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps\n",
3626 used_cores, total_mops, total_mbps);
3627 }
3628
3629 /* Aggregate the performance results over the number of cores used */
3630 static void
print_dec_throughput(struct thread_params * t_params,unsigned int used_cores)3631 print_dec_throughput(struct thread_params *t_params, unsigned int used_cores)
3632 {
3633 unsigned int core_idx = 0;
3634 double total_mops = 0, total_mbps = 0;
3635 uint8_t iter_count = 0;
3636
3637 for (core_idx = 0; core_idx < used_cores; core_idx++) {
3638 printf(
3639 "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps @ max %u iterations\n",
3640 t_params[core_idx].lcore_id,
3641 t_params[core_idx].ops_per_sec,
3642 t_params[core_idx].mbps,
3643 t_params[core_idx].iter_count);
3644 total_mops += t_params[core_idx].ops_per_sec;
3645 total_mbps += t_params[core_idx].mbps;
3646 iter_count = RTE_MAX(iter_count,
3647 t_params[core_idx].iter_count);
3648 }
3649 printf(
3650 "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps @ max %u iterations\n",
3651 used_cores, total_mops, total_mbps, iter_count);
3652 }
3653
3654 /* Aggregate the performance results over the number of cores used */
3655 static void
print_dec_bler(struct thread_params * t_params,unsigned int used_cores)3656 print_dec_bler(struct thread_params *t_params, unsigned int used_cores)
3657 {
3658 unsigned int core_idx = 0;
3659 double total_mbps = 0, total_bler = 0, total_iter = 0;
3660 double snr = get_snr();
3661
3662 for (core_idx = 0; core_idx < used_cores; core_idx++) {
3663 printf("Core%u BLER %.1f %% - Iters %.1f - Tp %.1f Mbps %s\n",
3664 t_params[core_idx].lcore_id,
3665 t_params[core_idx].bler * 100,
3666 t_params[core_idx].iter_average,
3667 t_params[core_idx].mbps,
3668 get_vector_filename());
3669 total_mbps += t_params[core_idx].mbps;
3670 total_bler += t_params[core_idx].bler;
3671 total_iter += t_params[core_idx].iter_average;
3672 }
3673 total_bler /= used_cores;
3674 total_iter /= used_cores;
3675
3676 printf("SNR %.2f BLER %.1f %% - Iterations %.1f %d - Tp %.1f Mbps %s\n",
3677 snr, total_bler * 100, total_iter, get_iter_max(),
3678 total_mbps, get_vector_filename());
3679 }
3680
3681 /*
3682 * Test function that determines BLER wireless performance
3683 */
3684 static int
bler_test(struct active_device * ad,struct test_op_params * op_params)3685 bler_test(struct active_device *ad,
3686 struct test_op_params *op_params)
3687 {
3688 int ret;
3689 unsigned int lcore_id, used_cores = 0;
3690 struct thread_params *t_params;
3691 struct rte_bbdev_info info;
3692 lcore_function_t *bler_function;
3693 uint16_t num_lcores;
3694 const char *op_type_str;
3695
3696 rte_bbdev_info_get(ad->dev_id, &info);
3697
3698 op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
3699 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
3700 test_vector.op_type);
3701
3702 printf("+ ------------------------------------------------------- +\n");
3703 printf("== test: bler\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, itr mode: %s, GHz: %lg\n",
3704 info.dev_name, ad->nb_queues, op_params->burst_sz,
3705 op_params->num_to_process, op_params->num_lcores,
3706 op_type_str,
3707 intr_enabled ? "Interrupt mode" : "PMD mode",
3708 (double)rte_get_tsc_hz() / 1000000000.0);
3709
3710 /* Set number of lcores */
3711 num_lcores = (ad->nb_queues < (op_params->num_lcores))
3712 ? ad->nb_queues
3713 : op_params->num_lcores;
3714
3715 /* Allocate memory for thread parameters structure */
3716 t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
3717 RTE_CACHE_LINE_SIZE);
3718 TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
3719 RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
3720 RTE_CACHE_LINE_SIZE));
3721
3722 if ((test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) &&
3723 !check_bit(test_vector.ldpc_dec.op_flags,
3724 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
3725 && !check_bit(test_vector.ldpc_dec.op_flags,
3726 RTE_BBDEV_LDPC_LLR_COMPRESSION))
3727 bler_function = bler_pmd_lcore_ldpc_dec;
3728 else
3729 return TEST_SKIPPED;
3730
3731 rte_atomic16_set(&op_params->sync, SYNC_WAIT);
3732
3733 /* Main core is set at first entry */
3734 t_params[0].dev_id = ad->dev_id;
3735 t_params[0].lcore_id = rte_lcore_id();
3736 t_params[0].op_params = op_params;
3737 t_params[0].queue_id = ad->queue_ids[used_cores++];
3738 t_params[0].iter_count = 0;
3739
3740 RTE_LCORE_FOREACH_WORKER(lcore_id) {
3741 if (used_cores >= num_lcores)
3742 break;
3743
3744 t_params[used_cores].dev_id = ad->dev_id;
3745 t_params[used_cores].lcore_id = lcore_id;
3746 t_params[used_cores].op_params = op_params;
3747 t_params[used_cores].queue_id = ad->queue_ids[used_cores];
3748 t_params[used_cores].iter_count = 0;
3749
3750 rte_eal_remote_launch(bler_function,
3751 &t_params[used_cores++], lcore_id);
3752 }
3753
3754 rte_atomic16_set(&op_params->sync, SYNC_START);
3755 ret = bler_function(&t_params[0]);
3756
3757 /* Main core is always used */
3758 for (used_cores = 1; used_cores < num_lcores; used_cores++)
3759 ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
3760
3761 print_dec_bler(t_params, num_lcores);
3762
3763 /* Return if test failed */
3764 if (ret) {
3765 rte_free(t_params);
3766 return ret;
3767 }
3768
3769 /* Function to print something here*/
3770 rte_free(t_params);
3771 return ret;
3772 }
3773
3774 /*
3775 * Test function that determines how long an enqueue + dequeue of a burst
3776 * takes on available lcores.
3777 */
3778 static int
throughput_test(struct active_device * ad,struct test_op_params * op_params)3779 throughput_test(struct active_device *ad,
3780 struct test_op_params *op_params)
3781 {
3782 int ret;
3783 unsigned int lcore_id, used_cores = 0;
3784 struct thread_params *t_params, *tp;
3785 struct rte_bbdev_info info;
3786 lcore_function_t *throughput_function;
3787 uint16_t num_lcores;
3788 const char *op_type_str;
3789
3790 rte_bbdev_info_get(ad->dev_id, &info);
3791
3792 op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
3793 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
3794 test_vector.op_type);
3795
3796 printf("+ ------------------------------------------------------- +\n");
3797 printf("== test: throughput\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, itr mode: %s, GHz: %lg\n",
3798 info.dev_name, ad->nb_queues, op_params->burst_sz,
3799 op_params->num_to_process, op_params->num_lcores,
3800 op_type_str,
3801 intr_enabled ? "Interrupt mode" : "PMD mode",
3802 (double)rte_get_tsc_hz() / 1000000000.0);
3803
3804 /* Set number of lcores */
3805 num_lcores = (ad->nb_queues < (op_params->num_lcores))
3806 ? ad->nb_queues
3807 : op_params->num_lcores;
3808
3809 /* Allocate memory for thread parameters structure */
3810 t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
3811 RTE_CACHE_LINE_SIZE);
3812 TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
3813 RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
3814 RTE_CACHE_LINE_SIZE));
3815
3816 if (intr_enabled) {
3817 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
3818 throughput_function = throughput_intr_lcore_dec;
3819 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
3820 throughput_function = throughput_intr_lcore_ldpc_dec;
3821 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
3822 throughput_function = throughput_intr_lcore_enc;
3823 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
3824 throughput_function = throughput_intr_lcore_ldpc_enc;
3825 else
3826 throughput_function = throughput_intr_lcore_enc;
3827
3828 /* Dequeue interrupt callback registration */
3829 ret = rte_bbdev_callback_register(ad->dev_id,
3830 RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
3831 t_params);
3832 if (ret < 0) {
3833 rte_free(t_params);
3834 return ret;
3835 }
3836 } else {
3837 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
3838 throughput_function = throughput_pmd_lcore_dec;
3839 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
3840 throughput_function = throughput_pmd_lcore_ldpc_dec;
3841 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
3842 throughput_function = throughput_pmd_lcore_enc;
3843 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
3844 throughput_function = throughput_pmd_lcore_ldpc_enc;
3845 else
3846 throughput_function = throughput_pmd_lcore_enc;
3847 }
3848
3849 rte_atomic16_set(&op_params->sync, SYNC_WAIT);
3850
3851 /* Main core is set at first entry */
3852 t_params[0].dev_id = ad->dev_id;
3853 t_params[0].lcore_id = rte_lcore_id();
3854 t_params[0].op_params = op_params;
3855 t_params[0].queue_id = ad->queue_ids[used_cores++];
3856 t_params[0].iter_count = 0;
3857
3858 RTE_LCORE_FOREACH_WORKER(lcore_id) {
3859 if (used_cores >= num_lcores)
3860 break;
3861
3862 t_params[used_cores].dev_id = ad->dev_id;
3863 t_params[used_cores].lcore_id = lcore_id;
3864 t_params[used_cores].op_params = op_params;
3865 t_params[used_cores].queue_id = ad->queue_ids[used_cores];
3866 t_params[used_cores].iter_count = 0;
3867
3868 rte_eal_remote_launch(throughput_function,
3869 &t_params[used_cores++], lcore_id);
3870 }
3871
3872 rte_atomic16_set(&op_params->sync, SYNC_START);
3873 ret = throughput_function(&t_params[0]);
3874
3875 /* Main core is always used */
3876 for (used_cores = 1; used_cores < num_lcores; used_cores++)
3877 ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
3878
3879 /* Return if test failed */
3880 if (ret) {
3881 rte_free(t_params);
3882 return ret;
3883 }
3884
3885 /* Print throughput if interrupts are disabled and test passed */
3886 if (!intr_enabled) {
3887 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
3888 test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
3889 print_dec_throughput(t_params, num_lcores);
3890 else
3891 print_enc_throughput(t_params, num_lcores);
3892 rte_free(t_params);
3893 return ret;
3894 }
3895
3896 /* In interrupt TC we need to wait for the interrupt callback to deqeue
3897 * all pending operations. Skip waiting for queues which reported an
3898 * error using processing_status variable.
3899 * Wait for main lcore operations.
3900 */
3901 tp = &t_params[0];
3902 while ((rte_atomic16_read(&tp->nb_dequeued) <
3903 op_params->num_to_process) &&
3904 (rte_atomic16_read(&tp->processing_status) !=
3905 TEST_FAILED))
3906 rte_pause();
3907
3908 tp->ops_per_sec /= TEST_REPETITIONS;
3909 tp->mbps /= TEST_REPETITIONS;
3910 ret |= (int)rte_atomic16_read(&tp->processing_status);
3911
3912 /* Wait for worker lcores operations */
3913 for (used_cores = 1; used_cores < num_lcores; used_cores++) {
3914 tp = &t_params[used_cores];
3915
3916 while ((rte_atomic16_read(&tp->nb_dequeued) <
3917 op_params->num_to_process) &&
3918 (rte_atomic16_read(&tp->processing_status) !=
3919 TEST_FAILED))
3920 rte_pause();
3921
3922 tp->ops_per_sec /= TEST_REPETITIONS;
3923 tp->mbps /= TEST_REPETITIONS;
3924 ret |= (int)rte_atomic16_read(&tp->processing_status);
3925 }
3926
3927 /* Print throughput if test passed */
3928 if (!ret) {
3929 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
3930 test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
3931 print_dec_throughput(t_params, num_lcores);
3932 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC ||
3933 test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
3934 print_enc_throughput(t_params, num_lcores);
3935 }
3936
3937 rte_free(t_params);
3938 return ret;
3939 }
3940
3941 static int
latency_test_dec(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_dec_op * ref_op,int vector_mask,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,uint64_t * total_time,uint64_t * min_time,uint64_t * max_time)3942 latency_test_dec(struct rte_mempool *mempool,
3943 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
3944 int vector_mask, uint16_t dev_id, uint16_t queue_id,
3945 const uint16_t num_to_process, uint16_t burst_sz,
3946 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
3947 {
3948 int ret = TEST_SUCCESS;
3949 uint16_t i, j, dequeued;
3950 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
3951 uint64_t start_time = 0, last_time = 0;
3952
3953 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
3954 uint16_t enq = 0, deq = 0;
3955 bool first_time = true;
3956 last_time = 0;
3957
3958 if (unlikely(num_to_process - dequeued < burst_sz))
3959 burst_sz = num_to_process - dequeued;
3960
3961 ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
3962 TEST_ASSERT_SUCCESS(ret,
3963 "rte_bbdev_dec_op_alloc_bulk() failed");
3964 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3965 copy_reference_dec_op(ops_enq, burst_sz, dequeued,
3966 bufs->inputs,
3967 bufs->hard_outputs,
3968 bufs->soft_outputs,
3969 ref_op);
3970
3971 /* Set counter to validate the ordering */
3972 for (j = 0; j < burst_sz; ++j)
3973 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3974
3975 start_time = rte_rdtsc_precise();
3976
3977 enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
3978 burst_sz);
3979 TEST_ASSERT(enq == burst_sz,
3980 "Error enqueueing burst, expected %u, got %u",
3981 burst_sz, enq);
3982
3983 /* Dequeue */
3984 do {
3985 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
3986 &ops_deq[deq], burst_sz - deq);
3987 if (likely(first_time && (deq > 0))) {
3988 last_time = rte_rdtsc_precise() - start_time;
3989 first_time = false;
3990 }
3991 } while (unlikely(burst_sz != deq));
3992
3993 *max_time = RTE_MAX(*max_time, last_time);
3994 *min_time = RTE_MIN(*min_time, last_time);
3995 *total_time += last_time;
3996
3997 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3998 ret = validate_dec_op(ops_deq, burst_sz, ref_op,
3999 vector_mask);
4000 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4001 }
4002
4003 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
4004 dequeued += deq;
4005 }
4006
4007 return i;
4008 }
4009
4010 /* Test case for latency/validation for LDPC Decoder */
4011 static int
latency_test_ldpc_dec(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_dec_op * ref_op,int vector_mask,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,uint64_t * total_time,uint64_t * min_time,uint64_t * max_time,bool disable_et)4012 latency_test_ldpc_dec(struct rte_mempool *mempool,
4013 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
4014 int vector_mask, uint16_t dev_id, uint16_t queue_id,
4015 const uint16_t num_to_process, uint16_t burst_sz,
4016 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time,
4017 bool disable_et)
4018 {
4019 int ret = TEST_SUCCESS;
4020 uint16_t i, j, dequeued;
4021 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4022 uint64_t start_time = 0, last_time = 0;
4023 bool extDdr = ldpc_cap_flags &
4024 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
4025
4026 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4027 uint16_t enq = 0, deq = 0;
4028 bool first_time = true;
4029 last_time = 0;
4030
4031 if (unlikely(num_to_process - dequeued < burst_sz))
4032 burst_sz = num_to_process - dequeued;
4033
4034 ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
4035 TEST_ASSERT_SUCCESS(ret,
4036 "rte_bbdev_dec_op_alloc_bulk() failed");
4037
4038 /* For latency tests we need to disable early termination */
4039 if (disable_et && check_bit(ref_op->ldpc_dec.op_flags,
4040 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
4041 ref_op->ldpc_dec.op_flags -=
4042 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
4043 ref_op->ldpc_dec.iter_max = get_iter_max();
4044 ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
4045
4046 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4047 copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
4048 bufs->inputs,
4049 bufs->hard_outputs,
4050 bufs->soft_outputs,
4051 bufs->harq_inputs,
4052 bufs->harq_outputs,
4053 ref_op);
4054
4055 if (extDdr)
4056 preload_harq_ddr(dev_id, queue_id, ops_enq,
4057 burst_sz, true);
4058
4059 /* Set counter to validate the ordering */
4060 for (j = 0; j < burst_sz; ++j)
4061 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4062
4063 start_time = rte_rdtsc_precise();
4064
4065 enq = rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
4066 &ops_enq[enq], burst_sz);
4067 TEST_ASSERT(enq == burst_sz,
4068 "Error enqueueing burst, expected %u, got %u",
4069 burst_sz, enq);
4070
4071 /* Dequeue */
4072 do {
4073 deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
4074 &ops_deq[deq], burst_sz - deq);
4075 if (likely(first_time && (deq > 0))) {
4076 last_time = rte_rdtsc_precise() - start_time;
4077 first_time = false;
4078 }
4079 } while (unlikely(burst_sz != deq));
4080
4081 *max_time = RTE_MAX(*max_time, last_time);
4082 *min_time = RTE_MIN(*min_time, last_time);
4083 *total_time += last_time;
4084
4085 if (extDdr)
4086 retrieve_harq_ddr(dev_id, queue_id, ops_enq, burst_sz);
4087
4088 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4089 ret = validate_ldpc_dec_op(ops_deq, burst_sz, ref_op,
4090 vector_mask);
4091 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4092 }
4093
4094 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
4095 dequeued += deq;
4096 }
4097 return i;
4098 }
4099
4100 static int
latency_test_enc(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_enc_op * ref_op,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,uint64_t * total_time,uint64_t * min_time,uint64_t * max_time)4101 latency_test_enc(struct rte_mempool *mempool,
4102 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
4103 uint16_t dev_id, uint16_t queue_id,
4104 const uint16_t num_to_process, uint16_t burst_sz,
4105 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
4106 {
4107 int ret = TEST_SUCCESS;
4108 uint16_t i, j, dequeued;
4109 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4110 uint64_t start_time = 0, last_time = 0;
4111
4112 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4113 uint16_t enq = 0, deq = 0;
4114 bool first_time = true;
4115 last_time = 0;
4116
4117 if (unlikely(num_to_process - dequeued < burst_sz))
4118 burst_sz = num_to_process - dequeued;
4119
4120 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
4121 TEST_ASSERT_SUCCESS(ret,
4122 "rte_bbdev_enc_op_alloc_bulk() failed");
4123 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4124 copy_reference_enc_op(ops_enq, burst_sz, dequeued,
4125 bufs->inputs,
4126 bufs->hard_outputs,
4127 ref_op);
4128
4129 /* Set counter to validate the ordering */
4130 for (j = 0; j < burst_sz; ++j)
4131 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4132
4133 start_time = rte_rdtsc_precise();
4134
4135 enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
4136 burst_sz);
4137 TEST_ASSERT(enq == burst_sz,
4138 "Error enqueueing burst, expected %u, got %u",
4139 burst_sz, enq);
4140
4141 /* Dequeue */
4142 do {
4143 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
4144 &ops_deq[deq], burst_sz - deq);
4145 if (likely(first_time && (deq > 0))) {
4146 last_time += rte_rdtsc_precise() - start_time;
4147 first_time = false;
4148 }
4149 } while (unlikely(burst_sz != deq));
4150
4151 *max_time = RTE_MAX(*max_time, last_time);
4152 *min_time = RTE_MIN(*min_time, last_time);
4153 *total_time += last_time;
4154
4155 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4156 ret = validate_enc_op(ops_deq, burst_sz, ref_op);
4157 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4158 }
4159
4160 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
4161 dequeued += deq;
4162 }
4163
4164 return i;
4165 }
4166
4167 static int
latency_test_ldpc_enc(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_enc_op * ref_op,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,uint64_t * total_time,uint64_t * min_time,uint64_t * max_time)4168 latency_test_ldpc_enc(struct rte_mempool *mempool,
4169 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
4170 uint16_t dev_id, uint16_t queue_id,
4171 const uint16_t num_to_process, uint16_t burst_sz,
4172 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
4173 {
4174 int ret = TEST_SUCCESS;
4175 uint16_t i, j, dequeued;
4176 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4177 uint64_t start_time = 0, last_time = 0;
4178
4179 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4180 uint16_t enq = 0, deq = 0;
4181 bool first_time = true;
4182 last_time = 0;
4183
4184 if (unlikely(num_to_process - dequeued < burst_sz))
4185 burst_sz = num_to_process - dequeued;
4186
4187 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
4188 TEST_ASSERT_SUCCESS(ret,
4189 "rte_bbdev_enc_op_alloc_bulk() failed");
4190 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4191 copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
4192 bufs->inputs,
4193 bufs->hard_outputs,
4194 ref_op);
4195
4196 /* Set counter to validate the ordering */
4197 for (j = 0; j < burst_sz; ++j)
4198 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4199
4200 start_time = rte_rdtsc_precise();
4201
4202 enq = rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
4203 &ops_enq[enq], burst_sz);
4204 TEST_ASSERT(enq == burst_sz,
4205 "Error enqueueing burst, expected %u, got %u",
4206 burst_sz, enq);
4207
4208 /* Dequeue */
4209 do {
4210 deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
4211 &ops_deq[deq], burst_sz - deq);
4212 if (likely(first_time && (deq > 0))) {
4213 last_time += rte_rdtsc_precise() - start_time;
4214 first_time = false;
4215 }
4216 } while (unlikely(burst_sz != deq));
4217
4218 *max_time = RTE_MAX(*max_time, last_time);
4219 *min_time = RTE_MIN(*min_time, last_time);
4220 *total_time += last_time;
4221
4222 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4223 ret = validate_enc_op(ops_deq, burst_sz, ref_op);
4224 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4225 }
4226
4227 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
4228 dequeued += deq;
4229 }
4230
4231 return i;
4232 }
4233
4234 /* Common function for running validation and latency test cases */
4235 static int
validation_latency_test(struct active_device * ad,struct test_op_params * op_params,bool latency_flag)4236 validation_latency_test(struct active_device *ad,
4237 struct test_op_params *op_params, bool latency_flag)
4238 {
4239 int iter;
4240 uint16_t burst_sz = op_params->burst_sz;
4241 const uint16_t num_to_process = op_params->num_to_process;
4242 const enum rte_bbdev_op_type op_type = test_vector.op_type;
4243 const uint16_t queue_id = ad->queue_ids[0];
4244 struct test_buffers *bufs = NULL;
4245 struct rte_bbdev_info info;
4246 uint64_t total_time, min_time, max_time;
4247 const char *op_type_str;
4248
4249 total_time = max_time = 0;
4250 min_time = UINT64_MAX;
4251
4252 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
4253 "BURST_SIZE should be <= %u", MAX_BURST);
4254
4255 rte_bbdev_info_get(ad->dev_id, &info);
4256 bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
4257
4258 op_type_str = rte_bbdev_op_type_str(op_type);
4259 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
4260
4261 printf("+ ------------------------------------------------------- +\n");
4262 if (latency_flag)
4263 printf("== test: latency\ndev:");
4264 else
4265 printf("== test: validation\ndev:");
4266 printf("%s, burst size: %u, num ops: %u, op type: %s\n",
4267 info.dev_name, burst_sz, num_to_process, op_type_str);
4268
4269 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
4270 iter = latency_test_dec(op_params->mp, bufs,
4271 op_params->ref_dec_op, op_params->vector_mask,
4272 ad->dev_id, queue_id, num_to_process,
4273 burst_sz, &total_time, &min_time, &max_time);
4274 else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
4275 iter = latency_test_ldpc_enc(op_params->mp, bufs,
4276 op_params->ref_enc_op, ad->dev_id, queue_id,
4277 num_to_process, burst_sz, &total_time,
4278 &min_time, &max_time);
4279 else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
4280 iter = latency_test_ldpc_dec(op_params->mp, bufs,
4281 op_params->ref_dec_op, op_params->vector_mask,
4282 ad->dev_id, queue_id, num_to_process,
4283 burst_sz, &total_time, &min_time, &max_time,
4284 latency_flag);
4285 else /* RTE_BBDEV_OP_TURBO_ENC */
4286 iter = latency_test_enc(op_params->mp, bufs,
4287 op_params->ref_enc_op,
4288 ad->dev_id, queue_id,
4289 num_to_process, burst_sz, &total_time,
4290 &min_time, &max_time);
4291
4292 if (iter <= 0)
4293 return TEST_FAILED;
4294
4295 printf("Operation latency:\n"
4296 "\tavg: %lg cycles, %lg us\n"
4297 "\tmin: %lg cycles, %lg us\n"
4298 "\tmax: %lg cycles, %lg us\n",
4299 (double)total_time / (double)iter,
4300 (double)(total_time * 1000000) / (double)iter /
4301 (double)rte_get_tsc_hz(), (double)min_time,
4302 (double)(min_time * 1000000) / (double)rte_get_tsc_hz(),
4303 (double)max_time, (double)(max_time * 1000000) /
4304 (double)rte_get_tsc_hz());
4305
4306 return TEST_SUCCESS;
4307 }
4308
4309 static int
latency_test(struct active_device * ad,struct test_op_params * op_params)4310 latency_test(struct active_device *ad, struct test_op_params *op_params)
4311 {
4312 return validation_latency_test(ad, op_params, true);
4313 }
4314
4315 static int
validation_test(struct active_device * ad,struct test_op_params * op_params)4316 validation_test(struct active_device *ad, struct test_op_params *op_params)
4317 {
4318 return validation_latency_test(ad, op_params, false);
4319 }
4320
4321 #ifdef RTE_BBDEV_OFFLOAD_COST
4322 static int
get_bbdev_queue_stats(uint16_t dev_id,uint16_t queue_id,struct rte_bbdev_stats * stats)4323 get_bbdev_queue_stats(uint16_t dev_id, uint16_t queue_id,
4324 struct rte_bbdev_stats *stats)
4325 {
4326 struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
4327 struct rte_bbdev_stats *q_stats;
4328
4329 if (queue_id >= dev->data->num_queues)
4330 return -1;
4331
4332 q_stats = &dev->data->queues[queue_id].queue_stats;
4333
4334 stats->enqueued_count = q_stats->enqueued_count;
4335 stats->dequeued_count = q_stats->dequeued_count;
4336 stats->enqueue_err_count = q_stats->enqueue_err_count;
4337 stats->dequeue_err_count = q_stats->dequeue_err_count;
4338 stats->acc_offload_cycles = q_stats->acc_offload_cycles;
4339
4340 return 0;
4341 }
4342
4343 static int
offload_latency_test_dec(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_dec_op * ref_op,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,struct test_time_stats * time_st)4344 offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
4345 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
4346 uint16_t queue_id, const uint16_t num_to_process,
4347 uint16_t burst_sz, struct test_time_stats *time_st)
4348 {
4349 int i, dequeued, ret;
4350 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4351 uint64_t enq_start_time, deq_start_time;
4352 uint64_t enq_sw_last_time, deq_last_time;
4353 struct rte_bbdev_stats stats;
4354
4355 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4356 uint16_t enq = 0, deq = 0;
4357
4358 if (unlikely(num_to_process - dequeued < burst_sz))
4359 burst_sz = num_to_process - dequeued;
4360
4361 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
4362 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4363 copy_reference_dec_op(ops_enq, burst_sz, dequeued,
4364 bufs->inputs,
4365 bufs->hard_outputs,
4366 bufs->soft_outputs,
4367 ref_op);
4368
4369 /* Start time meas for enqueue function offload latency */
4370 enq_start_time = rte_rdtsc_precise();
4371 do {
4372 enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
4373 &ops_enq[enq], burst_sz - enq);
4374 } while (unlikely(burst_sz != enq));
4375
4376 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
4377 TEST_ASSERT_SUCCESS(ret,
4378 "Failed to get stats for queue (%u) of device (%u)",
4379 queue_id, dev_id);
4380
4381 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
4382 stats.acc_offload_cycles;
4383 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
4384 enq_sw_last_time);
4385 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
4386 enq_sw_last_time);
4387 time_st->enq_sw_total_time += enq_sw_last_time;
4388
4389 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
4390 stats.acc_offload_cycles);
4391 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
4392 stats.acc_offload_cycles);
4393 time_st->enq_acc_total_time += stats.acc_offload_cycles;
4394
4395 /* give time for device to process ops */
4396 rte_delay_us(WAIT_OFFLOAD_US);
4397
4398 /* Start time meas for dequeue function offload latency */
4399 deq_start_time = rte_rdtsc_precise();
4400 /* Dequeue one operation */
4401 do {
4402 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
4403 &ops_deq[deq], enq);
4404 } while (unlikely(deq == 0));
4405
4406 deq_last_time = rte_rdtsc_precise() - deq_start_time;
4407 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
4408 deq_last_time);
4409 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
4410 deq_last_time);
4411 time_st->deq_total_time += deq_last_time;
4412
4413 /* Dequeue remaining operations if needed*/
4414 while (burst_sz != deq)
4415 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
4416 &ops_deq[deq], burst_sz - deq);
4417
4418 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
4419 dequeued += deq;
4420 }
4421
4422 return i;
4423 }
4424
4425 static int
offload_latency_test_ldpc_dec(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_dec_op * ref_op,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,struct test_time_stats * time_st)4426 offload_latency_test_ldpc_dec(struct rte_mempool *mempool,
4427 struct test_buffers *bufs,
4428 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
4429 uint16_t queue_id, const uint16_t num_to_process,
4430 uint16_t burst_sz, struct test_time_stats *time_st)
4431 {
4432 int i, dequeued, ret;
4433 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4434 uint64_t enq_start_time, deq_start_time;
4435 uint64_t enq_sw_last_time, deq_last_time;
4436 struct rte_bbdev_stats stats;
4437 bool extDdr = ldpc_cap_flags &
4438 RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
4439
4440 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4441 uint16_t enq = 0, deq = 0;
4442
4443 if (unlikely(num_to_process - dequeued < burst_sz))
4444 burst_sz = num_to_process - dequeued;
4445
4446 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
4447 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4448 copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
4449 bufs->inputs,
4450 bufs->hard_outputs,
4451 bufs->soft_outputs,
4452 bufs->harq_inputs,
4453 bufs->harq_outputs,
4454 ref_op);
4455
4456 if (extDdr)
4457 preload_harq_ddr(dev_id, queue_id, ops_enq,
4458 burst_sz, true);
4459
4460 /* Start time meas for enqueue function offload latency */
4461 enq_start_time = rte_rdtsc_precise();
4462 do {
4463 enq += rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
4464 &ops_enq[enq], burst_sz - enq);
4465 } while (unlikely(burst_sz != enq));
4466
4467 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
4468 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
4469 TEST_ASSERT_SUCCESS(ret,
4470 "Failed to get stats for queue (%u) of device (%u)",
4471 queue_id, dev_id);
4472
4473 enq_sw_last_time -= stats.acc_offload_cycles;
4474 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
4475 enq_sw_last_time);
4476 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
4477 enq_sw_last_time);
4478 time_st->enq_sw_total_time += enq_sw_last_time;
4479
4480 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
4481 stats.acc_offload_cycles);
4482 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
4483 stats.acc_offload_cycles);
4484 time_st->enq_acc_total_time += stats.acc_offload_cycles;
4485
4486 /* give time for device to process ops */
4487 rte_delay_us(WAIT_OFFLOAD_US);
4488
4489 /* Start time meas for dequeue function offload latency */
4490 deq_start_time = rte_rdtsc_precise();
4491 /* Dequeue one operation */
4492 do {
4493 deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
4494 &ops_deq[deq], enq);
4495 } while (unlikely(deq == 0));
4496
4497 deq_last_time = rte_rdtsc_precise() - deq_start_time;
4498 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
4499 deq_last_time);
4500 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
4501 deq_last_time);
4502 time_st->deq_total_time += deq_last_time;
4503
4504 /* Dequeue remaining operations if needed*/
4505 while (burst_sz != deq)
4506 deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
4507 &ops_deq[deq], burst_sz - deq);
4508
4509 if (extDdr) {
4510 /* Read loopback is not thread safe */
4511 retrieve_harq_ddr(dev_id, queue_id, ops_enq, burst_sz);
4512 }
4513
4514 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
4515 dequeued += deq;
4516 }
4517
4518 return i;
4519 }
4520
4521 static int
offload_latency_test_enc(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_enc_op * ref_op,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,struct test_time_stats * time_st)4522 offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
4523 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
4524 uint16_t queue_id, const uint16_t num_to_process,
4525 uint16_t burst_sz, struct test_time_stats *time_st)
4526 {
4527 int i, dequeued, ret;
4528 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4529 uint64_t enq_start_time, deq_start_time;
4530 uint64_t enq_sw_last_time, deq_last_time;
4531 struct rte_bbdev_stats stats;
4532
4533 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4534 uint16_t enq = 0, deq = 0;
4535
4536 if (unlikely(num_to_process - dequeued < burst_sz))
4537 burst_sz = num_to_process - dequeued;
4538
4539 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
4540 TEST_ASSERT_SUCCESS(ret,
4541 "rte_bbdev_enc_op_alloc_bulk() failed");
4542 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4543 copy_reference_enc_op(ops_enq, burst_sz, dequeued,
4544 bufs->inputs,
4545 bufs->hard_outputs,
4546 ref_op);
4547
4548 /* Start time meas for enqueue function offload latency */
4549 enq_start_time = rte_rdtsc_precise();
4550 do {
4551 enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
4552 &ops_enq[enq], burst_sz - enq);
4553 } while (unlikely(burst_sz != enq));
4554
4555 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
4556
4557 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
4558 TEST_ASSERT_SUCCESS(ret,
4559 "Failed to get stats for queue (%u) of device (%u)",
4560 queue_id, dev_id);
4561 enq_sw_last_time -= stats.acc_offload_cycles;
4562 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
4563 enq_sw_last_time);
4564 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
4565 enq_sw_last_time);
4566 time_st->enq_sw_total_time += enq_sw_last_time;
4567
4568 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
4569 stats.acc_offload_cycles);
4570 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
4571 stats.acc_offload_cycles);
4572 time_st->enq_acc_total_time += stats.acc_offload_cycles;
4573
4574 /* give time for device to process ops */
4575 rte_delay_us(WAIT_OFFLOAD_US);
4576
4577 /* Start time meas for dequeue function offload latency */
4578 deq_start_time = rte_rdtsc_precise();
4579 /* Dequeue one operation */
4580 do {
4581 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
4582 &ops_deq[deq], enq);
4583 } while (unlikely(deq == 0));
4584
4585 deq_last_time = rte_rdtsc_precise() - deq_start_time;
4586 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
4587 deq_last_time);
4588 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
4589 deq_last_time);
4590 time_st->deq_total_time += deq_last_time;
4591
4592 while (burst_sz != deq)
4593 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
4594 &ops_deq[deq], burst_sz - deq);
4595
4596 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
4597 dequeued += deq;
4598 }
4599
4600 return i;
4601 }
4602
4603 static int
offload_latency_test_ldpc_enc(struct rte_mempool * mempool,struct test_buffers * bufs,struct rte_bbdev_enc_op * ref_op,uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,struct test_time_stats * time_st)4604 offload_latency_test_ldpc_enc(struct rte_mempool *mempool,
4605 struct test_buffers *bufs,
4606 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
4607 uint16_t queue_id, const uint16_t num_to_process,
4608 uint16_t burst_sz, struct test_time_stats *time_st)
4609 {
4610 int i, dequeued, ret;
4611 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4612 uint64_t enq_start_time, deq_start_time;
4613 uint64_t enq_sw_last_time, deq_last_time;
4614 struct rte_bbdev_stats stats;
4615
4616 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4617 uint16_t enq = 0, deq = 0;
4618
4619 if (unlikely(num_to_process - dequeued < burst_sz))
4620 burst_sz = num_to_process - dequeued;
4621
4622 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
4623 TEST_ASSERT_SUCCESS(ret,
4624 "rte_bbdev_enc_op_alloc_bulk() failed");
4625 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4626 copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
4627 bufs->inputs,
4628 bufs->hard_outputs,
4629 ref_op);
4630
4631 /* Start time meas for enqueue function offload latency */
4632 enq_start_time = rte_rdtsc_precise();
4633 do {
4634 enq += rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
4635 &ops_enq[enq], burst_sz - enq);
4636 } while (unlikely(burst_sz != enq));
4637
4638 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
4639 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
4640 TEST_ASSERT_SUCCESS(ret,
4641 "Failed to get stats for queue (%u) of device (%u)",
4642 queue_id, dev_id);
4643
4644 enq_sw_last_time -= stats.acc_offload_cycles;
4645 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
4646 enq_sw_last_time);
4647 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
4648 enq_sw_last_time);
4649 time_st->enq_sw_total_time += enq_sw_last_time;
4650
4651 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
4652 stats.acc_offload_cycles);
4653 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
4654 stats.acc_offload_cycles);
4655 time_st->enq_acc_total_time += stats.acc_offload_cycles;
4656
4657 /* give time for device to process ops */
4658 rte_delay_us(WAIT_OFFLOAD_US);
4659
4660 /* Start time meas for dequeue function offload latency */
4661 deq_start_time = rte_rdtsc_precise();
4662 /* Dequeue one operation */
4663 do {
4664 deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
4665 &ops_deq[deq], enq);
4666 } while (unlikely(deq == 0));
4667
4668 deq_last_time = rte_rdtsc_precise() - deq_start_time;
4669 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
4670 deq_last_time);
4671 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
4672 deq_last_time);
4673 time_st->deq_total_time += deq_last_time;
4674
4675 while (burst_sz != deq)
4676 deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
4677 &ops_deq[deq], burst_sz - deq);
4678
4679 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
4680 dequeued += deq;
4681 }
4682
4683 return i;
4684 }
4685 #endif
4686
4687 static int
offload_cost_test(struct active_device * ad,struct test_op_params * op_params)4688 offload_cost_test(struct active_device *ad,
4689 struct test_op_params *op_params)
4690 {
4691 #ifndef RTE_BBDEV_OFFLOAD_COST
4692 RTE_SET_USED(ad);
4693 RTE_SET_USED(op_params);
4694 printf("Offload latency test is disabled.\n");
4695 printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
4696 return TEST_SKIPPED;
4697 #else
4698 int iter;
4699 uint16_t burst_sz = op_params->burst_sz;
4700 const uint16_t num_to_process = op_params->num_to_process;
4701 const enum rte_bbdev_op_type op_type = test_vector.op_type;
4702 const uint16_t queue_id = ad->queue_ids[0];
4703 struct test_buffers *bufs = NULL;
4704 struct rte_bbdev_info info;
4705 const char *op_type_str;
4706 struct test_time_stats time_st;
4707
4708 memset(&time_st, 0, sizeof(struct test_time_stats));
4709 time_st.enq_sw_min_time = UINT64_MAX;
4710 time_st.enq_acc_min_time = UINT64_MAX;
4711 time_st.deq_min_time = UINT64_MAX;
4712
4713 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
4714 "BURST_SIZE should be <= %u", MAX_BURST);
4715
4716 rte_bbdev_info_get(ad->dev_id, &info);
4717 bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
4718
4719 op_type_str = rte_bbdev_op_type_str(op_type);
4720 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
4721
4722 printf("+ ------------------------------------------------------- +\n");
4723 printf("== test: offload latency test\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
4724 info.dev_name, burst_sz, num_to_process, op_type_str);
4725
4726 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
4727 iter = offload_latency_test_dec(op_params->mp, bufs,
4728 op_params->ref_dec_op, ad->dev_id, queue_id,
4729 num_to_process, burst_sz, &time_st);
4730 else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
4731 iter = offload_latency_test_enc(op_params->mp, bufs,
4732 op_params->ref_enc_op, ad->dev_id, queue_id,
4733 num_to_process, burst_sz, &time_st);
4734 else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
4735 iter = offload_latency_test_ldpc_enc(op_params->mp, bufs,
4736 op_params->ref_enc_op, ad->dev_id, queue_id,
4737 num_to_process, burst_sz, &time_st);
4738 else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
4739 iter = offload_latency_test_ldpc_dec(op_params->mp, bufs,
4740 op_params->ref_dec_op, ad->dev_id, queue_id,
4741 num_to_process, burst_sz, &time_st);
4742 else
4743 iter = offload_latency_test_enc(op_params->mp, bufs,
4744 op_params->ref_enc_op, ad->dev_id, queue_id,
4745 num_to_process, burst_sz, &time_st);
4746
4747 if (iter <= 0)
4748 return TEST_FAILED;
4749
4750 printf("Enqueue driver offload cost latency:\n"
4751 "\tavg: %lg cycles, %lg us\n"
4752 "\tmin: %lg cycles, %lg us\n"
4753 "\tmax: %lg cycles, %lg us\n"
4754 "Enqueue accelerator offload cost latency:\n"
4755 "\tavg: %lg cycles, %lg us\n"
4756 "\tmin: %lg cycles, %lg us\n"
4757 "\tmax: %lg cycles, %lg us\n",
4758 (double)time_st.enq_sw_total_time / (double)iter,
4759 (double)(time_st.enq_sw_total_time * 1000000) /
4760 (double)iter / (double)rte_get_tsc_hz(),
4761 (double)time_st.enq_sw_min_time,
4762 (double)(time_st.enq_sw_min_time * 1000000) /
4763 rte_get_tsc_hz(), (double)time_st.enq_sw_max_time,
4764 (double)(time_st.enq_sw_max_time * 1000000) /
4765 rte_get_tsc_hz(), (double)time_st.enq_acc_total_time /
4766 (double)iter,
4767 (double)(time_st.enq_acc_total_time * 1000000) /
4768 (double)iter / (double)rte_get_tsc_hz(),
4769 (double)time_st.enq_acc_min_time,
4770 (double)(time_st.enq_acc_min_time * 1000000) /
4771 rte_get_tsc_hz(), (double)time_st.enq_acc_max_time,
4772 (double)(time_st.enq_acc_max_time * 1000000) /
4773 rte_get_tsc_hz());
4774
4775 printf("Dequeue offload cost latency - one op:\n"
4776 "\tavg: %lg cycles, %lg us\n"
4777 "\tmin: %lg cycles, %lg us\n"
4778 "\tmax: %lg cycles, %lg us\n",
4779 (double)time_st.deq_total_time / (double)iter,
4780 (double)(time_st.deq_total_time * 1000000) /
4781 (double)iter / (double)rte_get_tsc_hz(),
4782 (double)time_st.deq_min_time,
4783 (double)(time_st.deq_min_time * 1000000) /
4784 rte_get_tsc_hz(), (double)time_st.deq_max_time,
4785 (double)(time_st.deq_max_time * 1000000) /
4786 rte_get_tsc_hz());
4787
4788 struct rte_bbdev_stats stats = {0};
4789 get_bbdev_queue_stats(ad->dev_id, queue_id, &stats);
4790 if (op_type != RTE_BBDEV_OP_LDPC_DEC) {
4791 TEST_ASSERT_SUCCESS(stats.enqueued_count != num_to_process,
4792 "Mismatch in enqueue count %10"PRIu64" %d",
4793 stats.enqueued_count, num_to_process);
4794 TEST_ASSERT_SUCCESS(stats.dequeued_count != num_to_process,
4795 "Mismatch in dequeue count %10"PRIu64" %d",
4796 stats.dequeued_count, num_to_process);
4797 }
4798 TEST_ASSERT_SUCCESS(stats.enqueue_err_count != 0,
4799 "Enqueue count Error %10"PRIu64"",
4800 stats.enqueue_err_count);
4801 TEST_ASSERT_SUCCESS(stats.dequeue_err_count != 0,
4802 "Dequeue count Error (%10"PRIu64"",
4803 stats.dequeue_err_count);
4804
4805 return TEST_SUCCESS;
4806 #endif
4807 }
4808
4809 #ifdef RTE_BBDEV_OFFLOAD_COST
4810 static int
offload_latency_empty_q_test_dec(uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,uint64_t * deq_total_time,uint64_t * deq_min_time,uint64_t * deq_max_time,const enum rte_bbdev_op_type op_type)4811 offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
4812 const uint16_t num_to_process, uint16_t burst_sz,
4813 uint64_t *deq_total_time, uint64_t *deq_min_time,
4814 uint64_t *deq_max_time, const enum rte_bbdev_op_type op_type)
4815 {
4816 int i, deq_total;
4817 struct rte_bbdev_dec_op *ops[MAX_BURST];
4818 uint64_t deq_start_time, deq_last_time;
4819
4820 /* Test deq offload latency from an empty queue */
4821
4822 for (i = 0, deq_total = 0; deq_total < num_to_process;
4823 ++i, deq_total += burst_sz) {
4824 deq_start_time = rte_rdtsc_precise();
4825
4826 if (unlikely(num_to_process - deq_total < burst_sz))
4827 burst_sz = num_to_process - deq_total;
4828 if (op_type == RTE_BBDEV_OP_LDPC_DEC)
4829 rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id, ops,
4830 burst_sz);
4831 else
4832 rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops,
4833 burst_sz);
4834
4835 deq_last_time = rte_rdtsc_precise() - deq_start_time;
4836 *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
4837 *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
4838 *deq_total_time += deq_last_time;
4839 }
4840
4841 return i;
4842 }
4843
4844 static int
offload_latency_empty_q_test_enc(uint16_t dev_id,uint16_t queue_id,const uint16_t num_to_process,uint16_t burst_sz,uint64_t * deq_total_time,uint64_t * deq_min_time,uint64_t * deq_max_time,const enum rte_bbdev_op_type op_type)4845 offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
4846 const uint16_t num_to_process, uint16_t burst_sz,
4847 uint64_t *deq_total_time, uint64_t *deq_min_time,
4848 uint64_t *deq_max_time, const enum rte_bbdev_op_type op_type)
4849 {
4850 int i, deq_total;
4851 struct rte_bbdev_enc_op *ops[MAX_BURST];
4852 uint64_t deq_start_time, deq_last_time;
4853
4854 /* Test deq offload latency from an empty queue */
4855 for (i = 0, deq_total = 0; deq_total < num_to_process;
4856 ++i, deq_total += burst_sz) {
4857 deq_start_time = rte_rdtsc_precise();
4858
4859 if (unlikely(num_to_process - deq_total < burst_sz))
4860 burst_sz = num_to_process - deq_total;
4861 if (op_type == RTE_BBDEV_OP_LDPC_ENC)
4862 rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id, ops,
4863 burst_sz);
4864 else
4865 rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops,
4866 burst_sz);
4867
4868 deq_last_time = rte_rdtsc_precise() - deq_start_time;
4869 *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
4870 *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
4871 *deq_total_time += deq_last_time;
4872 }
4873
4874 return i;
4875 }
4876
4877 #endif
4878
4879 static int
offload_latency_empty_q_test(struct active_device * ad,struct test_op_params * op_params)4880 offload_latency_empty_q_test(struct active_device *ad,
4881 struct test_op_params *op_params)
4882 {
4883 #ifndef RTE_BBDEV_OFFLOAD_COST
4884 RTE_SET_USED(ad);
4885 RTE_SET_USED(op_params);
4886 printf("Offload latency empty dequeue test is disabled.\n");
4887 printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
4888 return TEST_SKIPPED;
4889 #else
4890 int iter;
4891 uint64_t deq_total_time, deq_min_time, deq_max_time;
4892 uint16_t burst_sz = op_params->burst_sz;
4893 const uint16_t num_to_process = op_params->num_to_process;
4894 const enum rte_bbdev_op_type op_type = test_vector.op_type;
4895 const uint16_t queue_id = ad->queue_ids[0];
4896 struct rte_bbdev_info info;
4897 const char *op_type_str;
4898
4899 deq_total_time = deq_max_time = 0;
4900 deq_min_time = UINT64_MAX;
4901
4902 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
4903 "BURST_SIZE should be <= %u", MAX_BURST);
4904
4905 rte_bbdev_info_get(ad->dev_id, &info);
4906
4907 op_type_str = rte_bbdev_op_type_str(op_type);
4908 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
4909
4910 printf("+ ------------------------------------------------------- +\n");
4911 printf("== test: offload latency empty dequeue\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
4912 info.dev_name, burst_sz, num_to_process, op_type_str);
4913
4914 if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
4915 op_type == RTE_BBDEV_OP_LDPC_DEC)
4916 iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
4917 num_to_process, burst_sz, &deq_total_time,
4918 &deq_min_time, &deq_max_time, op_type);
4919 else
4920 iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
4921 num_to_process, burst_sz, &deq_total_time,
4922 &deq_min_time, &deq_max_time, op_type);
4923
4924 if (iter <= 0)
4925 return TEST_FAILED;
4926
4927 printf("Empty dequeue offload:\n"
4928 "\tavg: %lg cycles, %lg us\n"
4929 "\tmin: %lg cycles, %lg us\n"
4930 "\tmax: %lg cycles, %lg us\n",
4931 (double)deq_total_time / (double)iter,
4932 (double)(deq_total_time * 1000000) / (double)iter /
4933 (double)rte_get_tsc_hz(), (double)deq_min_time,
4934 (double)(deq_min_time * 1000000) / rte_get_tsc_hz(),
4935 (double)deq_max_time, (double)(deq_max_time * 1000000) /
4936 rte_get_tsc_hz());
4937
4938 return TEST_SUCCESS;
4939 #endif
4940 }
4941
4942 static int
bler_tc(void)4943 bler_tc(void)
4944 {
4945 return run_test_case(bler_test);
4946 }
4947
4948 static int
throughput_tc(void)4949 throughput_tc(void)
4950 {
4951 return run_test_case(throughput_test);
4952 }
4953
4954 static int
offload_cost_tc(void)4955 offload_cost_tc(void)
4956 {
4957 return run_test_case(offload_cost_test);
4958 }
4959
4960 static int
offload_latency_empty_q_tc(void)4961 offload_latency_empty_q_tc(void)
4962 {
4963 return run_test_case(offload_latency_empty_q_test);
4964 }
4965
4966 static int
latency_tc(void)4967 latency_tc(void)
4968 {
4969 return run_test_case(latency_test);
4970 }
4971
4972 static int
validation_tc(void)4973 validation_tc(void)
4974 {
4975 return run_test_case(validation_test);
4976 }
4977
4978 static int
interrupt_tc(void)4979 interrupt_tc(void)
4980 {
4981 return run_test_case(throughput_test);
4982 }
4983
4984 static struct unit_test_suite bbdev_bler_testsuite = {
4985 .suite_name = "BBdev BLER Tests",
4986 .setup = testsuite_setup,
4987 .teardown = testsuite_teardown,
4988 .unit_test_cases = {
4989 TEST_CASE_ST(ut_setup, ut_teardown, bler_tc),
4990 TEST_CASES_END() /**< NULL terminate unit test array */
4991 }
4992 };
4993
4994 static struct unit_test_suite bbdev_throughput_testsuite = {
4995 .suite_name = "BBdev Throughput Tests",
4996 .setup = testsuite_setup,
4997 .teardown = testsuite_teardown,
4998 .unit_test_cases = {
4999 TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
5000 TEST_CASES_END() /**< NULL terminate unit test array */
5001 }
5002 };
5003
5004 static struct unit_test_suite bbdev_validation_testsuite = {
5005 .suite_name = "BBdev Validation Tests",
5006 .setup = testsuite_setup,
5007 .teardown = testsuite_teardown,
5008 .unit_test_cases = {
5009 TEST_CASE_ST(ut_setup, ut_teardown, validation_tc),
5010 TEST_CASES_END() /**< NULL terminate unit test array */
5011 }
5012 };
5013
5014 static struct unit_test_suite bbdev_latency_testsuite = {
5015 .suite_name = "BBdev Latency Tests",
5016 .setup = testsuite_setup,
5017 .teardown = testsuite_teardown,
5018 .unit_test_cases = {
5019 TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
5020 TEST_CASES_END() /**< NULL terminate unit test array */
5021 }
5022 };
5023
5024 static struct unit_test_suite bbdev_offload_cost_testsuite = {
5025 .suite_name = "BBdev Offload Cost Tests",
5026 .setup = testsuite_setup,
5027 .teardown = testsuite_teardown,
5028 .unit_test_cases = {
5029 TEST_CASE_ST(ut_setup, ut_teardown, offload_cost_tc),
5030 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
5031 TEST_CASES_END() /**< NULL terminate unit test array */
5032 }
5033 };
5034
5035 static struct unit_test_suite bbdev_interrupt_testsuite = {
5036 .suite_name = "BBdev Interrupt Tests",
5037 .setup = interrupt_testsuite_setup,
5038 .teardown = testsuite_teardown,
5039 .unit_test_cases = {
5040 TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
5041 TEST_CASES_END() /**< NULL terminate unit test array */
5042 }
5043 };
5044
5045 REGISTER_TEST_COMMAND(bler, bbdev_bler_testsuite);
5046 REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
5047 REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
5048 REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
5049 REGISTER_TEST_COMMAND(offload, bbdev_offload_cost_testsuite);
5050 REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);
5051