1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2021 Intel Corporation
4 #ifndef __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
5 #define __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
11 #include <rte_byteorder.h>
12 #include <rte_common.h>
13 #include <rte_cycles.h>
14 #include <rte_prefetch.h>
15 #include <rte_meter.h>
17 #include <rte_swx_table_selector.h>
18 #include <rte_swx_table_learner.h>
19 #include <rte_swx_pipeline.h>
20 #include <rte_swx_ctl.h>
27 #define TRACE(...) printf(__VA_ARGS__)
35 #define ntoh64(x) rte_be_to_cpu_64(x)
36 #define hton64(x) rte_cpu_to_be_64(x)
42 char name[RTE_SWX_NAME_SIZE];
49 TAILQ_ENTRY(struct_type) node;
50 char name[RTE_SWX_NAME_SIZE];
58 TAILQ_HEAD(struct_type_tailq, struct_type);
64 TAILQ_ENTRY(port_in_type) node;
65 char name[RTE_SWX_NAME_SIZE];
66 struct rte_swx_port_in_ops ops;
69 TAILQ_HEAD(port_in_type_tailq, port_in_type);
72 TAILQ_ENTRY(port_in) node;
73 struct port_in_type *type;
78 TAILQ_HEAD(port_in_tailq, port_in);
80 struct port_in_runtime {
81 rte_swx_port_in_pkt_rx_t pkt_rx;
88 struct port_out_type {
89 TAILQ_ENTRY(port_out_type) node;
90 char name[RTE_SWX_NAME_SIZE];
91 struct rte_swx_port_out_ops ops;
94 TAILQ_HEAD(port_out_type_tailq, port_out_type);
97 TAILQ_ENTRY(port_out) node;
98 struct port_out_type *type;
103 TAILQ_HEAD(port_out_tailq, port_out);
105 struct port_out_runtime {
106 rte_swx_port_out_pkt_tx_t pkt_tx;
107 rte_swx_port_out_flush_t flush;
114 struct extern_type_member_func {
115 TAILQ_ENTRY(extern_type_member_func) node;
116 char name[RTE_SWX_NAME_SIZE];
117 rte_swx_extern_type_member_func_t func;
121 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
124 TAILQ_ENTRY(extern_type) node;
125 char name[RTE_SWX_NAME_SIZE];
126 struct struct_type *mailbox_struct_type;
127 rte_swx_extern_type_constructor_t constructor;
128 rte_swx_extern_type_destructor_t destructor;
129 struct extern_type_member_func_tailq funcs;
133 TAILQ_HEAD(extern_type_tailq, extern_type);
136 TAILQ_ENTRY(extern_obj) node;
137 char name[RTE_SWX_NAME_SIZE];
138 struct extern_type *type;
144 TAILQ_HEAD(extern_obj_tailq, extern_obj);
146 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
147 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
150 struct extern_obj_runtime {
153 rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
160 TAILQ_ENTRY(extern_func) node;
161 char name[RTE_SWX_NAME_SIZE];
162 struct struct_type *mailbox_struct_type;
163 rte_swx_extern_func_t func;
168 TAILQ_HEAD(extern_func_tailq, extern_func);
170 struct extern_func_runtime {
172 rte_swx_extern_func_t func;
179 TAILQ_ENTRY(header) node;
180 char name[RTE_SWX_NAME_SIZE];
181 struct struct_type *st;
186 TAILQ_HEAD(header_tailq, header);
188 struct header_runtime {
193 struct header_out_runtime {
203 /* Packet headers are always in Network Byte Order (NBO), i.e. big endian.
204 * Packet meta-data fields are always assumed to be in Host Byte Order (HBO).
205 * Table entry fields can be in either NBO or HBO; they are assumed to be in HBO
206 * when transferred to packet meta-data and in NBO when transferred to packet
210 /* Notation conventions:
211 * -Header field: H = h.header.field (dst/src)
212 * -Meta-data field: M = m.field (dst/src)
213 * -Extern object mailbox field: E = e.field (dst/src)
214 * -Extern function mailbox field: F = f.field (dst/src)
215 * -Table action data field: T = t.field (src only)
216 * -Immediate value: I = 32-bit unsigned value (src only)
219 enum instruction_type {
226 INSTR_TX, /* port_out = M */
227 INSTR_TX_I, /* port_out = I */
230 /* extract h.header */
240 /* extract h.header m.last_field_size */
243 /* lookahead h.header */
257 /* validate h.header */
260 /* invalidate h.header */
261 INSTR_HDR_INVALIDATE,
265 * dst = HMEF, src = HMEFTI
267 INSTR_MOV, /* dst = MEF, src = MEFT */
268 INSTR_MOV_MH, /* dst = MEF, src = H */
269 INSTR_MOV_HM, /* dst = H, src = MEFT */
270 INSTR_MOV_HH, /* dst = H, src = H */
271 INSTR_MOV_I, /* dst = HMEF, src = I */
273 /* dma h.header t.field
274 * memcpy(h.header, t.field, sizeof(h.header))
287 * dst = HMEF, src = HMEFTI
289 INSTR_ALU_ADD, /* dst = MEF, src = MEF */
290 INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
291 INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
292 INSTR_ALU_ADD_HH, /* dst = H, src = H */
293 INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
294 INSTR_ALU_ADD_HI, /* dst = H, src = I */
298 * dst = HMEF, src = HMEFTI
300 INSTR_ALU_SUB, /* dst = MEF, src = MEF */
301 INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
302 INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
303 INSTR_ALU_SUB_HH, /* dst = H, src = H */
304 INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
305 INSTR_ALU_SUB_HI, /* dst = H, src = I */
308 * dst = dst '+ src[0:1] '+ src[2:3] '+ ...
309 * dst = H, src = {H, h.header}, '+ = 1's complement addition operator
311 INSTR_ALU_CKADD_FIELD, /* src = H */
312 INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 bytes. */
313 INSTR_ALU_CKADD_STRUCT, /* src = h.header, with sizeof(header) any 4-byte multiple. */
317 * dst = H, src = H, '- = 1's complement subtraction operator
319 INSTR_ALU_CKSUB_FIELD,
323 * dst = HMEF, src = HMEFTI
325 INSTR_ALU_AND, /* dst = MEF, src = MEFT */
326 INSTR_ALU_AND_MH, /* dst = MEF, src = H */
327 INSTR_ALU_AND_HM, /* dst = H, src = MEFT */
328 INSTR_ALU_AND_HH, /* dst = H, src = H */
329 INSTR_ALU_AND_I, /* dst = HMEF, src = I */
333 * dst = HMEF, src = HMEFTI
335 INSTR_ALU_OR, /* dst = MEF, src = MEFT */
336 INSTR_ALU_OR_MH, /* dst = MEF, src = H */
337 INSTR_ALU_OR_HM, /* dst = H, src = MEFT */
338 INSTR_ALU_OR_HH, /* dst = H, src = H */
339 INSTR_ALU_OR_I, /* dst = HMEF, src = I */
343 * dst = HMEF, src = HMEFTI
345 INSTR_ALU_XOR, /* dst = MEF, src = MEFT */
346 INSTR_ALU_XOR_MH, /* dst = MEF, src = H */
347 INSTR_ALU_XOR_HM, /* dst = H, src = MEFT */
348 INSTR_ALU_XOR_HH, /* dst = H, src = H */
349 INSTR_ALU_XOR_I, /* dst = HMEF, src = I */
353 * dst = HMEF, src = HMEFTI
355 INSTR_ALU_SHL, /* dst = MEF, src = MEF */
356 INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
357 INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
358 INSTR_ALU_SHL_HH, /* dst = H, src = H */
359 INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
360 INSTR_ALU_SHL_HI, /* dst = H, src = I */
364 * dst = HMEF, src = HMEFTI
366 INSTR_ALU_SHR, /* dst = MEF, src = MEF */
367 INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
368 INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
369 INSTR_ALU_SHR_HH, /* dst = H, src = H */
370 INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
371 INSTR_ALU_SHR_HI, /* dst = H, src = I */
373 /* regprefetch REGARRAY index
374 * prefetch REGARRAY[index]
377 INSTR_REGPREFETCH_RH, /* index = H */
378 INSTR_REGPREFETCH_RM, /* index = MEFT */
379 INSTR_REGPREFETCH_RI, /* index = I */
381 /* regrd dst REGARRAY index
382 * dst = REGARRAY[index]
383 * dst = HMEF, index = HMEFTI
385 INSTR_REGRD_HRH, /* dst = H, index = H */
386 INSTR_REGRD_HRM, /* dst = H, index = MEFT */
387 INSTR_REGRD_HRI, /* dst = H, index = I */
388 INSTR_REGRD_MRH, /* dst = MEF, index = H */
389 INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
390 INSTR_REGRD_MRI, /* dst = MEF, index = I */
392 /* regwr REGARRAY index src
393 * REGARRAY[index] = src
394 * index = HMEFTI, src = HMEFTI
396 INSTR_REGWR_RHH, /* index = H, src = H */
397 INSTR_REGWR_RHM, /* index = H, src = MEFT */
398 INSTR_REGWR_RHI, /* index = H, src = I */
399 INSTR_REGWR_RMH, /* index = MEFT, src = H */
400 INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
401 INSTR_REGWR_RMI, /* index = MEFT, src = I */
402 INSTR_REGWR_RIH, /* index = I, src = H */
403 INSTR_REGWR_RIM, /* index = I, src = MEFT */
404 INSTR_REGWR_RII, /* index = I, src = I */
406 /* regadd REGARRAY index src
407 * REGARRAY[index] += src
408 * index = HMEFTI, src = HMEFTI
410 INSTR_REGADD_RHH, /* index = H, src = H */
411 INSTR_REGADD_RHM, /* index = H, src = MEFT */
412 INSTR_REGADD_RHI, /* index = H, src = I */
413 INSTR_REGADD_RMH, /* index = MEFT, src = H */
414 INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
415 INSTR_REGADD_RMI, /* index = MEFT, src = I */
416 INSTR_REGADD_RIH, /* index = I, src = H */
417 INSTR_REGADD_RIM, /* index = I, src = MEFT */
418 INSTR_REGADD_RII, /* index = I, src = I */
420 /* metprefetch METARRAY index
421 * prefetch METARRAY[index]
424 INSTR_METPREFETCH_H, /* index = H */
425 INSTR_METPREFETCH_M, /* index = MEFT */
426 INSTR_METPREFETCH_I, /* index = I */
428 /* meter METARRAY index length color_in color_out
429 * color_out = meter(METARRAY[index], length, color_in)
430 * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
432 INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
433 INSTR_METER_HHI, /* index = H, length = H, color_in = I */
434 INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
435 INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
436 INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
437 INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
438 INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
439 INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
440 INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
441 INSTR_METER_IHI, /* index = I, length = H, color_in = I */
442 INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
443 INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
452 /* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
456 INSTR_LEARNER_FORGET,
458 /* extern e.obj.func */
469 /* jmpv LABEL h.header
470 * Jump if header is valid
474 /* jmpnv LABEL h.header
475 * Jump if header is invalid
480 * Jump if table lookup hit
485 * Jump if table lookup miss
492 INSTR_JMP_ACTION_HIT,
494 /* jmpna LABEL ACTION
495 * Jump if action not run
497 INSTR_JMP_ACTION_MISS,
500 * Jump if a is equal to b
501 * a = HMEFT, b = HMEFTI
503 INSTR_JMP_EQ, /* a = MEFT, b = MEFT */
504 INSTR_JMP_EQ_MH, /* a = MEFT, b = H */
505 INSTR_JMP_EQ_HM, /* a = H, b = MEFT */
506 INSTR_JMP_EQ_HH, /* a = H, b = H */
507 INSTR_JMP_EQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
510 * Jump if a is not equal to b
511 * a = HMEFT, b = HMEFTI
513 INSTR_JMP_NEQ, /* a = MEFT, b = MEFT */
514 INSTR_JMP_NEQ_MH, /* a = MEFT, b = H */
515 INSTR_JMP_NEQ_HM, /* a = H, b = MEFT */
516 INSTR_JMP_NEQ_HH, /* a = H, b = H */
517 INSTR_JMP_NEQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
520 * Jump if a is less than b
521 * a = HMEFT, b = HMEFTI
523 INSTR_JMP_LT, /* a = MEFT, b = MEFT */
524 INSTR_JMP_LT_MH, /* a = MEFT, b = H */
525 INSTR_JMP_LT_HM, /* a = H, b = MEFT */
526 INSTR_JMP_LT_HH, /* a = H, b = H */
527 INSTR_JMP_LT_MI, /* a = MEFT, b = I */
528 INSTR_JMP_LT_HI, /* a = H, b = I */
531 * Jump if a is greater than b
532 * a = HMEFT, b = HMEFTI
534 INSTR_JMP_GT, /* a = MEFT, b = MEFT */
535 INSTR_JMP_GT_MH, /* a = MEFT, b = H */
536 INSTR_JMP_GT_HM, /* a = H, b = MEFT */
537 INSTR_JMP_GT_HH, /* a = H, b = H */
538 INSTR_JMP_GT_MI, /* a = MEFT, b = I */
539 INSTR_JMP_GT_HI, /* a = H, b = I */
546 /* Start of custom instructions. */
550 struct instr_operand {
571 uint8_t header_id[8];
572 uint8_t struct_id[8];
577 struct instr_hdr_validity {
590 struct instr_extern_obj {
595 struct instr_extern_func {
599 struct instr_dst_src {
600 struct instr_operand dst;
602 struct instr_operand src;
607 struct instr_regarray {
612 struct instr_operand idx;
617 struct instr_operand dstsrc;
627 struct instr_operand idx;
631 struct instr_operand length;
634 struct instr_operand color_in;
635 uint32_t color_in_val;
638 struct instr_operand color_out;
643 uint8_t header_id[8];
644 uint8_t struct_id[8];
655 struct instruction *ip;
658 struct instr_operand a;
664 struct instr_operand b;
670 enum instruction_type type;
673 struct instr_hdr_validity valid;
674 struct instr_dst_src mov;
675 struct instr_regarray regarray;
676 struct instr_meter meter;
677 struct instr_dma dma;
678 struct instr_dst_src alu;
679 struct instr_table table;
680 struct instr_learn learn;
681 struct instr_extern_obj ext_obj;
682 struct instr_extern_func ext_func;
683 struct instr_jmp jmp;
687 struct instruction_data {
688 char label[RTE_SWX_NAME_SIZE];
689 char jmp_label[RTE_SWX_NAME_SIZE];
690 uint32_t n_users; /* user = jmp instruction to this instruction. */
694 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
700 (*action_func_t)(struct rte_swx_pipeline *p);
703 TAILQ_ENTRY(action) node;
704 char name[RTE_SWX_NAME_SIZE];
705 struct struct_type *st;
706 int *args_endianness; /* 0 = Host Byte Order (HBO); 1 = Network Byte Order (NBO). */
707 struct instruction *instructions;
708 struct instruction_data *instruction_data;
709 uint32_t n_instructions;
713 TAILQ_HEAD(action_tailq, action);
719 TAILQ_ENTRY(table_type) node;
720 char name[RTE_SWX_NAME_SIZE];
721 enum rte_swx_table_match_type match_type;
722 struct rte_swx_table_ops ops;
725 TAILQ_HEAD(table_type_tailq, table_type);
728 enum rte_swx_table_match_type match_type;
733 TAILQ_ENTRY(table) node;
734 char name[RTE_SWX_NAME_SIZE];
735 char args[RTE_SWX_NAME_SIZE];
736 struct table_type *type; /* NULL when n_fields == 0. */
739 struct match_field *fields;
741 struct header *header; /* Only valid when n_fields > 0. */
744 struct action **actions;
745 struct action *default_action;
746 uint8_t *default_action_data;
748 int default_action_is_const;
749 uint32_t action_data_size_max;
750 int *action_is_for_table_entries;
751 int *action_is_for_default_entry;
757 TAILQ_HEAD(table_tailq, table);
759 struct table_runtime {
760 rte_swx_table_lookup_t func;
765 struct table_statistics {
766 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
767 uint64_t *n_pkts_action;
774 TAILQ_ENTRY(selector) node;
775 char name[RTE_SWX_NAME_SIZE];
777 struct field *group_id_field;
778 struct field **selector_fields;
779 uint32_t n_selector_fields;
780 struct header *selector_header;
781 struct field *member_id_field;
783 uint32_t n_groups_max;
784 uint32_t n_members_per_group_max;
789 TAILQ_HEAD(selector_tailq, selector);
791 struct selector_runtime {
793 uint8_t **group_id_buffer;
794 uint8_t **selector_buffer;
795 uint8_t **member_id_buffer;
798 struct selector_statistics {
806 TAILQ_ENTRY(learner) node;
807 char name[RTE_SWX_NAME_SIZE];
810 struct field **fields;
812 struct header *header;
815 struct action **actions;
816 struct action *default_action;
817 uint8_t *default_action_data;
819 int default_action_is_const;
820 uint32_t action_data_size_max;
821 int *action_is_for_table_entries;
822 int *action_is_for_default_entry;
829 TAILQ_HEAD(learner_tailq, learner);
831 struct learner_runtime {
836 struct learner_statistics {
837 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
838 uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
839 uint64_t n_pkts_forget;
840 uint64_t *n_pkts_action;
847 TAILQ_ENTRY(regarray) node;
848 char name[RTE_SWX_NAME_SIZE];
854 TAILQ_HEAD(regarray_tailq, regarray);
856 struct regarray_runtime {
864 struct meter_profile {
865 TAILQ_ENTRY(meter_profile) node;
866 char name[RTE_SWX_NAME_SIZE];
867 struct rte_meter_trtcm_params params;
868 struct rte_meter_trtcm_profile profile;
872 TAILQ_HEAD(meter_profile_tailq, meter_profile);
875 TAILQ_ENTRY(metarray) node;
876 char name[RTE_SWX_NAME_SIZE];
881 TAILQ_HEAD(metarray_tailq, metarray);
884 struct rte_meter_trtcm m;
885 struct meter_profile *profile;
886 enum rte_color color_mask;
889 uint64_t n_pkts[RTE_COLORS];
890 uint64_t n_bytes[RTE_COLORS];
893 struct metarray_runtime {
894 struct meter *metarray;
903 struct rte_swx_pkt pkt;
909 /* Packet headers. */
910 struct header_runtime *headers; /* Extracted or generated headers. */
911 struct header_out_runtime *headers_out; /* Emitted headers. */
912 uint8_t *header_storage;
913 uint8_t *header_out_storage;
914 uint64_t valid_headers;
915 uint32_t n_headers_out;
917 /* Packet meta-data. */
921 struct table_runtime *tables;
922 struct selector_runtime *selectors;
923 struct learner_runtime *learners;
924 struct rte_swx_table_state *table_state;
926 int hit; /* 0 = Miss, 1 = Hit. */
930 /* Extern objects and functions. */
931 struct extern_obj_runtime *extern_objs;
932 struct extern_func_runtime *extern_funcs;
935 struct instruction *ip;
936 struct instruction *ret;
939 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
940 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
941 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
943 #define HEADER_VALID(thread, header_id) \
944 MASK64_BIT_GET((thread)->valid_headers, header_id)
946 static inline uint64_t
947 instr_operand_hbo(struct thread *t, const struct instr_operand *x)
949 uint8_t *x_struct = t->structs[x->struct_id];
950 uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
951 uint64_t x64 = *x64_ptr;
952 uint64_t x64_mask = UINT64_MAX >> (64 - x->n_bits);
954 return x64 & x64_mask;
957 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
959 static inline uint64_t
960 instr_operand_nbo(struct thread *t, const struct instr_operand *x)
962 uint8_t *x_struct = t->structs[x->struct_id];
963 uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
964 uint64_t x64 = *x64_ptr;
966 return ntoh64(x64) >> (64 - x->n_bits);
971 #define instr_operand_nbo instr_operand_hbo
975 #define ALU(thread, ip, operator) \
977 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
978 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
979 uint64_t dst64 = *dst64_ptr; \
980 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
981 uint64_t dst = dst64 & dst64_mask; \
983 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
984 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
985 uint64_t src64 = *src64_ptr; \
986 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
987 uint64_t src = src64 & src64_mask; \
989 uint64_t result = dst operator src; \
991 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
994 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
996 #define ALU_MH(thread, ip, operator) \
998 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
999 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1000 uint64_t dst64 = *dst64_ptr; \
1001 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1002 uint64_t dst = dst64 & dst64_mask; \
1004 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1005 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1006 uint64_t src64 = *src64_ptr; \
1007 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1009 uint64_t result = dst operator src; \
1011 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1014 #define ALU_HM(thread, ip, operator) \
1016 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1017 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1018 uint64_t dst64 = *dst64_ptr; \
1019 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1020 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1022 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1023 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1024 uint64_t src64 = *src64_ptr; \
1025 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1026 uint64_t src = src64 & src64_mask; \
1028 uint64_t result = dst operator src; \
1029 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1031 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1034 #define ALU_HM_FAST(thread, ip, operator) \
1036 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1037 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1038 uint64_t dst64 = *dst64_ptr; \
1039 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1040 uint64_t dst = dst64 & dst64_mask; \
1042 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1043 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1044 uint64_t src64 = *src64_ptr; \
1045 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1046 uint64_t src = hton64(src64 & src64_mask) >> (64 - (ip)->alu.dst.n_bits); \
1048 uint64_t result = dst operator src; \
1050 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1053 #define ALU_HH(thread, ip, operator) \
1055 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1056 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1057 uint64_t dst64 = *dst64_ptr; \
1058 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1059 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1061 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1062 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1063 uint64_t src64 = *src64_ptr; \
1064 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1066 uint64_t result = dst operator src; \
1067 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1069 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1072 #define ALU_HH_FAST(thread, ip, operator) \
1074 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1075 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1076 uint64_t dst64 = *dst64_ptr; \
1077 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1078 uint64_t dst = dst64 & dst64_mask; \
1080 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1081 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1082 uint64_t src64 = *src64_ptr; \
1083 uint64_t src = (src64 << (64 - (ip)->alu.src.n_bits)) >> (64 - (ip)->alu.dst.n_bits); \
1085 uint64_t result = dst operator src; \
1087 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1094 #define ALU_HM_FAST ALU
1096 #define ALU_HH_FAST ALU
1100 #define ALU_I(thread, ip, operator) \
1102 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1103 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1104 uint64_t dst64 = *dst64_ptr; \
1105 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1106 uint64_t dst = dst64 & dst64_mask; \
1108 uint64_t src = (ip)->alu.src_val; \
1110 uint64_t result = dst operator src; \
1112 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1115 #define ALU_MI ALU_I
1117 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1119 #define ALU_HI(thread, ip, operator) \
1121 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1122 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1123 uint64_t dst64 = *dst64_ptr; \
1124 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1125 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1127 uint64_t src = (ip)->alu.src_val; \
1129 uint64_t result = dst operator src; \
1130 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1132 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1137 #define ALU_HI ALU_I
1141 #define MOV(thread, ip) \
1143 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1144 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1145 uint64_t dst64 = *dst64_ptr; \
1146 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1148 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1149 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1150 uint64_t src64 = *src64_ptr; \
1151 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1152 uint64_t src = src64 & src64_mask; \
1154 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1157 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1159 #define MOV_MH(thread, ip) \
1161 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1162 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1163 uint64_t dst64 = *dst64_ptr; \
1164 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1166 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1167 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1168 uint64_t src64 = *src64_ptr; \
1169 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1171 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1174 #define MOV_HM(thread, ip) \
1176 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1177 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1178 uint64_t dst64 = *dst64_ptr; \
1179 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1181 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1182 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1183 uint64_t src64 = *src64_ptr; \
1184 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1185 uint64_t src = src64 & src64_mask; \
1187 src = hton64(src) >> (64 - (ip)->mov.dst.n_bits); \
1188 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1191 #define MOV_HH(thread, ip) \
1193 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1194 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1195 uint64_t dst64 = *dst64_ptr; \
1196 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1198 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1199 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1200 uint64_t src64 = *src64_ptr; \
1202 uint64_t src = src64 << (64 - (ip)->mov.src.n_bits); \
1203 src = src >> (64 - (ip)->mov.dst.n_bits); \
1204 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1215 #define MOV_I(thread, ip) \
1217 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1218 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1219 uint64_t dst64 = *dst64_ptr; \
1220 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1222 uint64_t src = (ip)->mov.src_val; \
1224 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1227 #define JMP_CMP(thread, ip, operator) \
1229 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1230 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1231 uint64_t a64 = *a64_ptr; \
1232 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1233 uint64_t a = a64 & a64_mask; \
1235 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1236 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1237 uint64_t b64 = *b64_ptr; \
1238 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1239 uint64_t b = b64 & b64_mask; \
1241 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1244 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1246 #define JMP_CMP_MH(thread, ip, operator) \
1248 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1249 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1250 uint64_t a64 = *a64_ptr; \
1251 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1252 uint64_t a = a64 & a64_mask; \
1254 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1255 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1256 uint64_t b64 = *b64_ptr; \
1257 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1259 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1262 #define JMP_CMP_HM(thread, ip, operator) \
1264 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1265 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1266 uint64_t a64 = *a64_ptr; \
1267 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1269 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1270 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1271 uint64_t b64 = *b64_ptr; \
1272 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1273 uint64_t b = b64 & b64_mask; \
1275 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1278 #define JMP_CMP_HH(thread, ip, operator) \
1280 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1281 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1282 uint64_t a64 = *a64_ptr; \
1283 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1285 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1286 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1287 uint64_t b64 = *b64_ptr; \
1288 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1290 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1293 #define JMP_CMP_HH_FAST(thread, ip, operator) \
1295 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1296 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1297 uint64_t a64 = *a64_ptr; \
1298 uint64_t a = a64 << (64 - (ip)->jmp.a.n_bits); \
1300 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1301 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1302 uint64_t b64 = *b64_ptr; \
1303 uint64_t b = b64 << (64 - (ip)->jmp.b.n_bits); \
1305 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1310 #define JMP_CMP_MH JMP_CMP
1311 #define JMP_CMP_HM JMP_CMP
1312 #define JMP_CMP_HH JMP_CMP
1313 #define JMP_CMP_HH_FAST JMP_CMP
1317 #define JMP_CMP_I(thread, ip, operator) \
1319 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1320 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1321 uint64_t a64 = *a64_ptr; \
1322 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1323 uint64_t a = a64 & a64_mask; \
1325 uint64_t b = (ip)->jmp.b_val; \
1327 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1330 #define JMP_CMP_MI JMP_CMP_I
1332 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1334 #define JMP_CMP_HI(thread, ip, operator) \
1336 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1337 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1338 uint64_t a64 = *a64_ptr; \
1339 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1341 uint64_t b = (ip)->jmp.b_val; \
1343 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1348 #define JMP_CMP_HI JMP_CMP_I
1352 #define METADATA_READ(thread, offset, n_bits) \
1354 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1355 uint64_t m64 = *m64_ptr; \
1356 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1360 #define METADATA_WRITE(thread, offset, n_bits, value) \
1362 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1363 uint64_t m64 = *m64_ptr; \
1364 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1366 uint64_t m_new = value; \
1368 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1371 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1372 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1375 #ifndef RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX
1376 #define RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX 256
1379 struct rte_swx_pipeline {
1380 struct struct_type_tailq struct_types;
1381 struct port_in_type_tailq port_in_types;
1382 struct port_in_tailq ports_in;
1383 struct port_out_type_tailq port_out_types;
1384 struct port_out_tailq ports_out;
1385 struct extern_type_tailq extern_types;
1386 struct extern_obj_tailq extern_objs;
1387 struct extern_func_tailq extern_funcs;
1388 struct header_tailq headers;
1389 struct struct_type *metadata_st;
1390 uint32_t metadata_struct_id;
1391 struct action_tailq actions;
1392 struct table_type_tailq table_types;
1393 struct table_tailq tables;
1394 struct selector_tailq selectors;
1395 struct learner_tailq learners;
1396 struct regarray_tailq regarrays;
1397 struct meter_profile_tailq meter_profiles;
1398 struct metarray_tailq metarrays;
1400 struct port_in_runtime *in;
1401 struct port_out_runtime *out;
1402 struct instruction **action_instructions;
1403 action_func_t *action_funcs;
1404 struct rte_swx_table_state *table_state;
1405 struct table_statistics *table_stats;
1406 struct selector_statistics *selector_stats;
1407 struct learner_statistics *learner_stats;
1408 struct regarray_runtime *regarray_runtime;
1409 struct metarray_runtime *metarray_runtime;
1410 struct instruction *instructions;
1411 struct instruction_data *instruction_data;
1412 instr_exec_t *instruction_table;
1413 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1417 uint32_t n_ports_in;
1418 uint32_t n_ports_out;
1419 uint32_t n_extern_objs;
1420 uint32_t n_extern_funcs;
1423 uint32_t n_selectors;
1424 uint32_t n_learners;
1425 uint32_t n_regarrays;
1426 uint32_t n_metarrays;
1430 uint32_t n_instructions;
1439 pipeline_port_inc(struct rte_swx_pipeline *p)
1441 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
1445 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
1447 t->ip = p->instructions;
1451 thread_ip_set(struct thread *t, struct instruction *ip)
1457 thread_ip_action_call(struct rte_swx_pipeline *p,
1462 t->ip = p->action_instructions[action_id];
1466 thread_ip_inc(struct rte_swx_pipeline *p);
1469 thread_ip_inc(struct rte_swx_pipeline *p)
1471 struct thread *t = &p->threads[p->thread_id];
1477 thread_ip_inc_cond(struct thread *t, int cond)
1483 thread_yield(struct rte_swx_pipeline *p)
1485 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1489 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
1491 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1498 __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1500 struct port_in_runtime *port = &p->in[p->port_id];
1501 struct rte_swx_pkt *pkt = &t->pkt;
1505 pkt_received = port->pkt_rx(port->obj, pkt);
1506 t->ptr = &pkt->pkt[pkt->offset];
1507 rte_prefetch0(t->ptr);
1509 TRACE("[Thread %2u] rx %s from port %u\n",
1511 pkt_received ? "1 pkt" : "0 pkts",
1515 t->valid_headers = 0;
1516 t->n_headers_out = 0;
1519 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
1522 t->table_state = p->table_state;
1525 pipeline_port_inc(p);
1527 return pkt_received;
1531 instr_rx_exec(struct rte_swx_pipeline *p)
1533 struct thread *t = &p->threads[p->thread_id];
1534 struct instruction *ip = t->ip;
1538 pkt_received = __instr_rx_exec(p, t, ip);
1541 thread_ip_inc_cond(t, pkt_received);
1549 emit_handler(struct thread *t)
1551 struct header_out_runtime *h0 = &t->headers_out[0];
1552 struct header_out_runtime *h1 = &t->headers_out[1];
1553 uint32_t offset = 0, i;
1555 /* No header change or header decapsulation. */
1556 if ((t->n_headers_out == 1) &&
1557 (h0->ptr + h0->n_bytes == t->ptr)) {
1558 TRACE("Emit handler: no header change or header decap.\n");
1560 t->pkt.offset -= h0->n_bytes;
1561 t->pkt.length += h0->n_bytes;
1566 /* Header encapsulation (optionally, with prior header decapsulation). */
1567 if ((t->n_headers_out == 2) &&
1568 (h1->ptr + h1->n_bytes == t->ptr) &&
1569 (h0->ptr == h0->ptr0)) {
1572 TRACE("Emit handler: header encapsulation.\n");
1574 offset = h0->n_bytes + h1->n_bytes;
1575 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1576 t->pkt.offset -= offset;
1577 t->pkt.length += offset;
1582 /* For any other case. */
1583 TRACE("Emit handler: complex case.\n");
1585 for (i = 0; i < t->n_headers_out; i++) {
1586 struct header_out_runtime *h = &t->headers_out[i];
1588 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1589 offset += h->n_bytes;
1593 memcpy(t->ptr - offset, t->header_out_storage, offset);
1594 t->pkt.offset -= offset;
1595 t->pkt.length += offset;
1600 __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1602 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1603 struct port_out_runtime *port = &p->out[port_id];
1604 struct rte_swx_pkt *pkt = &t->pkt;
1606 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1614 port->pkt_tx(port->obj, pkt);
1618 __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1620 uint64_t port_id = ip->io.io.val;
1621 struct port_out_runtime *port = &p->out[port_id];
1622 struct rte_swx_pkt *pkt = &t->pkt;
1624 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1632 port->pkt_tx(port->obj, pkt);
1636 __instr_drop_exec(struct rte_swx_pipeline *p,
1638 const struct instruction *ip __rte_unused)
1640 uint64_t port_id = p->n_ports_out - 1;
1641 struct port_out_runtime *port = &p->out[port_id];
1642 struct rte_swx_pkt *pkt = &t->pkt;
1644 TRACE("[Thread %2u]: drop 1 pkt\n",
1651 port->pkt_tx(port->obj, pkt);
1658 __instr_hdr_extract_many_exec(struct rte_swx_pipeline *p __rte_unused,
1660 const struct instruction *ip,
1663 uint64_t valid_headers = t->valid_headers;
1664 uint8_t *ptr = t->ptr;
1665 uint32_t offset = t->pkt.offset;
1666 uint32_t length = t->pkt.length;
1669 for (i = 0; i < n_extract; i++) {
1670 uint32_t header_id = ip->io.hdr.header_id[i];
1671 uint32_t struct_id = ip->io.hdr.struct_id[i];
1672 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1674 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1680 t->structs[struct_id] = ptr;
1681 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1690 t->valid_headers = valid_headers;
1693 t->pkt.offset = offset;
1694 t->pkt.length = length;
1699 __instr_hdr_extract_exec(struct rte_swx_pipeline *p,
1701 const struct instruction *ip)
1703 __instr_hdr_extract_many_exec(p, t, ip, 1);
1707 __instr_hdr_extract2_exec(struct rte_swx_pipeline *p,
1709 const struct instruction *ip)
1711 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1713 __instr_hdr_extract_many_exec(p, t, ip, 2);
1717 __instr_hdr_extract3_exec(struct rte_swx_pipeline *p,
1719 const struct instruction *ip)
1721 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1723 __instr_hdr_extract_many_exec(p, t, ip, 3);
1727 __instr_hdr_extract4_exec(struct rte_swx_pipeline *p,
1729 const struct instruction *ip)
1731 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1733 __instr_hdr_extract_many_exec(p, t, ip, 4);
1737 __instr_hdr_extract5_exec(struct rte_swx_pipeline *p,
1739 const struct instruction *ip)
1741 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1743 __instr_hdr_extract_many_exec(p, t, ip, 5);
1747 __instr_hdr_extract6_exec(struct rte_swx_pipeline *p,
1749 const struct instruction *ip)
1751 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1753 __instr_hdr_extract_many_exec(p, t, ip, 6);
1757 __instr_hdr_extract7_exec(struct rte_swx_pipeline *p,
1759 const struct instruction *ip)
1761 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1763 __instr_hdr_extract_many_exec(p, t, ip, 7);
1767 __instr_hdr_extract8_exec(struct rte_swx_pipeline *p,
1769 const struct instruction *ip)
1771 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1773 __instr_hdr_extract_many_exec(p, t, ip, 8);
1777 __instr_hdr_extract_m_exec(struct rte_swx_pipeline *p __rte_unused,
1779 const struct instruction *ip)
1781 uint64_t valid_headers = t->valid_headers;
1782 uint8_t *ptr = t->ptr;
1783 uint32_t offset = t->pkt.offset;
1784 uint32_t length = t->pkt.length;
1786 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1787 uint32_t header_id = ip->io.hdr.header_id[0];
1788 uint32_t struct_id = ip->io.hdr.struct_id[0];
1789 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1791 struct header_runtime *h = &t->headers[header_id];
1793 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1799 n_bytes += n_bytes_last;
1802 t->structs[struct_id] = ptr;
1803 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1804 h->n_bytes = n_bytes;
1807 t->pkt.offset = offset + n_bytes;
1808 t->pkt.length = length - n_bytes;
1809 t->ptr = ptr + n_bytes;
1813 __instr_hdr_lookahead_exec(struct rte_swx_pipeline *p __rte_unused,
1815 const struct instruction *ip)
1817 uint64_t valid_headers = t->valid_headers;
1818 uint8_t *ptr = t->ptr;
1820 uint32_t header_id = ip->io.hdr.header_id[0];
1821 uint32_t struct_id = ip->io.hdr.struct_id[0];
1823 TRACE("[Thread %2u]: lookahead header %u\n",
1828 t->structs[struct_id] = ptr;
1829 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1836 __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
1838 const struct instruction *ip,
1841 uint64_t valid_headers = t->valid_headers;
1842 uint32_t n_headers_out = t->n_headers_out;
1843 struct header_out_runtime *ho = NULL;
1844 uint8_t *ho_ptr = NULL;
1845 uint32_t ho_nbytes = 0, i;
1847 for (i = 0; i < n_emit; i++) {
1848 uint32_t header_id = ip->io.hdr.header_id[i];
1849 uint32_t struct_id = ip->io.hdr.struct_id[i];
1851 struct header_runtime *hi = &t->headers[header_id];
1852 uint8_t *hi_ptr0 = hi->ptr0;
1853 uint32_t n_bytes = hi->n_bytes;
1855 uint8_t *hi_ptr = t->structs[struct_id];
1857 if (!MASK64_BIT_GET(valid_headers, header_id)) {
1858 TRACE("[Thread %2u]: emit header %u (invalid)\n",
1865 TRACE("[Thread %2u]: emit header %u (valid)\n",
1871 if (!n_headers_out) {
1872 ho = &t->headers_out[0];
1878 ho_nbytes = n_bytes;
1884 ho = &t->headers_out[n_headers_out - 1];
1887 ho_nbytes = ho->n_bytes;
1891 if (ho_ptr + ho_nbytes == hi_ptr) {
1892 ho_nbytes += n_bytes;
1894 ho->n_bytes = ho_nbytes;
1901 ho_nbytes = n_bytes;
1908 ho->n_bytes = ho_nbytes;
1909 t->n_headers_out = n_headers_out;
1913 __instr_hdr_emit_exec(struct rte_swx_pipeline *p,
1915 const struct instruction *ip)
1917 __instr_hdr_emit_many_exec(p, t, ip, 1);
1921 __instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p,
1923 const struct instruction *ip)
1925 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1927 __instr_hdr_emit_many_exec(p, t, ip, 1);
1928 __instr_tx_exec(p, t, ip);
1932 __instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p,
1934 const struct instruction *ip)
1936 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1938 __instr_hdr_emit_many_exec(p, t, ip, 2);
1939 __instr_tx_exec(p, t, ip);
1943 __instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p,
1945 const struct instruction *ip)
1947 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1949 __instr_hdr_emit_many_exec(p, t, ip, 3);
1950 __instr_tx_exec(p, t, ip);
1954 __instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p,
1956 const struct instruction *ip)
1958 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1960 __instr_hdr_emit_many_exec(p, t, ip, 4);
1961 __instr_tx_exec(p, t, ip);
1965 __instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p,
1967 const struct instruction *ip)
1969 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1971 __instr_hdr_emit_many_exec(p, t, ip, 5);
1972 __instr_tx_exec(p, t, ip);
1976 __instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p,
1978 const struct instruction *ip)
1980 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1982 __instr_hdr_emit_many_exec(p, t, ip, 6);
1983 __instr_tx_exec(p, t, ip);
1987 __instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p,
1989 const struct instruction *ip)
1991 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1993 __instr_hdr_emit_many_exec(p, t, ip, 7);
1994 __instr_tx_exec(p, t, ip);
1998 __instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p,
2000 const struct instruction *ip)
2002 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n", p->thread_id);
2004 __instr_hdr_emit_many_exec(p, t, ip, 8);
2005 __instr_tx_exec(p, t, ip);
2012 __instr_hdr_validate_exec(struct rte_swx_pipeline *p __rte_unused,
2014 const struct instruction *ip)
2016 uint32_t header_id = ip->valid.header_id;
2018 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2021 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2028 __instr_hdr_invalidate_exec(struct rte_swx_pipeline *p __rte_unused,
2030 const struct instruction *ip)
2032 uint32_t header_id = ip->valid.header_id;
2034 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2037 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2044 __instr_learn_exec(struct rte_swx_pipeline *p,
2046 const struct instruction *ip)
2048 uint64_t action_id = ip->learn.action_id;
2049 uint32_t mf_offset = ip->learn.mf_offset;
2050 uint32_t learner_id = t->learner_id;
2051 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2052 p->n_selectors + learner_id];
2053 struct learner_runtime *l = &t->learners[learner_id];
2054 struct learner_statistics *stats = &p->learner_stats[learner_id];
2058 status = rte_swx_table_learner_add(ts->obj,
2062 &t->metadata[mf_offset]);
2064 TRACE("[Thread %2u] learner %u learn %s\n",
2067 status ? "ok" : "error");
2069 stats->n_pkts_learn[status] += 1;
2076 __instr_forget_exec(struct rte_swx_pipeline *p,
2078 const struct instruction *ip __rte_unused)
2080 uint32_t learner_id = t->learner_id;
2081 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2082 p->n_selectors + learner_id];
2083 struct learner_runtime *l = &t->learners[learner_id];
2084 struct learner_statistics *stats = &p->learner_stats[learner_id];
2087 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2089 TRACE("[Thread %2u] learner %u forget\n",
2093 stats->n_pkts_forget += 1;
2099 static inline uint32_t
2100 __instr_extern_obj_exec(struct rte_swx_pipeline *p __rte_unused,
2102 const struct instruction *ip)
2104 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2105 uint32_t func_id = ip->ext_obj.func_id;
2106 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2107 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2110 TRACE("[Thread %2u] extern obj %u member func %u\n",
2115 done = func(obj->obj, obj->mailbox);
2120 static inline uint32_t
2121 __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
2123 const struct instruction *ip)
2125 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2126 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2127 rte_swx_extern_func_t func = ext_func->func;
2130 TRACE("[Thread %2u] extern func %u\n",
2134 done = func(ext_func->mailbox);
2143 __instr_mov_exec(struct rte_swx_pipeline *p __rte_unused,
2145 const struct instruction *ip)
2147 TRACE("[Thread %2u] mov\n", p->thread_id);
2153 __instr_mov_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2155 const struct instruction *ip)
2157 TRACE("[Thread %2u] mov (mh)\n", p->thread_id);
2163 __instr_mov_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2165 const struct instruction *ip)
2167 TRACE("[Thread %2u] mov (hm)\n", p->thread_id);
2173 __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2175 const struct instruction *ip)
2177 TRACE("[Thread %2u] mov (hh)\n", p->thread_id);
2183 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
2185 const struct instruction *ip)
2187 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val);
2196 __instr_dma_ht_many_exec(struct rte_swx_pipeline *p __rte_unused,
2198 const struct instruction *ip,
2201 uint8_t *action_data = t->structs[0];
2202 uint64_t valid_headers = t->valid_headers;
2205 for (i = 0; i < n_dma; i++) {
2206 uint32_t header_id = ip->dma.dst.header_id[i];
2207 uint32_t struct_id = ip->dma.dst.struct_id[i];
2208 uint32_t offset = ip->dma.src.offset[i];
2209 uint32_t n_bytes = ip->dma.n_bytes[i];
2211 struct header_runtime *h = &t->headers[header_id];
2212 uint8_t *h_ptr0 = h->ptr0;
2213 uint8_t *h_ptr = t->structs[struct_id];
2215 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2217 void *src = &action_data[offset];
2219 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2222 memcpy(dst, src, n_bytes);
2223 t->structs[struct_id] = dst;
2224 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2227 t->valid_headers = valid_headers;
2231 __instr_dma_ht_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2233 __instr_dma_ht_many_exec(p, t, ip, 1);
2237 __instr_dma_ht2_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2239 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2241 __instr_dma_ht_many_exec(p, t, ip, 2);
2245 __instr_dma_ht3_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2247 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2249 __instr_dma_ht_many_exec(p, t, ip, 3);
2253 __instr_dma_ht4_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2255 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2257 __instr_dma_ht_many_exec(p, t, ip, 4);
2261 __instr_dma_ht5_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2263 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2265 __instr_dma_ht_many_exec(p, t, ip, 5);
2269 __instr_dma_ht6_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2271 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2273 __instr_dma_ht_many_exec(p, t, ip, 6);
2277 __instr_dma_ht7_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2279 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2281 __instr_dma_ht_many_exec(p, t, ip, 7);
2285 __instr_dma_ht8_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2287 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2289 __instr_dma_ht_many_exec(p, t, ip, 8);
2296 __instr_alu_add_exec(struct rte_swx_pipeline *p __rte_unused,
2298 const struct instruction *ip)
2300 TRACE("[Thread %2u] add\n", p->thread_id);
2306 __instr_alu_add_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2308 const struct instruction *ip)
2310 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
2316 __instr_alu_add_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2318 const struct instruction *ip)
2320 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
2326 __instr_alu_add_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2328 const struct instruction *ip)
2330 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
2336 __instr_alu_add_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2338 const struct instruction *ip)
2340 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
2346 __instr_alu_add_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2348 const struct instruction *ip)
2350 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
2356 __instr_alu_sub_exec(struct rte_swx_pipeline *p __rte_unused,
2358 const struct instruction *ip)
2360 TRACE("[Thread %2u] sub\n", p->thread_id);
2366 __instr_alu_sub_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2368 const struct instruction *ip)
2370 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
2376 __instr_alu_sub_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2378 const struct instruction *ip)
2380 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
2386 __instr_alu_sub_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2388 const struct instruction *ip)
2390 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
2396 __instr_alu_sub_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2398 const struct instruction *ip)
2400 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
2406 __instr_alu_sub_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2408 const struct instruction *ip)
2410 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
2416 __instr_alu_shl_exec(struct rte_swx_pipeline *p __rte_unused,
2418 const struct instruction *ip)
2420 TRACE("[Thread %2u] shl\n", p->thread_id);
2426 __instr_alu_shl_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2428 const struct instruction *ip)
2430 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
2436 __instr_alu_shl_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2438 const struct instruction *ip)
2440 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
2446 __instr_alu_shl_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2448 const struct instruction *ip)
2450 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
2456 __instr_alu_shl_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2458 const struct instruction *ip)
2460 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
2466 __instr_alu_shl_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2468 const struct instruction *ip)
2470 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
2476 __instr_alu_shr_exec(struct rte_swx_pipeline *p __rte_unused,
2478 const struct instruction *ip)
2480 TRACE("[Thread %2u] shr\n", p->thread_id);
2486 __instr_alu_shr_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2488 const struct instruction *ip)
2490 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
2496 __instr_alu_shr_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2498 const struct instruction *ip)
2500 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
2506 __instr_alu_shr_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2508 const struct instruction *ip)
2510 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
2516 __instr_alu_shr_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2518 const struct instruction *ip)
2520 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
2527 __instr_alu_shr_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2529 const struct instruction *ip)
2531 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
2537 __instr_alu_and_exec(struct rte_swx_pipeline *p __rte_unused,
2539 const struct instruction *ip)
2541 TRACE("[Thread %2u] and\n", p->thread_id);
2547 __instr_alu_and_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2549 const struct instruction *ip)
2551 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
2557 __instr_alu_and_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2559 const struct instruction *ip)
2561 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
2563 ALU_HM_FAST(t, ip, &);
2567 __instr_alu_and_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2569 const struct instruction *ip)
2571 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
2573 ALU_HH_FAST(t, ip, &);
2577 __instr_alu_and_i_exec(struct rte_swx_pipeline *p __rte_unused,
2579 const struct instruction *ip)
2581 TRACE("[Thread %2u] and (i)\n", p->thread_id);
2587 __instr_alu_or_exec(struct rte_swx_pipeline *p __rte_unused,
2589 const struct instruction *ip)
2591 TRACE("[Thread %2u] or\n", p->thread_id);
2597 __instr_alu_or_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2599 const struct instruction *ip)
2601 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
2607 __instr_alu_or_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2609 const struct instruction *ip)
2611 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
2613 ALU_HM_FAST(t, ip, |);
2617 __instr_alu_or_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2619 const struct instruction *ip)
2621 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
2623 ALU_HH_FAST(t, ip, |);
2627 __instr_alu_or_i_exec(struct rte_swx_pipeline *p __rte_unused,
2629 const struct instruction *ip)
2631 TRACE("[Thread %2u] or (i)\n", p->thread_id);
2637 __instr_alu_xor_exec(struct rte_swx_pipeline *p __rte_unused,
2639 const struct instruction *ip)
2641 TRACE("[Thread %2u] xor\n", p->thread_id);
2647 __instr_alu_xor_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2649 const struct instruction *ip)
2651 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
2657 __instr_alu_xor_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2659 const struct instruction *ip)
2661 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
2663 ALU_HM_FAST(t, ip, ^);
2667 __instr_alu_xor_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2669 const struct instruction *ip)
2671 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
2673 ALU_HH_FAST(t, ip, ^);
2677 __instr_alu_xor_i_exec(struct rte_swx_pipeline *p __rte_unused,
2679 const struct instruction *ip)
2681 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
2687 __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
2689 const struct instruction *ip)
2691 uint8_t *dst_struct, *src_struct;
2692 uint16_t *dst16_ptr, dst;
2693 uint64_t *src64_ptr, src64, src64_mask, src;
2696 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
2699 dst_struct = t->structs[ip->alu.dst.struct_id];
2700 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2703 src_struct = t->structs[ip->alu.src.struct_id];
2704 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2706 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2707 src = src64 & src64_mask;
2709 /* Initialize the result with destination 1's complement. */
2713 /* The first input (r) is a 16-bit number. The second and the third
2714 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
2715 * three numbers (output r) is a 34-bit number.
2717 r += (src >> 32) + (src & 0xFFFFFFFF);
2719 /* The first input is a 16-bit number. The second input is an 18-bit
2720 * number. In the worst case scenario, the sum of the two numbers is a
2723 r = (r & 0xFFFF) + (r >> 16);
2725 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2726 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
2728 r = (r & 0xFFFF) + (r >> 16);
2730 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2731 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2732 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
2733 * therefore the output r is always a 16-bit number.
2735 r = (r & 0xFFFF) + (r >> 16);
2737 /* Apply 1's complement to the result. */
2741 *dst16_ptr = (uint16_t)r;
2745 __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
2747 const struct instruction *ip)
2749 uint8_t *dst_struct, *src_struct;
2750 uint16_t *dst16_ptr, dst;
2751 uint64_t *src64_ptr, src64, src64_mask, src;
2754 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
2757 dst_struct = t->structs[ip->alu.dst.struct_id];
2758 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2761 src_struct = t->structs[ip->alu.src.struct_id];
2762 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2764 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2765 src = src64 & src64_mask;
2767 /* Initialize the result with destination 1's complement. */
2771 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
2772 * the following sequence of operations in 2's complement arithmetic:
2773 * a '- b = (a - b) % 0xFFFF.
2775 * In order to prevent an underflow for the below subtraction, in which
2776 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
2777 * minuend), we first add a multiple of the 0xFFFF modulus to the
2778 * minuend. The number we add to the minuend needs to be a 34-bit number
2779 * or higher, so for readability reasons we picked the 36-bit multiple.
2780 * We are effectively turning the 16-bit minuend into a 36-bit number:
2781 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
2783 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
2785 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
2786 * result (the output r) is a 36-bit number.
2788 r -= (src >> 32) + (src & 0xFFFFFFFF);
2790 /* The first input is a 16-bit number. The second input is a 20-bit
2791 * number. Their sum is a 21-bit number.
2793 r = (r & 0xFFFF) + (r >> 16);
2795 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2796 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
2798 r = (r & 0xFFFF) + (r >> 16);
2800 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2801 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2802 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2803 * generated, therefore the output r is always a 16-bit number.
2805 r = (r & 0xFFFF) + (r >> 16);
2807 /* Apply 1's complement to the result. */
2811 *dst16_ptr = (uint16_t)r;
2815 __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
2817 const struct instruction *ip)
2819 uint8_t *dst_struct, *src_struct;
2820 uint16_t *dst16_ptr, dst;
2821 uint32_t *src32_ptr;
2824 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
2827 dst_struct = t->structs[ip->alu.dst.struct_id];
2828 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2831 src_struct = t->structs[ip->alu.src.struct_id];
2832 src32_ptr = (uint32_t *)&src_struct[0];
2834 /* Initialize the result with destination 1's complement. */
2838 r0 += src32_ptr[0]; /* The output r0 is a 33-bit number. */
2839 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
2840 r0 += src32_ptr[2]; /* The output r0 is a 34-bit number. */
2841 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
2842 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
2844 /* The first input is a 16-bit number. The second input is a 19-bit
2845 * number. Their sum is a 20-bit number.
2847 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2849 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2850 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
2852 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2854 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2855 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2856 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
2857 * generated, therefore the output r is always a 16-bit number.
2859 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2861 /* Apply 1's complement to the result. */
2863 r0 = r0 ? r0 : 0xFFFF;
2865 *dst16_ptr = (uint16_t)r0;
2869 __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
2871 const struct instruction *ip)
2873 uint32_t src_header_id = ip->alu.src.n_bits; /* The src header ID is stored here. */
2874 uint32_t n_src_header_bytes = t->headers[src_header_id].n_bytes;
2875 uint8_t *dst_struct, *src_struct;
2876 uint16_t *dst16_ptr, dst;
2877 uint32_t *src32_ptr;
2881 if (n_src_header_bytes == 20) {
2882 __instr_alu_ckadd_struct20_exec(p, t, ip);
2886 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
2889 dst_struct = t->structs[ip->alu.dst.struct_id];
2890 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2893 src_struct = t->structs[ip->alu.src.struct_id];
2894 src32_ptr = (uint32_t *)&src_struct[0];
2896 /* Initialize the result with destination 1's complement. */
2900 /* The max number of 32-bit words in a 32K-byte header is 2^13.
2901 * Therefore, in the worst case scenario, a 45-bit number is added to a
2902 * 16-bit number (the input r), so the output r is 46-bit number.
2904 for (i = 0; i < n_src_header_bytes / 4; i++, src32_ptr++)
2907 /* The first input is a 16-bit number. The second input is a 30-bit
2908 * number. Their sum is a 31-bit number.
2910 r = (r & 0xFFFF) + (r >> 16);
2912 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2913 * a 15-bit number (0 .. 0x7FFF). The sum is a 17-bit number (0 .. 0x17FFE).
2915 r = (r & 0xFFFF) + (r >> 16);
2917 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2918 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2919 * 0x17FFE), the output r is (0 .. 0x7FFF). So no carry bit can be
2920 * generated, therefore the output r is always a 16-bit number.
2922 r = (r & 0xFFFF) + (r >> 16);
2924 /* Apply 1's complement to the result. */
2928 *dst16_ptr = (uint16_t)r;
2934 static inline uint64_t *
2935 instr_regarray_regarray(struct rte_swx_pipeline *p, const struct instruction *ip)
2937 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2941 static inline uint64_t
2942 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2944 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2946 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2947 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2948 uint64_t idx64 = *idx64_ptr;
2949 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
2950 uint64_t idx = idx64 & idx64_mask & r->size_mask;
2955 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2957 static inline uint64_t
2958 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2960 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2962 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2963 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2964 uint64_t idx64 = *idx64_ptr;
2965 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
2972 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
2976 static inline uint64_t
2977 instr_regarray_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
2979 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2981 uint64_t idx = ip->regarray.idx_val & r->size_mask;
2986 static inline uint64_t
2987 instr_regarray_src_hbo(struct thread *t, const struct instruction *ip)
2989 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
2990 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
2991 uint64_t src64 = *src64_ptr;
2992 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
2993 uint64_t src = src64 & src64_mask;
2998 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3000 static inline uint64_t
3001 instr_regarray_src_nbo(struct thread *t, const struct instruction *ip)
3003 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3004 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3005 uint64_t src64 = *src64_ptr;
3006 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
3013 #define instr_regarray_src_nbo instr_regarray_src_hbo
3018 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3020 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3021 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3022 uint64_t dst64 = *dst64_ptr;
3023 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3025 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3029 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3032 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3034 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3035 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3036 uint64_t dst64 = *dst64_ptr;
3037 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3039 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
3040 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3045 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
3050 __instr_regprefetch_rh_exec(struct rte_swx_pipeline *p,
3052 const struct instruction *ip)
3054 uint64_t *regarray, idx;
3056 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
3058 regarray = instr_regarray_regarray(p, ip);
3059 idx = instr_regarray_idx_nbo(p, t, ip);
3060 rte_prefetch0(®array[idx]);
3064 __instr_regprefetch_rm_exec(struct rte_swx_pipeline *p,
3066 const struct instruction *ip)
3068 uint64_t *regarray, idx;
3070 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
3072 regarray = instr_regarray_regarray(p, ip);
3073 idx = instr_regarray_idx_hbo(p, t, ip);
3074 rte_prefetch0(®array[idx]);
3078 __instr_regprefetch_ri_exec(struct rte_swx_pipeline *p,
3079 struct thread *t __rte_unused,
3080 const struct instruction *ip)
3082 uint64_t *regarray, idx;
3084 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
3086 regarray = instr_regarray_regarray(p, ip);
3087 idx = instr_regarray_idx_imm(p, ip);
3088 rte_prefetch0(®array[idx]);
3092 __instr_regrd_hrh_exec(struct rte_swx_pipeline *p,
3094 const struct instruction *ip)
3096 uint64_t *regarray, idx;
3098 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
3100 regarray = instr_regarray_regarray(p, ip);
3101 idx = instr_regarray_idx_nbo(p, t, ip);
3102 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3106 __instr_regrd_hrm_exec(struct rte_swx_pipeline *p,
3108 const struct instruction *ip)
3110 uint64_t *regarray, idx;
3112 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
3115 regarray = instr_regarray_regarray(p, ip);
3116 idx = instr_regarray_idx_hbo(p, t, ip);
3117 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3121 __instr_regrd_mrh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3123 uint64_t *regarray, idx;
3125 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
3127 regarray = instr_regarray_regarray(p, ip);
3128 idx = instr_regarray_idx_nbo(p, t, ip);
3129 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3133 __instr_regrd_mrm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3135 uint64_t *regarray, idx;
3137 TRACE("[Thread %2u] regrd (m = r[m])\n", p->thread_id);
3139 regarray = instr_regarray_regarray(p, ip);
3140 idx = instr_regarray_idx_hbo(p, t, ip);
3141 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3145 __instr_regrd_hri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3147 uint64_t *regarray, idx;
3149 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
3151 regarray = instr_regarray_regarray(p, ip);
3152 idx = instr_regarray_idx_imm(p, ip);
3153 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3157 __instr_regrd_mri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3159 uint64_t *regarray, idx;
3161 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
3163 regarray = instr_regarray_regarray(p, ip);
3164 idx = instr_regarray_idx_imm(p, ip);
3165 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3169 __instr_regwr_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3171 uint64_t *regarray, idx, src;
3173 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
3175 regarray = instr_regarray_regarray(p, ip);
3176 idx = instr_regarray_idx_nbo(p, t, ip);
3177 src = instr_regarray_src_nbo(t, ip);
3178 regarray[idx] = src;
3182 __instr_regwr_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3184 uint64_t *regarray, idx, src;
3186 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
3188 regarray = instr_regarray_regarray(p, ip);
3189 idx = instr_regarray_idx_nbo(p, t, ip);
3190 src = instr_regarray_src_hbo(t, ip);
3191 regarray[idx] = src;
3195 __instr_regwr_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3197 uint64_t *regarray, idx, src;
3199 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
3201 regarray = instr_regarray_regarray(p, ip);
3202 idx = instr_regarray_idx_hbo(p, t, ip);
3203 src = instr_regarray_src_nbo(t, ip);
3204 regarray[idx] = src;
3208 __instr_regwr_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3210 uint64_t *regarray, idx, src;
3212 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
3214 regarray = instr_regarray_regarray(p, ip);
3215 idx = instr_regarray_idx_hbo(p, t, ip);
3216 src = instr_regarray_src_hbo(t, ip);
3217 regarray[idx] = src;
3221 __instr_regwr_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3223 uint64_t *regarray, idx, src;
3225 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
3227 regarray = instr_regarray_regarray(p, ip);
3228 idx = instr_regarray_idx_nbo(p, t, ip);
3229 src = ip->regarray.dstsrc_val;
3230 regarray[idx] = src;
3234 __instr_regwr_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3236 uint64_t *regarray, idx, src;
3238 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
3240 regarray = instr_regarray_regarray(p, ip);
3241 idx = instr_regarray_idx_hbo(p, t, ip);
3242 src = ip->regarray.dstsrc_val;
3243 regarray[idx] = src;
3247 __instr_regwr_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3249 uint64_t *regarray, idx, src;
3251 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
3253 regarray = instr_regarray_regarray(p, ip);
3254 idx = instr_regarray_idx_imm(p, ip);
3255 src = instr_regarray_src_nbo(t, ip);
3256 regarray[idx] = src;
3260 __instr_regwr_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3262 uint64_t *regarray, idx, src;
3264 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
3266 regarray = instr_regarray_regarray(p, ip);
3267 idx = instr_regarray_idx_imm(p, ip);
3268 src = instr_regarray_src_hbo(t, ip);
3269 regarray[idx] = src;
3273 __instr_regwr_rii_exec(struct rte_swx_pipeline *p,
3274 struct thread *t __rte_unused,
3275 const struct instruction *ip)
3277 uint64_t *regarray, idx, src;
3279 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
3281 regarray = instr_regarray_regarray(p, ip);
3282 idx = instr_regarray_idx_imm(p, ip);
3283 src = ip->regarray.dstsrc_val;
3284 regarray[idx] = src;
3288 __instr_regadd_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3290 uint64_t *regarray, idx, src;
3292 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
3294 regarray = instr_regarray_regarray(p, ip);
3295 idx = instr_regarray_idx_nbo(p, t, ip);
3296 src = instr_regarray_src_nbo(t, ip);
3297 regarray[idx] += src;
3301 __instr_regadd_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3303 uint64_t *regarray, idx, src;
3305 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
3307 regarray = instr_regarray_regarray(p, ip);
3308 idx = instr_regarray_idx_nbo(p, t, ip);
3309 src = instr_regarray_src_hbo(t, ip);
3310 regarray[idx] += src;
3314 __instr_regadd_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3316 uint64_t *regarray, idx, src;
3318 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
3320 regarray = instr_regarray_regarray(p, ip);
3321 idx = instr_regarray_idx_hbo(p, t, ip);
3322 src = instr_regarray_src_nbo(t, ip);
3323 regarray[idx] += src;
3327 __instr_regadd_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3329 uint64_t *regarray, idx, src;
3331 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
3333 regarray = instr_regarray_regarray(p, ip);
3334 idx = instr_regarray_idx_hbo(p, t, ip);
3335 src = instr_regarray_src_hbo(t, ip);
3336 regarray[idx] += src;
3340 __instr_regadd_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3342 uint64_t *regarray, idx, src;
3344 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
3346 regarray = instr_regarray_regarray(p, ip);
3347 idx = instr_regarray_idx_nbo(p, t, ip);
3348 src = ip->regarray.dstsrc_val;
3349 regarray[idx] += src;
3353 __instr_regadd_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3355 uint64_t *regarray, idx, src;
3357 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
3359 regarray = instr_regarray_regarray(p, ip);
3360 idx = instr_regarray_idx_hbo(p, t, ip);
3361 src = ip->regarray.dstsrc_val;
3362 regarray[idx] += src;
3366 __instr_regadd_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3368 uint64_t *regarray, idx, src;
3370 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
3372 regarray = instr_regarray_regarray(p, ip);
3373 idx = instr_regarray_idx_imm(p, ip);
3374 src = instr_regarray_src_nbo(t, ip);
3375 regarray[idx] += src;
3379 __instr_regadd_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3381 uint64_t *regarray, idx, src;
3383 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
3385 regarray = instr_regarray_regarray(p, ip);
3386 idx = instr_regarray_idx_imm(p, ip);
3387 src = instr_regarray_src_hbo(t, ip);
3388 regarray[idx] += src;
3392 __instr_regadd_rii_exec(struct rte_swx_pipeline *p,
3393 struct thread *t __rte_unused,
3394 const struct instruction *ip)
3396 uint64_t *regarray, idx, src;
3398 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
3400 regarray = instr_regarray_regarray(p, ip);
3401 idx = instr_regarray_idx_imm(p, ip);
3402 src = ip->regarray.dstsrc_val;
3403 regarray[idx] += src;
3409 static inline struct meter *
3410 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3412 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3414 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3415 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3416 uint64_t idx64 = *idx64_ptr;
3417 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
3418 uint64_t idx = idx64 & idx64_mask & r->size_mask;
3420 return &r->metarray[idx];
3423 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3425 static inline struct meter *
3426 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3428 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3430 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3431 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3432 uint64_t idx64 = *idx64_ptr;
3433 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
3435 return &r->metarray[idx];
3440 #define instr_meter_idx_nbo instr_meter_idx_hbo
3444 static inline struct meter *
3445 instr_meter_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3447 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3449 uint64_t idx = ip->meter.idx_val & r->size_mask;
3451 return &r->metarray[idx];
3454 static inline uint32_t
3455 instr_meter_length_hbo(struct thread *t, const struct instruction *ip)
3457 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3458 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3459 uint64_t src64 = *src64_ptr;
3460 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
3461 uint64_t src = src64 & src64_mask;
3463 return (uint32_t)src;
3466 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3468 static inline uint32_t
3469 instr_meter_length_nbo(struct thread *t, const struct instruction *ip)
3471 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3472 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3473 uint64_t src64 = *src64_ptr;
3474 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
3476 return (uint32_t)src;
3481 #define instr_meter_length_nbo instr_meter_length_hbo
3485 static inline enum rte_color
3486 instr_meter_color_in_hbo(struct thread *t, const struct instruction *ip)
3488 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
3489 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
3490 uint64_t src64 = *src64_ptr;
3491 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
3492 uint64_t src = src64 & src64_mask;
3494 return (enum rte_color)src;
3498 instr_meter_color_out_hbo_set(struct thread *t,
3499 const struct instruction *ip,
3500 enum rte_color color_out)
3502 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
3503 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
3504 uint64_t dst64 = *dst64_ptr;
3505 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
3507 uint64_t src = (uint64_t)color_out;
3509 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3513 __instr_metprefetch_h_exec(struct rte_swx_pipeline *p,
3515 const struct instruction *ip)
3519 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
3521 m = instr_meter_idx_nbo(p, t, ip);
3526 __instr_metprefetch_m_exec(struct rte_swx_pipeline *p,
3528 const struct instruction *ip)
3532 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
3534 m = instr_meter_idx_hbo(p, t, ip);
3539 __instr_metprefetch_i_exec(struct rte_swx_pipeline *p,
3540 struct thread *t __rte_unused,
3541 const struct instruction *ip)
3545 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
3547 m = instr_meter_idx_imm(p, ip);
3552 __instr_meter_hhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3555 uint64_t time, n_pkts, n_bytes;
3557 enum rte_color color_in, color_out;
3559 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
3561 m = instr_meter_idx_nbo(p, t, ip);
3562 rte_prefetch0(m->n_pkts);
3563 time = rte_get_tsc_cycles();
3564 length = instr_meter_length_nbo(t, ip);
3565 color_in = instr_meter_color_in_hbo(t, ip);
3567 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3568 &m->profile->profile,
3573 color_out &= m->color_mask;
3575 n_pkts = m->n_pkts[color_out];
3576 n_bytes = m->n_bytes[color_out];
3578 instr_meter_color_out_hbo_set(t, ip, color_out);
3580 m->n_pkts[color_out] = n_pkts + 1;
3581 m->n_bytes[color_out] = n_bytes + length;
3585 __instr_meter_hhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3588 uint64_t time, n_pkts, n_bytes;
3590 enum rte_color color_in, color_out;
3592 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
3594 m = instr_meter_idx_nbo(p, t, ip);
3595 rte_prefetch0(m->n_pkts);
3596 time = rte_get_tsc_cycles();
3597 length = instr_meter_length_nbo(t, ip);
3598 color_in = (enum rte_color)ip->meter.color_in_val;
3600 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3601 &m->profile->profile,
3606 color_out &= m->color_mask;
3608 n_pkts = m->n_pkts[color_out];
3609 n_bytes = m->n_bytes[color_out];
3611 instr_meter_color_out_hbo_set(t, ip, color_out);
3613 m->n_pkts[color_out] = n_pkts + 1;
3614 m->n_bytes[color_out] = n_bytes + length;
3618 __instr_meter_hmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3621 uint64_t time, n_pkts, n_bytes;
3623 enum rte_color color_in, color_out;
3625 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
3627 m = instr_meter_idx_nbo(p, t, ip);
3628 rte_prefetch0(m->n_pkts);
3629 time = rte_get_tsc_cycles();
3630 length = instr_meter_length_hbo(t, ip);
3631 color_in = instr_meter_color_in_hbo(t, ip);
3633 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3634 &m->profile->profile,
3639 color_out &= m->color_mask;
3641 n_pkts = m->n_pkts[color_out];
3642 n_bytes = m->n_bytes[color_out];
3644 instr_meter_color_out_hbo_set(t, ip, color_out);
3646 m->n_pkts[color_out] = n_pkts + 1;
3647 m->n_bytes[color_out] = n_bytes + length;
3651 __instr_meter_hmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3654 uint64_t time, n_pkts, n_bytes;
3656 enum rte_color color_in, color_out;
3658 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
3660 m = instr_meter_idx_nbo(p, t, ip);
3661 rte_prefetch0(m->n_pkts);
3662 time = rte_get_tsc_cycles();
3663 length = instr_meter_length_hbo(t, ip);
3664 color_in = (enum rte_color)ip->meter.color_in_val;
3666 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3667 &m->profile->profile,
3672 color_out &= m->color_mask;
3674 n_pkts = m->n_pkts[color_out];
3675 n_bytes = m->n_bytes[color_out];
3677 instr_meter_color_out_hbo_set(t, ip, color_out);
3679 m->n_pkts[color_out] = n_pkts + 1;
3680 m->n_bytes[color_out] = n_bytes + length;
3684 __instr_meter_mhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3687 uint64_t time, n_pkts, n_bytes;
3689 enum rte_color color_in, color_out;
3691 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
3693 m = instr_meter_idx_hbo(p, t, ip);
3694 rte_prefetch0(m->n_pkts);
3695 time = rte_get_tsc_cycles();
3696 length = instr_meter_length_nbo(t, ip);
3697 color_in = instr_meter_color_in_hbo(t, ip);
3699 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3700 &m->profile->profile,
3705 color_out &= m->color_mask;
3707 n_pkts = m->n_pkts[color_out];
3708 n_bytes = m->n_bytes[color_out];
3710 instr_meter_color_out_hbo_set(t, ip, color_out);
3712 m->n_pkts[color_out] = n_pkts + 1;
3713 m->n_bytes[color_out] = n_bytes + length;
3717 __instr_meter_mhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3720 uint64_t time, n_pkts, n_bytes;
3722 enum rte_color color_in, color_out;
3724 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
3726 m = instr_meter_idx_hbo(p, t, ip);
3727 rte_prefetch0(m->n_pkts);
3728 time = rte_get_tsc_cycles();
3729 length = instr_meter_length_nbo(t, ip);
3730 color_in = (enum rte_color)ip->meter.color_in_val;
3732 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3733 &m->profile->profile,
3738 color_out &= m->color_mask;
3740 n_pkts = m->n_pkts[color_out];
3741 n_bytes = m->n_bytes[color_out];
3743 instr_meter_color_out_hbo_set(t, ip, color_out);
3745 m->n_pkts[color_out] = n_pkts + 1;
3746 m->n_bytes[color_out] = n_bytes + length;
3750 __instr_meter_mmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3753 uint64_t time, n_pkts, n_bytes;
3755 enum rte_color color_in, color_out;
3757 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
3759 m = instr_meter_idx_hbo(p, t, ip);
3760 rte_prefetch0(m->n_pkts);
3761 time = rte_get_tsc_cycles();
3762 length = instr_meter_length_hbo(t, ip);
3763 color_in = instr_meter_color_in_hbo(t, ip);
3765 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3766 &m->profile->profile,
3771 color_out &= m->color_mask;
3773 n_pkts = m->n_pkts[color_out];
3774 n_bytes = m->n_bytes[color_out];
3776 instr_meter_color_out_hbo_set(t, ip, color_out);
3778 m->n_pkts[color_out] = n_pkts + 1;
3779 m->n_bytes[color_out] = n_bytes + length;
3783 __instr_meter_mmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3786 uint64_t time, n_pkts, n_bytes;
3788 enum rte_color color_in, color_out;
3790 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
3792 m = instr_meter_idx_hbo(p, t, ip);
3793 rte_prefetch0(m->n_pkts);
3794 time = rte_get_tsc_cycles();
3795 length = instr_meter_length_hbo(t, ip);
3796 color_in = (enum rte_color)ip->meter.color_in_val;
3798 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3799 &m->profile->profile,
3804 color_out &= m->color_mask;
3806 n_pkts = m->n_pkts[color_out];
3807 n_bytes = m->n_bytes[color_out];
3809 instr_meter_color_out_hbo_set(t, ip, color_out);
3811 m->n_pkts[color_out] = n_pkts + 1;
3812 m->n_bytes[color_out] = n_bytes + length;
3816 __instr_meter_ihm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3819 uint64_t time, n_pkts, n_bytes;
3821 enum rte_color color_in, color_out;
3823 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
3825 m = instr_meter_idx_imm(p, ip);
3826 rte_prefetch0(m->n_pkts);
3827 time = rte_get_tsc_cycles();
3828 length = instr_meter_length_nbo(t, ip);
3829 color_in = instr_meter_color_in_hbo(t, ip);
3831 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3832 &m->profile->profile,
3837 color_out &= m->color_mask;
3839 n_pkts = m->n_pkts[color_out];
3840 n_bytes = m->n_bytes[color_out];
3842 instr_meter_color_out_hbo_set(t, ip, color_out);
3844 m->n_pkts[color_out] = n_pkts + 1;
3845 m->n_bytes[color_out] = n_bytes + length;
3849 __instr_meter_ihi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3852 uint64_t time, n_pkts, n_bytes;
3854 enum rte_color color_in, color_out;
3856 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
3858 m = instr_meter_idx_imm(p, ip);
3859 rte_prefetch0(m->n_pkts);
3860 time = rte_get_tsc_cycles();
3861 length = instr_meter_length_nbo(t, ip);
3862 color_in = (enum rte_color)ip->meter.color_in_val;
3864 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3865 &m->profile->profile,
3870 color_out &= m->color_mask;
3872 n_pkts = m->n_pkts[color_out];
3873 n_bytes = m->n_bytes[color_out];
3875 instr_meter_color_out_hbo_set(t, ip, color_out);
3877 m->n_pkts[color_out] = n_pkts + 1;
3878 m->n_bytes[color_out] = n_bytes + length;
3882 __instr_meter_imm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3885 uint64_t time, n_pkts, n_bytes;
3887 enum rte_color color_in, color_out;
3889 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
3891 m = instr_meter_idx_imm(p, ip);
3892 rte_prefetch0(m->n_pkts);
3893 time = rte_get_tsc_cycles();
3894 length = instr_meter_length_hbo(t, ip);
3895 color_in = instr_meter_color_in_hbo(t, ip);
3897 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3898 &m->profile->profile,
3903 color_out &= m->color_mask;
3905 n_pkts = m->n_pkts[color_out];
3906 n_bytes = m->n_bytes[color_out];
3908 instr_meter_color_out_hbo_set(t, ip, color_out);
3910 m->n_pkts[color_out] = n_pkts + 1;
3911 m->n_bytes[color_out] = n_bytes + length;
3915 __instr_meter_imi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3918 uint64_t time, n_pkts, n_bytes;
3920 enum rte_color color_in, color_out;
3922 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
3924 m = instr_meter_idx_imm(p, ip);
3925 rte_prefetch0(m->n_pkts);
3926 time = rte_get_tsc_cycles();
3927 length = instr_meter_length_hbo(t, ip);
3928 color_in = (enum rte_color)ip->meter.color_in_val;
3930 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3931 &m->profile->profile,
3936 color_out &= m->color_mask;
3938 n_pkts = m->n_pkts[color_out];
3939 n_bytes = m->n_bytes[color_out];
3941 instr_meter_color_out_hbo_set(t, ip, color_out);
3943 m->n_pkts[color_out] = n_pkts + 1;
3944 m->n_bytes[color_out] = n_bytes + length;