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