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 */
229 /* extract h.header */
239 /* extract h.header m.last_field_size */
242 /* lookahead h.header */
256 /* validate h.header */
259 /* invalidate h.header */
260 INSTR_HDR_INVALIDATE,
264 * dst = HMEF, src = HMEFTI
266 INSTR_MOV, /* dst = MEF, src = MEFT */
267 INSTR_MOV_MH, /* dst = MEF, src = H */
268 INSTR_MOV_HM, /* dst = H, src = MEFT */
269 INSTR_MOV_HH, /* dst = H, src = H */
270 INSTR_MOV_I, /* dst = HMEF, src = I */
272 /* dma h.header t.field
273 * memcpy(h.header, t.field, sizeof(h.header))
286 * dst = HMEF, src = HMEFTI
288 INSTR_ALU_ADD, /* dst = MEF, src = MEF */
289 INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
290 INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
291 INSTR_ALU_ADD_HH, /* dst = H, src = H */
292 INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
293 INSTR_ALU_ADD_HI, /* dst = H, src = I */
297 * dst = HMEF, src = HMEFTI
299 INSTR_ALU_SUB, /* dst = MEF, src = MEF */
300 INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
301 INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
302 INSTR_ALU_SUB_HH, /* dst = H, src = H */
303 INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
304 INSTR_ALU_SUB_HI, /* dst = H, src = I */
307 * dst = dst '+ src[0:1] '+ src[2:3] + ...
308 * dst = H, src = {H, h.header}
310 INSTR_ALU_CKADD_FIELD, /* src = H */
311 INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 */
312 INSTR_ALU_CKADD_STRUCT, /* src = h.hdeader, with any sizeof(header) */
318 INSTR_ALU_CKSUB_FIELD,
322 * dst = HMEF, src = HMEFTI
324 INSTR_ALU_AND, /* dst = MEF, src = MEFT */
325 INSTR_ALU_AND_MH, /* dst = MEF, src = H */
326 INSTR_ALU_AND_HM, /* dst = H, src = MEFT */
327 INSTR_ALU_AND_HH, /* dst = H, src = H */
328 INSTR_ALU_AND_I, /* dst = HMEF, src = I */
332 * dst = HMEF, src = HMEFTI
334 INSTR_ALU_OR, /* dst = MEF, src = MEFT */
335 INSTR_ALU_OR_MH, /* dst = MEF, src = H */
336 INSTR_ALU_OR_HM, /* dst = H, src = MEFT */
337 INSTR_ALU_OR_HH, /* dst = H, src = H */
338 INSTR_ALU_OR_I, /* dst = HMEF, src = I */
342 * dst = HMEF, src = HMEFTI
344 INSTR_ALU_XOR, /* dst = MEF, src = MEFT */
345 INSTR_ALU_XOR_MH, /* dst = MEF, src = H */
346 INSTR_ALU_XOR_HM, /* dst = H, src = MEFT */
347 INSTR_ALU_XOR_HH, /* dst = H, src = H */
348 INSTR_ALU_XOR_I, /* dst = HMEF, src = I */
352 * dst = HMEF, src = HMEFTI
354 INSTR_ALU_SHL, /* dst = MEF, src = MEF */
355 INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
356 INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
357 INSTR_ALU_SHL_HH, /* dst = H, src = H */
358 INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
359 INSTR_ALU_SHL_HI, /* dst = H, src = I */
363 * dst = HMEF, src = HMEFTI
365 INSTR_ALU_SHR, /* dst = MEF, src = MEF */
366 INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
367 INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
368 INSTR_ALU_SHR_HH, /* dst = H, src = H */
369 INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
370 INSTR_ALU_SHR_HI, /* dst = H, src = I */
372 /* regprefetch REGARRAY index
373 * prefetch REGARRAY[index]
376 INSTR_REGPREFETCH_RH, /* index = H */
377 INSTR_REGPREFETCH_RM, /* index = MEFT */
378 INSTR_REGPREFETCH_RI, /* index = I */
380 /* regrd dst REGARRAY index
381 * dst = REGARRAY[index]
382 * dst = HMEF, index = HMEFTI
384 INSTR_REGRD_HRH, /* dst = H, index = H */
385 INSTR_REGRD_HRM, /* dst = H, index = MEFT */
386 INSTR_REGRD_HRI, /* dst = H, index = I */
387 INSTR_REGRD_MRH, /* dst = MEF, index = H */
388 INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
389 INSTR_REGRD_MRI, /* dst = MEF, index = I */
391 /* regwr REGARRAY index src
392 * REGARRAY[index] = src
393 * index = HMEFTI, src = HMEFTI
395 INSTR_REGWR_RHH, /* index = H, src = H */
396 INSTR_REGWR_RHM, /* index = H, src = MEFT */
397 INSTR_REGWR_RHI, /* index = H, src = I */
398 INSTR_REGWR_RMH, /* index = MEFT, src = H */
399 INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
400 INSTR_REGWR_RMI, /* index = MEFT, src = I */
401 INSTR_REGWR_RIH, /* index = I, src = H */
402 INSTR_REGWR_RIM, /* index = I, src = MEFT */
403 INSTR_REGWR_RII, /* index = I, src = I */
405 /* regadd REGARRAY index src
406 * REGARRAY[index] += src
407 * index = HMEFTI, src = HMEFTI
409 INSTR_REGADD_RHH, /* index = H, src = H */
410 INSTR_REGADD_RHM, /* index = H, src = MEFT */
411 INSTR_REGADD_RHI, /* index = H, src = I */
412 INSTR_REGADD_RMH, /* index = MEFT, src = H */
413 INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
414 INSTR_REGADD_RMI, /* index = MEFT, src = I */
415 INSTR_REGADD_RIH, /* index = I, src = H */
416 INSTR_REGADD_RIM, /* index = I, src = MEFT */
417 INSTR_REGADD_RII, /* index = I, src = I */
419 /* metprefetch METARRAY index
420 * prefetch METARRAY[index]
423 INSTR_METPREFETCH_H, /* index = H */
424 INSTR_METPREFETCH_M, /* index = MEFT */
425 INSTR_METPREFETCH_I, /* index = I */
427 /* meter METARRAY index length color_in color_out
428 * color_out = meter(METARRAY[index], length, color_in)
429 * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
431 INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
432 INSTR_METER_HHI, /* index = H, length = H, color_in = I */
433 INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
434 INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
435 INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
436 INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
437 INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
438 INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
439 INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
440 INSTR_METER_IHI, /* index = I, length = H, color_in = I */
441 INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
442 INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
449 /* learn LEARNER ACTION_NAME */
453 INSTR_LEARNER_FORGET,
455 /* extern e.obj.func */
466 /* jmpv LABEL h.header
467 * Jump if header is valid
471 /* jmpnv LABEL h.header
472 * Jump if header is invalid
477 * Jump if table lookup hit
482 * Jump if table lookup miss
489 INSTR_JMP_ACTION_HIT,
491 /* jmpna LABEL ACTION
492 * Jump if action not run
494 INSTR_JMP_ACTION_MISS,
497 * Jump if a is equal to b
498 * a = HMEFT, b = HMEFTI
500 INSTR_JMP_EQ, /* a = MEFT, b = MEFT */
501 INSTR_JMP_EQ_MH, /* a = MEFT, b = H */
502 INSTR_JMP_EQ_HM, /* a = H, b = MEFT */
503 INSTR_JMP_EQ_HH, /* a = H, b = H */
504 INSTR_JMP_EQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
507 * Jump if a is not equal to b
508 * a = HMEFT, b = HMEFTI
510 INSTR_JMP_NEQ, /* a = MEFT, b = MEFT */
511 INSTR_JMP_NEQ_MH, /* a = MEFT, b = H */
512 INSTR_JMP_NEQ_HM, /* a = H, b = MEFT */
513 INSTR_JMP_NEQ_HH, /* a = H, b = H */
514 INSTR_JMP_NEQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
517 * Jump if a is less than b
518 * a = HMEFT, b = HMEFTI
520 INSTR_JMP_LT, /* a = MEFT, b = MEFT */
521 INSTR_JMP_LT_MH, /* a = MEFT, b = H */
522 INSTR_JMP_LT_HM, /* a = H, b = MEFT */
523 INSTR_JMP_LT_HH, /* a = H, b = H */
524 INSTR_JMP_LT_MI, /* a = MEFT, b = I */
525 INSTR_JMP_LT_HI, /* a = H, b = I */
528 * Jump if a is greater than b
529 * a = HMEFT, b = HMEFTI
531 INSTR_JMP_GT, /* a = MEFT, b = MEFT */
532 INSTR_JMP_GT_MH, /* a = MEFT, b = H */
533 INSTR_JMP_GT_HM, /* a = H, b = MEFT */
534 INSTR_JMP_GT_HH, /* a = H, b = H */
535 INSTR_JMP_GT_MI, /* a = MEFT, b = I */
536 INSTR_JMP_GT_HI, /* a = H, b = I */
544 struct instr_operand {
565 uint8_t header_id[8];
566 uint8_t struct_id[8];
571 struct instr_hdr_validity {
583 struct instr_extern_obj {
588 struct instr_extern_func {
592 struct instr_dst_src {
593 struct instr_operand dst;
595 struct instr_operand src;
600 struct instr_regarray {
605 struct instr_operand idx;
610 struct instr_operand dstsrc;
620 struct instr_operand idx;
624 struct instr_operand length;
627 struct instr_operand color_in;
628 uint32_t color_in_val;
631 struct instr_operand color_out;
636 uint8_t header_id[8];
637 uint8_t struct_id[8];
648 struct instruction *ip;
651 struct instr_operand a;
657 struct instr_operand b;
663 enum instruction_type type;
666 struct instr_hdr_validity valid;
667 struct instr_dst_src mov;
668 struct instr_regarray regarray;
669 struct instr_meter meter;
670 struct instr_dma dma;
671 struct instr_dst_src alu;
672 struct instr_table table;
673 struct instr_learn learn;
674 struct instr_extern_obj ext_obj;
675 struct instr_extern_func ext_func;
676 struct instr_jmp jmp;
680 struct instruction_data {
681 char label[RTE_SWX_NAME_SIZE];
682 char jmp_label[RTE_SWX_NAME_SIZE];
683 uint32_t n_users; /* user = jmp instruction to this instruction. */
691 TAILQ_ENTRY(action) node;
692 char name[RTE_SWX_NAME_SIZE];
693 struct struct_type *st;
694 int *args_endianness; /* 0 = Host Byte Order (HBO); 1 = Network Byte Order (NBO). */
695 struct instruction *instructions;
696 struct instruction_data *instruction_data;
697 uint32_t n_instructions;
701 TAILQ_HEAD(action_tailq, action);
707 TAILQ_ENTRY(table_type) node;
708 char name[RTE_SWX_NAME_SIZE];
709 enum rte_swx_table_match_type match_type;
710 struct rte_swx_table_ops ops;
713 TAILQ_HEAD(table_type_tailq, table_type);
716 enum rte_swx_table_match_type match_type;
721 TAILQ_ENTRY(table) node;
722 char name[RTE_SWX_NAME_SIZE];
723 char args[RTE_SWX_NAME_SIZE];
724 struct table_type *type; /* NULL when n_fields == 0. */
727 struct match_field *fields;
729 struct header *header; /* Only valid when n_fields > 0. */
732 struct action **actions;
733 struct action *default_action;
734 uint8_t *default_action_data;
736 int default_action_is_const;
737 uint32_t action_data_size_max;
743 TAILQ_HEAD(table_tailq, table);
745 struct table_runtime {
746 rte_swx_table_lookup_t func;
751 struct table_statistics {
752 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
753 uint64_t *n_pkts_action;
760 TAILQ_ENTRY(selector) node;
761 char name[RTE_SWX_NAME_SIZE];
763 struct field *group_id_field;
764 struct field **selector_fields;
765 uint32_t n_selector_fields;
766 struct header *selector_header;
767 struct field *member_id_field;
769 uint32_t n_groups_max;
770 uint32_t n_members_per_group_max;
775 TAILQ_HEAD(selector_tailq, selector);
777 struct selector_runtime {
779 uint8_t **group_id_buffer;
780 uint8_t **selector_buffer;
781 uint8_t **member_id_buffer;
784 struct selector_statistics {
792 TAILQ_ENTRY(learner) node;
793 char name[RTE_SWX_NAME_SIZE];
796 struct field **fields;
798 struct header *header;
801 struct action **actions;
802 struct field **action_arg;
803 struct action *default_action;
804 uint8_t *default_action_data;
806 int default_action_is_const;
807 uint32_t action_data_size_max;
814 TAILQ_HEAD(learner_tailq, learner);
816 struct learner_runtime {
819 uint8_t **action_data;
822 struct learner_statistics {
823 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
824 uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
825 uint64_t n_pkts_forget;
826 uint64_t *n_pkts_action;
833 TAILQ_ENTRY(regarray) node;
834 char name[RTE_SWX_NAME_SIZE];
840 TAILQ_HEAD(regarray_tailq, regarray);
842 struct regarray_runtime {
850 struct meter_profile {
851 TAILQ_ENTRY(meter_profile) node;
852 char name[RTE_SWX_NAME_SIZE];
853 struct rte_meter_trtcm_params params;
854 struct rte_meter_trtcm_profile profile;
858 TAILQ_HEAD(meter_profile_tailq, meter_profile);
861 TAILQ_ENTRY(metarray) node;
862 char name[RTE_SWX_NAME_SIZE];
867 TAILQ_HEAD(metarray_tailq, metarray);
870 struct rte_meter_trtcm m;
871 struct meter_profile *profile;
872 enum rte_color color_mask;
875 uint64_t n_pkts[RTE_COLORS];
876 uint64_t n_bytes[RTE_COLORS];
879 struct metarray_runtime {
880 struct meter *metarray;
889 struct rte_swx_pkt pkt;
895 /* Packet headers. */
896 struct header_runtime *headers; /* Extracted or generated headers. */
897 struct header_out_runtime *headers_out; /* Emitted headers. */
898 uint8_t *header_storage;
899 uint8_t *header_out_storage;
900 uint64_t valid_headers;
901 uint32_t n_headers_out;
903 /* Packet meta-data. */
907 struct table_runtime *tables;
908 struct selector_runtime *selectors;
909 struct learner_runtime *learners;
910 struct rte_swx_table_state *table_state;
912 int hit; /* 0 = Miss, 1 = Hit. */
916 /* Extern objects and functions. */
917 struct extern_obj_runtime *extern_objs;
918 struct extern_func_runtime *extern_funcs;
921 struct instruction *ip;
922 struct instruction *ret;
925 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
926 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
927 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
929 #define HEADER_VALID(thread, header_id) \
930 MASK64_BIT_GET((thread)->valid_headers, header_id)
932 static inline uint64_t
933 instr_operand_hbo(struct thread *t, const struct instr_operand *x)
935 uint8_t *x_struct = t->structs[x->struct_id];
936 uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
937 uint64_t x64 = *x64_ptr;
938 uint64_t x64_mask = UINT64_MAX >> (64 - x->n_bits);
940 return x64 & x64_mask;
943 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
945 static inline uint64_t
946 instr_operand_nbo(struct thread *t, const struct instr_operand *x)
948 uint8_t *x_struct = t->structs[x->struct_id];
949 uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
950 uint64_t x64 = *x64_ptr;
952 return ntoh64(x64) >> (64 - x->n_bits);
957 #define instr_operand_nbo instr_operand_hbo
961 #define ALU(thread, ip, operator) \
963 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
964 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
965 uint64_t dst64 = *dst64_ptr; \
966 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
967 uint64_t dst = dst64 & dst64_mask; \
969 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
970 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
971 uint64_t src64 = *src64_ptr; \
972 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
973 uint64_t src = src64 & src64_mask; \
975 uint64_t result = dst operator src; \
977 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
980 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
982 #define ALU_MH(thread, ip, operator) \
984 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
985 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
986 uint64_t dst64 = *dst64_ptr; \
987 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
988 uint64_t dst = dst64 & dst64_mask; \
990 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
991 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
992 uint64_t src64 = *src64_ptr; \
993 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
995 uint64_t result = dst operator src; \
997 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1000 #define ALU_HM(thread, ip, operator) \
1002 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1003 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1004 uint64_t dst64 = *dst64_ptr; \
1005 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1006 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1008 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1009 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1010 uint64_t src64 = *src64_ptr; \
1011 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1012 uint64_t src = src64 & src64_mask; \
1014 uint64_t result = dst operator src; \
1015 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1017 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1020 #define ALU_HM_FAST(thread, ip, operator) \
1022 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1023 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1024 uint64_t dst64 = *dst64_ptr; \
1025 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1026 uint64_t dst = dst64 & dst64_mask; \
1028 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1029 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1030 uint64_t src64 = *src64_ptr; \
1031 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1032 uint64_t src = hton64(src64 & src64_mask) >> (64 - (ip)->alu.dst.n_bits); \
1034 uint64_t result = dst operator src; \
1036 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1039 #define ALU_HH(thread, ip, operator) \
1041 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1042 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1043 uint64_t dst64 = *dst64_ptr; \
1044 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1045 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1047 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1048 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1049 uint64_t src64 = *src64_ptr; \
1050 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1052 uint64_t result = dst operator src; \
1053 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1055 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1058 #define ALU_HH_FAST(thread, ip, operator) \
1060 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1061 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1062 uint64_t dst64 = *dst64_ptr; \
1063 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1064 uint64_t dst = dst64 & dst64_mask; \
1066 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1067 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1068 uint64_t src64 = *src64_ptr; \
1069 uint64_t src = (src64 << (64 - (ip)->alu.src.n_bits)) >> (64 - (ip)->alu.dst.n_bits); \
1071 uint64_t result = dst operator src; \
1073 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1080 #define ALU_HM_FAST ALU
1082 #define ALU_HH_FAST ALU
1086 #define ALU_I(thread, ip, operator) \
1088 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1089 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1090 uint64_t dst64 = *dst64_ptr; \
1091 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1092 uint64_t dst = dst64 & dst64_mask; \
1094 uint64_t src = (ip)->alu.src_val; \
1096 uint64_t result = dst operator src; \
1098 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1101 #define ALU_MI ALU_I
1103 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1105 #define ALU_HI(thread, ip, operator) \
1107 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1108 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1109 uint64_t dst64 = *dst64_ptr; \
1110 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1111 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1113 uint64_t src = (ip)->alu.src_val; \
1115 uint64_t result = dst operator src; \
1116 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1118 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1123 #define ALU_HI ALU_I
1127 #define MOV(thread, ip) \
1129 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1130 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1131 uint64_t dst64 = *dst64_ptr; \
1132 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1134 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1135 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1136 uint64_t src64 = *src64_ptr; \
1137 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1138 uint64_t src = src64 & src64_mask; \
1140 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1143 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1145 #define MOV_MH(thread, ip) \
1147 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1148 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1149 uint64_t dst64 = *dst64_ptr; \
1150 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1152 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1153 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1154 uint64_t src64 = *src64_ptr; \
1155 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1157 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1160 #define MOV_HM(thread, ip) \
1162 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1163 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1164 uint64_t dst64 = *dst64_ptr; \
1165 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1167 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1168 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1169 uint64_t src64 = *src64_ptr; \
1170 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1171 uint64_t src = src64 & src64_mask; \
1173 src = hton64(src) >> (64 - (ip)->mov.dst.n_bits); \
1174 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1177 #define MOV_HH(thread, ip) \
1179 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1180 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1181 uint64_t dst64 = *dst64_ptr; \
1182 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1184 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1185 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1186 uint64_t src64 = *src64_ptr; \
1188 uint64_t src = src64 << (64 - (ip)->mov.src.n_bits); \
1189 src = src >> (64 - (ip)->mov.dst.n_bits); \
1190 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1201 #define MOV_I(thread, ip) \
1203 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1204 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1205 uint64_t dst64 = *dst64_ptr; \
1206 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1208 uint64_t src = (ip)->mov.src_val; \
1210 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1213 #define JMP_CMP(thread, ip, operator) \
1215 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1216 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1217 uint64_t a64 = *a64_ptr; \
1218 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1219 uint64_t a = a64 & a64_mask; \
1221 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1222 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1223 uint64_t b64 = *b64_ptr; \
1224 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1225 uint64_t b = b64 & b64_mask; \
1227 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1230 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1232 #define JMP_CMP_MH(thread, ip, operator) \
1234 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1235 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1236 uint64_t a64 = *a64_ptr; \
1237 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1238 uint64_t a = a64 & a64_mask; \
1240 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1241 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1242 uint64_t b64 = *b64_ptr; \
1243 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1245 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1248 #define JMP_CMP_HM(thread, ip, operator) \
1250 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1251 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1252 uint64_t a64 = *a64_ptr; \
1253 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1255 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1256 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1257 uint64_t b64 = *b64_ptr; \
1258 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1259 uint64_t b = b64 & b64_mask; \
1261 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1264 #define JMP_CMP_HH(thread, ip, operator) \
1266 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1267 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1268 uint64_t a64 = *a64_ptr; \
1269 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1271 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1272 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1273 uint64_t b64 = *b64_ptr; \
1274 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1276 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1279 #define JMP_CMP_HH_FAST(thread, ip, operator) \
1281 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1282 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1283 uint64_t a64 = *a64_ptr; \
1284 uint64_t a = a64 << (64 - (ip)->jmp.a.n_bits); \
1286 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1287 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1288 uint64_t b64 = *b64_ptr; \
1289 uint64_t b = b64 << (64 - (ip)->jmp.b.n_bits); \
1291 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1296 #define JMP_CMP_MH JMP_CMP
1297 #define JMP_CMP_HM JMP_CMP
1298 #define JMP_CMP_HH JMP_CMP
1299 #define JMP_CMP_HH_FAST JMP_CMP
1303 #define JMP_CMP_I(thread, ip, operator) \
1305 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1306 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1307 uint64_t a64 = *a64_ptr; \
1308 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1309 uint64_t a = a64 & a64_mask; \
1311 uint64_t b = (ip)->jmp.b_val; \
1313 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1316 #define JMP_CMP_MI JMP_CMP_I
1318 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1320 #define JMP_CMP_HI(thread, ip, operator) \
1322 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1323 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1324 uint64_t a64 = *a64_ptr; \
1325 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1327 uint64_t b = (ip)->jmp.b_val; \
1329 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1334 #define JMP_CMP_HI JMP_CMP_I
1338 #define METADATA_READ(thread, offset, n_bits) \
1340 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1341 uint64_t m64 = *m64_ptr; \
1342 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1346 #define METADATA_WRITE(thread, offset, n_bits, value) \
1348 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1349 uint64_t m64 = *m64_ptr; \
1350 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1352 uint64_t m_new = value; \
1354 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1357 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1358 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1361 struct rte_swx_pipeline {
1362 struct struct_type_tailq struct_types;
1363 struct port_in_type_tailq port_in_types;
1364 struct port_in_tailq ports_in;
1365 struct port_out_type_tailq port_out_types;
1366 struct port_out_tailq ports_out;
1367 struct extern_type_tailq extern_types;
1368 struct extern_obj_tailq extern_objs;
1369 struct extern_func_tailq extern_funcs;
1370 struct header_tailq headers;
1371 struct struct_type *metadata_st;
1372 uint32_t metadata_struct_id;
1373 struct action_tailq actions;
1374 struct table_type_tailq table_types;
1375 struct table_tailq tables;
1376 struct selector_tailq selectors;
1377 struct learner_tailq learners;
1378 struct regarray_tailq regarrays;
1379 struct meter_profile_tailq meter_profiles;
1380 struct metarray_tailq metarrays;
1382 struct port_in_runtime *in;
1383 struct port_out_runtime *out;
1384 struct instruction **action_instructions;
1385 struct rte_swx_table_state *table_state;
1386 struct table_statistics *table_stats;
1387 struct selector_statistics *selector_stats;
1388 struct learner_statistics *learner_stats;
1389 struct regarray_runtime *regarray_runtime;
1390 struct metarray_runtime *metarray_runtime;
1391 struct instruction *instructions;
1392 struct instruction_data *instruction_data;
1393 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1396 uint32_t n_ports_in;
1397 uint32_t n_ports_out;
1398 uint32_t n_extern_objs;
1399 uint32_t n_extern_funcs;
1402 uint32_t n_selectors;
1403 uint32_t n_learners;
1404 uint32_t n_regarrays;
1405 uint32_t n_metarrays;
1409 uint32_t n_instructions;
1418 pipeline_port_inc(struct rte_swx_pipeline *p)
1420 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
1424 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
1426 t->ip = p->instructions;
1430 thread_ip_set(struct thread *t, struct instruction *ip)
1436 thread_ip_action_call(struct rte_swx_pipeline *p,
1441 t->ip = p->action_instructions[action_id];
1445 thread_ip_inc(struct rte_swx_pipeline *p);
1448 thread_ip_inc(struct rte_swx_pipeline *p)
1450 struct thread *t = &p->threads[p->thread_id];
1456 thread_ip_inc_cond(struct thread *t, int cond)
1462 thread_yield(struct rte_swx_pipeline *p)
1464 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1468 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
1470 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1477 __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1479 struct port_in_runtime *port = &p->in[p->port_id];
1480 struct rte_swx_pkt *pkt = &t->pkt;
1484 pkt_received = port->pkt_rx(port->obj, pkt);
1485 t->ptr = &pkt->pkt[pkt->offset];
1486 rte_prefetch0(t->ptr);
1488 TRACE("[Thread %2u] rx %s from port %u\n",
1490 pkt_received ? "1 pkt" : "0 pkts",
1494 t->valid_headers = 0;
1495 t->n_headers_out = 0;
1498 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
1501 t->table_state = p->table_state;
1504 pipeline_port_inc(p);
1506 return pkt_received;
1510 instr_rx_exec(struct rte_swx_pipeline *p)
1512 struct thread *t = &p->threads[p->thread_id];
1513 struct instruction *ip = t->ip;
1517 pkt_received = __instr_rx_exec(p, t, ip);
1520 thread_ip_inc_cond(t, pkt_received);
1528 emit_handler(struct thread *t)
1530 struct header_out_runtime *h0 = &t->headers_out[0];
1531 struct header_out_runtime *h1 = &t->headers_out[1];
1532 uint32_t offset = 0, i;
1534 /* No header change or header decapsulation. */
1535 if ((t->n_headers_out == 1) &&
1536 (h0->ptr + h0->n_bytes == t->ptr)) {
1537 TRACE("Emit handler: no header change or header decap.\n");
1539 t->pkt.offset -= h0->n_bytes;
1540 t->pkt.length += h0->n_bytes;
1545 /* Header encapsulation (optionally, with prior header decasulation). */
1546 if ((t->n_headers_out == 2) &&
1547 (h1->ptr + h1->n_bytes == t->ptr) &&
1548 (h0->ptr == h0->ptr0)) {
1551 TRACE("Emit handler: header encapsulation.\n");
1553 offset = h0->n_bytes + h1->n_bytes;
1554 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1555 t->pkt.offset -= offset;
1556 t->pkt.length += offset;
1561 /* For any other case. */
1562 TRACE("Emit handler: complex case.\n");
1564 for (i = 0; i < t->n_headers_out; i++) {
1565 struct header_out_runtime *h = &t->headers_out[i];
1567 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1568 offset += h->n_bytes;
1572 memcpy(t->ptr - offset, t->header_out_storage, offset);
1573 t->pkt.offset -= offset;
1574 t->pkt.length += offset;
1579 __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1581 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1582 struct port_out_runtime *port = &p->out[port_id];
1583 struct rte_swx_pkt *pkt = &t->pkt;
1585 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1593 port->pkt_tx(port->obj, pkt);
1597 __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1599 uint64_t port_id = ip->io.io.val;
1600 struct port_out_runtime *port = &p->out[port_id];
1601 struct rte_swx_pkt *pkt = &t->pkt;
1603 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1611 port->pkt_tx(port->obj, pkt);
1618 __instr_hdr_extract_many_exec(struct rte_swx_pipeline *p __rte_unused,
1620 const struct instruction *ip,
1623 uint64_t valid_headers = t->valid_headers;
1624 uint8_t *ptr = t->ptr;
1625 uint32_t offset = t->pkt.offset;
1626 uint32_t length = t->pkt.length;
1629 for (i = 0; i < n_extract; i++) {
1630 uint32_t header_id = ip->io.hdr.header_id[i];
1631 uint32_t struct_id = ip->io.hdr.struct_id[i];
1632 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1634 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1640 t->structs[struct_id] = ptr;
1641 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1650 t->valid_headers = valid_headers;
1653 t->pkt.offset = offset;
1654 t->pkt.length = length;
1659 __instr_hdr_extract_exec(struct rte_swx_pipeline *p,
1661 const struct instruction *ip)
1663 __instr_hdr_extract_many_exec(p, t, ip, 1);
1667 __instr_hdr_extract2_exec(struct rte_swx_pipeline *p,
1669 const struct instruction *ip)
1671 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1673 __instr_hdr_extract_many_exec(p, t, ip, 2);
1677 __instr_hdr_extract3_exec(struct rte_swx_pipeline *p,
1679 const struct instruction *ip)
1681 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1683 __instr_hdr_extract_many_exec(p, t, ip, 3);
1687 __instr_hdr_extract4_exec(struct rte_swx_pipeline *p,
1689 const struct instruction *ip)
1691 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1693 __instr_hdr_extract_many_exec(p, t, ip, 4);
1697 __instr_hdr_extract5_exec(struct rte_swx_pipeline *p,
1699 const struct instruction *ip)
1701 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1703 __instr_hdr_extract_many_exec(p, t, ip, 5);
1707 __instr_hdr_extract6_exec(struct rte_swx_pipeline *p,
1709 const struct instruction *ip)
1711 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1713 __instr_hdr_extract_many_exec(p, t, ip, 6);
1717 __instr_hdr_extract7_exec(struct rte_swx_pipeline *p,
1719 const struct instruction *ip)
1721 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1723 __instr_hdr_extract_many_exec(p, t, ip, 7);
1727 __instr_hdr_extract8_exec(struct rte_swx_pipeline *p,
1729 const struct instruction *ip)
1731 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1733 __instr_hdr_extract_many_exec(p, t, ip, 8);
1737 __instr_hdr_extract_m_exec(struct rte_swx_pipeline *p __rte_unused,
1739 const struct instruction *ip)
1741 uint64_t valid_headers = t->valid_headers;
1742 uint8_t *ptr = t->ptr;
1743 uint32_t offset = t->pkt.offset;
1744 uint32_t length = t->pkt.length;
1746 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1747 uint32_t header_id = ip->io.hdr.header_id[0];
1748 uint32_t struct_id = ip->io.hdr.struct_id[0];
1749 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1751 struct header_runtime *h = &t->headers[header_id];
1753 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1759 n_bytes += n_bytes_last;
1762 t->structs[struct_id] = ptr;
1763 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1764 h->n_bytes = n_bytes;
1767 t->pkt.offset = offset + n_bytes;
1768 t->pkt.length = length - n_bytes;
1769 t->ptr = ptr + n_bytes;
1773 __instr_hdr_lookahead_exec(struct rte_swx_pipeline *p __rte_unused,
1775 const struct instruction *ip)
1777 uint64_t valid_headers = t->valid_headers;
1778 uint8_t *ptr = t->ptr;
1780 uint32_t header_id = ip->io.hdr.header_id[0];
1781 uint32_t struct_id = ip->io.hdr.struct_id[0];
1783 TRACE("[Thread %2u]: lookahead header %u\n",
1788 t->structs[struct_id] = ptr;
1789 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1796 __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
1798 const struct instruction *ip,
1801 uint64_t valid_headers = t->valid_headers;
1802 uint32_t n_headers_out = t->n_headers_out;
1803 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
1804 uint8_t *ho_ptr = NULL;
1805 uint32_t ho_nbytes = 0, first = 1, i;
1807 for (i = 0; i < n_emit; i++) {
1808 uint32_t header_id = ip->io.hdr.header_id[i];
1809 uint32_t struct_id = ip->io.hdr.struct_id[i];
1811 struct header_runtime *hi = &t->headers[header_id];
1812 uint8_t *hi_ptr0 = hi->ptr0;
1813 uint32_t n_bytes = hi->n_bytes;
1815 uint8_t *hi_ptr = t->structs[struct_id];
1817 if (!MASK64_BIT_GET(valid_headers, header_id))
1820 TRACE("[Thread %2u]: emit header %u\n",
1828 if (!t->n_headers_out) {
1829 ho = &t->headers_out[0];
1835 ho_nbytes = n_bytes;
1842 ho_nbytes = ho->n_bytes;
1846 if (ho_ptr + ho_nbytes == hi_ptr) {
1847 ho_nbytes += n_bytes;
1849 ho->n_bytes = ho_nbytes;
1856 ho_nbytes = n_bytes;
1862 ho->n_bytes = ho_nbytes;
1863 t->n_headers_out = n_headers_out;
1867 __instr_hdr_emit_exec(struct rte_swx_pipeline *p,
1869 const struct instruction *ip)
1871 __instr_hdr_emit_many_exec(p, t, ip, 1);
1875 __instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p,
1877 const struct instruction *ip)
1879 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1881 __instr_hdr_emit_many_exec(p, t, ip, 1);
1882 __instr_tx_exec(p, t, ip);
1886 __instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p,
1888 const struct instruction *ip)
1890 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1892 __instr_hdr_emit_many_exec(p, t, ip, 2);
1893 __instr_tx_exec(p, t, ip);
1897 __instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p,
1899 const struct instruction *ip)
1901 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1903 __instr_hdr_emit_many_exec(p, t, ip, 3);
1904 __instr_tx_exec(p, t, ip);
1908 __instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p,
1910 const struct instruction *ip)
1912 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1914 __instr_hdr_emit_many_exec(p, t, ip, 4);
1915 __instr_tx_exec(p, t, ip);
1919 __instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p,
1921 const struct instruction *ip)
1923 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1925 __instr_hdr_emit_many_exec(p, t, ip, 5);
1926 __instr_tx_exec(p, t, ip);
1930 __instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p,
1932 const struct instruction *ip)
1934 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1936 __instr_hdr_emit_many_exec(p, t, ip, 6);
1937 __instr_tx_exec(p, t, ip);
1941 __instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p,
1943 const struct instruction *ip)
1945 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1947 __instr_hdr_emit_many_exec(p, t, ip, 7);
1948 __instr_tx_exec(p, t, ip);
1952 __instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p,
1954 const struct instruction *ip)
1956 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n", p->thread_id);
1958 __instr_hdr_emit_many_exec(p, t, ip, 8);
1959 __instr_tx_exec(p, t, ip);
1966 __instr_hdr_validate_exec(struct rte_swx_pipeline *p __rte_unused,
1968 const struct instruction *ip)
1970 uint32_t header_id = ip->valid.header_id;
1972 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
1975 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
1982 __instr_hdr_invalidate_exec(struct rte_swx_pipeline *p __rte_unused,
1984 const struct instruction *ip)
1986 uint32_t header_id = ip->valid.header_id;
1988 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
1991 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
1998 __instr_learn_exec(struct rte_swx_pipeline *p,
2000 const struct instruction *ip)
2002 uint64_t action_id = ip->learn.action_id;
2003 uint32_t learner_id = t->learner_id;
2004 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2005 p->n_selectors + learner_id];
2006 struct learner_runtime *l = &t->learners[learner_id];
2007 struct learner_statistics *stats = &p->learner_stats[learner_id];
2011 status = rte_swx_table_learner_add(ts->obj,
2015 l->action_data[action_id]);
2017 TRACE("[Thread %2u] learner %u learn %s\n",
2020 status ? "ok" : "error");
2022 stats->n_pkts_learn[status] += 1;
2029 __instr_forget_exec(struct rte_swx_pipeline *p,
2031 const struct instruction *ip __rte_unused)
2033 uint32_t learner_id = t->learner_id;
2034 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2035 p->n_selectors + learner_id];
2036 struct learner_runtime *l = &t->learners[learner_id];
2037 struct learner_statistics *stats = &p->learner_stats[learner_id];
2040 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2042 TRACE("[Thread %2u] learner %u forget\n",
2046 stats->n_pkts_forget += 1;
2052 static inline uint32_t
2053 __instr_extern_obj_exec(struct rte_swx_pipeline *p __rte_unused,
2055 const struct instruction *ip)
2057 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2058 uint32_t func_id = ip->ext_obj.func_id;
2059 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2060 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2063 TRACE("[Thread %2u] extern obj %u member func %u\n",
2068 done = func(obj->obj, obj->mailbox);
2073 static inline uint32_t
2074 __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
2076 const struct instruction *ip)
2078 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2079 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2080 rte_swx_extern_func_t func = ext_func->func;
2083 TRACE("[Thread %2u] extern func %u\n",
2087 done = func(ext_func->mailbox);
2096 __instr_mov_exec(struct rte_swx_pipeline *p __rte_unused,
2098 const struct instruction *ip)
2100 TRACE("[Thread %2u] mov\n", p->thread_id);
2106 __instr_mov_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2108 const struct instruction *ip)
2110 TRACE("[Thread %2u] mov (mh)\n", p->thread_id);
2116 __instr_mov_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2118 const struct instruction *ip)
2120 TRACE("[Thread %2u] mov (hm)\n", p->thread_id);
2126 __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2128 const struct instruction *ip)
2130 TRACE("[Thread %2u] mov (hh)\n", p->thread_id);
2136 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
2138 const struct instruction *ip)
2140 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val);
2149 __instr_dma_ht_many_exec(struct rte_swx_pipeline *p __rte_unused,
2151 const struct instruction *ip,
2154 uint8_t *action_data = t->structs[0];
2155 uint64_t valid_headers = t->valid_headers;
2158 for (i = 0; i < n_dma; i++) {
2159 uint32_t header_id = ip->dma.dst.header_id[i];
2160 uint32_t struct_id = ip->dma.dst.struct_id[i];
2161 uint32_t offset = ip->dma.src.offset[i];
2162 uint32_t n_bytes = ip->dma.n_bytes[i];
2164 struct header_runtime *h = &t->headers[header_id];
2165 uint8_t *h_ptr0 = h->ptr0;
2166 uint8_t *h_ptr = t->structs[struct_id];
2168 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2170 void *src = &action_data[offset];
2172 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2175 memcpy(dst, src, n_bytes);
2176 t->structs[struct_id] = dst;
2177 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2180 t->valid_headers = valid_headers;
2184 __instr_dma_ht_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2186 __instr_dma_ht_many_exec(p, t, ip, 1);
2190 __instr_dma_ht2_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2192 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2194 __instr_dma_ht_many_exec(p, t, ip, 2);
2198 __instr_dma_ht3_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2200 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2202 __instr_dma_ht_many_exec(p, t, ip, 3);
2206 __instr_dma_ht4_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2208 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2210 __instr_dma_ht_many_exec(p, t, ip, 4);
2214 __instr_dma_ht5_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2216 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2218 __instr_dma_ht_many_exec(p, t, ip, 5);
2222 __instr_dma_ht6_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2224 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2226 __instr_dma_ht_many_exec(p, t, ip, 6);
2230 __instr_dma_ht7_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2232 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2234 __instr_dma_ht_many_exec(p, t, ip, 7);
2238 __instr_dma_ht8_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2240 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2242 __instr_dma_ht_many_exec(p, t, ip, 8);
2249 __instr_alu_add_exec(struct rte_swx_pipeline *p __rte_unused,
2251 const struct instruction *ip)
2253 TRACE("[Thread %2u] add\n", p->thread_id);
2259 __instr_alu_add_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2261 const struct instruction *ip)
2263 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
2269 __instr_alu_add_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2271 const struct instruction *ip)
2273 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
2279 __instr_alu_add_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2281 const struct instruction *ip)
2283 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
2289 __instr_alu_add_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2291 const struct instruction *ip)
2293 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
2299 __instr_alu_add_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2301 const struct instruction *ip)
2303 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
2309 __instr_alu_sub_exec(struct rte_swx_pipeline *p __rte_unused,
2311 const struct instruction *ip)
2313 TRACE("[Thread %2u] sub\n", p->thread_id);
2319 __instr_alu_sub_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2321 const struct instruction *ip)
2323 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
2329 __instr_alu_sub_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2331 const struct instruction *ip)
2333 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
2339 __instr_alu_sub_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2341 const struct instruction *ip)
2343 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
2349 __instr_alu_sub_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2351 const struct instruction *ip)
2353 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
2359 __instr_alu_sub_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2361 const struct instruction *ip)
2363 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
2369 __instr_alu_shl_exec(struct rte_swx_pipeline *p __rte_unused,
2371 const struct instruction *ip)
2373 TRACE("[Thread %2u] shl\n", p->thread_id);
2379 __instr_alu_shl_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2381 const struct instruction *ip)
2383 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
2389 __instr_alu_shl_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2391 const struct instruction *ip)
2393 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
2399 __instr_alu_shl_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2401 const struct instruction *ip)
2403 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
2409 __instr_alu_shl_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2411 const struct instruction *ip)
2413 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
2419 __instr_alu_shl_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2421 const struct instruction *ip)
2423 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
2429 __instr_alu_shr_exec(struct rte_swx_pipeline *p __rte_unused,
2431 const struct instruction *ip)
2433 TRACE("[Thread %2u] shr\n", p->thread_id);
2439 __instr_alu_shr_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2441 const struct instruction *ip)
2443 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
2449 __instr_alu_shr_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2451 const struct instruction *ip)
2453 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
2459 __instr_alu_shr_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2461 const struct instruction *ip)
2463 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
2469 __instr_alu_shr_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2471 const struct instruction *ip)
2473 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
2480 __instr_alu_shr_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2482 const struct instruction *ip)
2484 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
2490 __instr_alu_and_exec(struct rte_swx_pipeline *p __rte_unused,
2492 const struct instruction *ip)
2494 TRACE("[Thread %2u] and\n", p->thread_id);
2500 __instr_alu_and_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2502 const struct instruction *ip)
2504 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
2510 __instr_alu_and_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2512 const struct instruction *ip)
2514 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
2516 ALU_HM_FAST(t, ip, &);
2520 __instr_alu_and_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2522 const struct instruction *ip)
2524 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
2526 ALU_HH_FAST(t, ip, &);
2530 __instr_alu_and_i_exec(struct rte_swx_pipeline *p __rte_unused,
2532 const struct instruction *ip)
2534 TRACE("[Thread %2u] and (i)\n", p->thread_id);
2540 __instr_alu_or_exec(struct rte_swx_pipeline *p __rte_unused,
2542 const struct instruction *ip)
2544 TRACE("[Thread %2u] or\n", p->thread_id);
2550 __instr_alu_or_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2552 const struct instruction *ip)
2554 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
2560 __instr_alu_or_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2562 const struct instruction *ip)
2564 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
2566 ALU_HM_FAST(t, ip, |);
2570 __instr_alu_or_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2572 const struct instruction *ip)
2574 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
2576 ALU_HH_FAST(t, ip, |);
2580 __instr_alu_or_i_exec(struct rte_swx_pipeline *p __rte_unused,
2582 const struct instruction *ip)
2584 TRACE("[Thread %2u] or (i)\n", p->thread_id);
2590 __instr_alu_xor_exec(struct rte_swx_pipeline *p __rte_unused,
2592 const struct instruction *ip)
2594 TRACE("[Thread %2u] xor\n", p->thread_id);
2600 __instr_alu_xor_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2602 const struct instruction *ip)
2604 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
2610 __instr_alu_xor_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2612 const struct instruction *ip)
2614 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
2616 ALU_HM_FAST(t, ip, ^);
2620 __instr_alu_xor_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2622 const struct instruction *ip)
2624 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
2626 ALU_HH_FAST(t, ip, ^);
2630 __instr_alu_xor_i_exec(struct rte_swx_pipeline *p __rte_unused,
2632 const struct instruction *ip)
2634 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
2640 __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
2642 const struct instruction *ip)
2644 uint8_t *dst_struct, *src_struct;
2645 uint16_t *dst16_ptr, dst;
2646 uint64_t *src64_ptr, src64, src64_mask, src;
2649 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
2652 dst_struct = t->structs[ip->alu.dst.struct_id];
2653 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2656 src_struct = t->structs[ip->alu.src.struct_id];
2657 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2659 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2660 src = src64 & src64_mask;
2665 /* The first input (r) is a 16-bit number. The second and the third
2666 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
2667 * three numbers (output r) is a 34-bit number.
2669 r += (src >> 32) + (src & 0xFFFFFFFF);
2671 /* The first input is a 16-bit number. The second input is an 18-bit
2672 * number. In the worst case scenario, the sum of the two numbers is a
2675 r = (r & 0xFFFF) + (r >> 16);
2677 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2678 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
2680 r = (r & 0xFFFF) + (r >> 16);
2682 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2683 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2684 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
2685 * therefore the output r is always a 16-bit number.
2687 r = (r & 0xFFFF) + (r >> 16);
2692 *dst16_ptr = (uint16_t)r;
2696 __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
2698 const struct instruction *ip)
2700 uint8_t *dst_struct, *src_struct;
2701 uint16_t *dst16_ptr, dst;
2702 uint64_t *src64_ptr, src64, src64_mask, src;
2705 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
2708 dst_struct = t->structs[ip->alu.dst.struct_id];
2709 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2712 src_struct = t->structs[ip->alu.src.struct_id];
2713 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2715 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2716 src = src64 & src64_mask;
2721 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
2722 * the following sequence of operations in 2's complement arithmetic:
2723 * a '- b = (a - b) % 0xFFFF.
2725 * In order to prevent an underflow for the below subtraction, in which
2726 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
2727 * minuend), we first add a multiple of the 0xFFFF modulus to the
2728 * minuend. The number we add to the minuend needs to be a 34-bit number
2729 * or higher, so for readability reasons we picked the 36-bit multiple.
2730 * We are effectively turning the 16-bit minuend into a 36-bit number:
2731 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
2733 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
2735 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
2736 * result (the output r) is a 36-bit number.
2738 r -= (src >> 32) + (src & 0xFFFFFFFF);
2740 /* The first input is a 16-bit number. The second input is a 20-bit
2741 * number. Their sum is a 21-bit number.
2743 r = (r & 0xFFFF) + (r >> 16);
2745 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2746 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
2748 r = (r & 0xFFFF) + (r >> 16);
2750 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2751 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2752 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2753 * generated, therefore the output r is always a 16-bit number.
2755 r = (r & 0xFFFF) + (r >> 16);
2760 *dst16_ptr = (uint16_t)r;
2764 __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
2766 const struct instruction *ip)
2768 uint8_t *dst_struct, *src_struct;
2769 uint16_t *dst16_ptr;
2770 uint32_t *src32_ptr;
2773 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
2776 dst_struct = t->structs[ip->alu.dst.struct_id];
2777 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2779 src_struct = t->structs[ip->alu.src.struct_id];
2780 src32_ptr = (uint32_t *)&src_struct[0];
2782 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
2783 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
2784 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
2785 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
2786 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
2788 /* The first input is a 16-bit number. The second input is a 19-bit
2789 * number. Their sum is a 20-bit number.
2791 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2793 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2794 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
2796 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2798 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2799 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2800 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
2801 * generated, therefore the output r is always a 16-bit number.
2803 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2806 r0 = r0 ? r0 : 0xFFFF;
2808 *dst16_ptr = (uint16_t)r0;
2812 __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
2814 const struct instruction *ip)
2816 uint8_t *dst_struct, *src_struct;
2817 uint16_t *dst16_ptr;
2818 uint32_t *src32_ptr;
2822 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
2825 dst_struct = t->structs[ip->alu.dst.struct_id];
2826 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2828 src_struct = t->structs[ip->alu.src.struct_id];
2829 src32_ptr = (uint32_t *)&src_struct[0];
2831 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
2832 * Therefore, in the worst case scenario, a 35-bit number is added to a
2833 * 16-bit number (the input r), so the output r is 36-bit number.
2835 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
2838 /* The first input is a 16-bit number. The second input is a 20-bit
2839 * number. Their sum is a 21-bit number.
2841 r = (r & 0xFFFF) + (r >> 16);
2843 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2844 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
2846 r = (r & 0xFFFF) + (r >> 16);
2848 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2849 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2850 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2851 * generated, therefore the output r is always a 16-bit number.
2853 r = (r & 0xFFFF) + (r >> 16);
2858 *dst16_ptr = (uint16_t)r;
2864 static inline uint64_t *
2865 instr_regarray_regarray(struct rte_swx_pipeline *p, const struct instruction *ip)
2867 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2871 static inline uint64_t
2872 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2874 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2876 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2877 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2878 uint64_t idx64 = *idx64_ptr;
2879 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
2880 uint64_t idx = idx64 & idx64_mask & r->size_mask;
2885 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2887 static inline uint64_t
2888 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2890 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2892 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2893 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2894 uint64_t idx64 = *idx64_ptr;
2895 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
2902 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
2906 static inline uint64_t
2907 instr_regarray_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
2909 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2911 uint64_t idx = ip->regarray.idx_val & r->size_mask;
2916 static inline uint64_t
2917 instr_regarray_src_hbo(struct thread *t, const struct instruction *ip)
2919 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
2920 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
2921 uint64_t src64 = *src64_ptr;
2922 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
2923 uint64_t src = src64 & src64_mask;
2928 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2930 static inline uint64_t
2931 instr_regarray_src_nbo(struct thread *t, const struct instruction *ip)
2933 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
2934 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
2935 uint64_t src64 = *src64_ptr;
2936 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
2943 #define instr_regarray_src_nbo instr_regarray_src_hbo
2948 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
2950 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
2951 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
2952 uint64_t dst64 = *dst64_ptr;
2953 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
2955 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
2959 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2962 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
2964 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
2965 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
2966 uint64_t dst64 = *dst64_ptr;
2967 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
2969 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
2970 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
2975 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
2980 __instr_regprefetch_rh_exec(struct rte_swx_pipeline *p,
2982 const struct instruction *ip)
2984 uint64_t *regarray, idx;
2986 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
2988 regarray = instr_regarray_regarray(p, ip);
2989 idx = instr_regarray_idx_nbo(p, t, ip);
2990 rte_prefetch0(®array[idx]);
2994 __instr_regprefetch_rm_exec(struct rte_swx_pipeline *p,
2996 const struct instruction *ip)
2998 uint64_t *regarray, idx;
3000 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
3002 regarray = instr_regarray_regarray(p, ip);
3003 idx = instr_regarray_idx_hbo(p, t, ip);
3004 rte_prefetch0(®array[idx]);
3008 __instr_regprefetch_ri_exec(struct rte_swx_pipeline *p,
3009 struct thread *t __rte_unused,
3010 const struct instruction *ip)
3012 uint64_t *regarray, idx;
3014 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
3016 regarray = instr_regarray_regarray(p, ip);
3017 idx = instr_regarray_idx_imm(p, ip);
3018 rte_prefetch0(®array[idx]);
3022 __instr_regrd_hrh_exec(struct rte_swx_pipeline *p,
3024 const struct instruction *ip)
3026 uint64_t *regarray, idx;
3028 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
3030 regarray = instr_regarray_regarray(p, ip);
3031 idx = instr_regarray_idx_nbo(p, t, ip);
3032 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3036 __instr_regrd_hrm_exec(struct rte_swx_pipeline *p,
3038 const struct instruction *ip)
3040 uint64_t *regarray, idx;
3042 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
3045 regarray = instr_regarray_regarray(p, ip);
3046 idx = instr_regarray_idx_hbo(p, t, ip);
3047 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3051 __instr_regrd_mrh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3053 uint64_t *regarray, idx;
3055 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
3057 regarray = instr_regarray_regarray(p, ip);
3058 idx = instr_regarray_idx_nbo(p, t, ip);
3059 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3063 __instr_regrd_mrm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3065 uint64_t *regarray, idx;
3067 TRACE("[Thread %2u] regrd (m = r[m])\n", p->thread_id);
3069 regarray = instr_regarray_regarray(p, ip);
3070 idx = instr_regarray_idx_hbo(p, t, ip);
3071 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3075 __instr_regrd_hri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3077 uint64_t *regarray, idx;
3079 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
3081 regarray = instr_regarray_regarray(p, ip);
3082 idx = instr_regarray_idx_imm(p, ip);
3083 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3087 __instr_regrd_mri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3089 uint64_t *regarray, idx;
3091 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
3093 regarray = instr_regarray_regarray(p, ip);
3094 idx = instr_regarray_idx_imm(p, ip);
3095 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3099 __instr_regwr_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3101 uint64_t *regarray, idx, src;
3103 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
3105 regarray = instr_regarray_regarray(p, ip);
3106 idx = instr_regarray_idx_nbo(p, t, ip);
3107 src = instr_regarray_src_nbo(t, ip);
3108 regarray[idx] = src;
3112 __instr_regwr_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3114 uint64_t *regarray, idx, src;
3116 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
3118 regarray = instr_regarray_regarray(p, ip);
3119 idx = instr_regarray_idx_nbo(p, t, ip);
3120 src = instr_regarray_src_hbo(t, ip);
3121 regarray[idx] = src;
3125 __instr_regwr_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3127 uint64_t *regarray, idx, src;
3129 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
3131 regarray = instr_regarray_regarray(p, ip);
3132 idx = instr_regarray_idx_hbo(p, t, ip);
3133 src = instr_regarray_src_nbo(t, ip);
3134 regarray[idx] = src;
3138 __instr_regwr_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3140 uint64_t *regarray, idx, src;
3142 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
3144 regarray = instr_regarray_regarray(p, ip);
3145 idx = instr_regarray_idx_hbo(p, t, ip);
3146 src = instr_regarray_src_hbo(t, ip);
3147 regarray[idx] = src;
3151 __instr_regwr_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3153 uint64_t *regarray, idx, src;
3155 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
3157 regarray = instr_regarray_regarray(p, ip);
3158 idx = instr_regarray_idx_nbo(p, t, ip);
3159 src = ip->regarray.dstsrc_val;
3160 regarray[idx] = src;
3164 __instr_regwr_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3166 uint64_t *regarray, idx, src;
3168 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
3170 regarray = instr_regarray_regarray(p, ip);
3171 idx = instr_regarray_idx_hbo(p, t, ip);
3172 src = ip->regarray.dstsrc_val;
3173 regarray[idx] = src;
3177 __instr_regwr_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3179 uint64_t *regarray, idx, src;
3181 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
3183 regarray = instr_regarray_regarray(p, ip);
3184 idx = instr_regarray_idx_imm(p, ip);
3185 src = instr_regarray_src_nbo(t, ip);
3186 regarray[idx] = src;
3190 __instr_regwr_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3192 uint64_t *regarray, idx, src;
3194 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
3196 regarray = instr_regarray_regarray(p, ip);
3197 idx = instr_regarray_idx_imm(p, ip);
3198 src = instr_regarray_src_hbo(t, ip);
3199 regarray[idx] = src;
3203 __instr_regwr_rii_exec(struct rte_swx_pipeline *p,
3204 struct thread *t __rte_unused,
3205 const struct instruction *ip)
3207 uint64_t *regarray, idx, src;
3209 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
3211 regarray = instr_regarray_regarray(p, ip);
3212 idx = instr_regarray_idx_imm(p, ip);
3213 src = ip->regarray.dstsrc_val;
3214 regarray[idx] = src;
3218 __instr_regadd_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3220 uint64_t *regarray, idx, src;
3222 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
3224 regarray = instr_regarray_regarray(p, ip);
3225 idx = instr_regarray_idx_nbo(p, t, ip);
3226 src = instr_regarray_src_nbo(t, ip);
3227 regarray[idx] += src;
3231 __instr_regadd_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3233 uint64_t *regarray, idx, src;
3235 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
3237 regarray = instr_regarray_regarray(p, ip);
3238 idx = instr_regarray_idx_nbo(p, t, ip);
3239 src = instr_regarray_src_hbo(t, ip);
3240 regarray[idx] += src;
3244 __instr_regadd_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3246 uint64_t *regarray, idx, src;
3248 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
3250 regarray = instr_regarray_regarray(p, ip);
3251 idx = instr_regarray_idx_hbo(p, t, ip);
3252 src = instr_regarray_src_nbo(t, ip);
3253 regarray[idx] += src;
3257 __instr_regadd_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3259 uint64_t *regarray, idx, src;
3261 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
3263 regarray = instr_regarray_regarray(p, ip);
3264 idx = instr_regarray_idx_hbo(p, t, ip);
3265 src = instr_regarray_src_hbo(t, ip);
3266 regarray[idx] += src;
3270 __instr_regadd_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3272 uint64_t *regarray, idx, src;
3274 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
3276 regarray = instr_regarray_regarray(p, ip);
3277 idx = instr_regarray_idx_nbo(p, t, ip);
3278 src = ip->regarray.dstsrc_val;
3279 regarray[idx] += src;
3283 __instr_regadd_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3285 uint64_t *regarray, idx, src;
3287 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
3289 regarray = instr_regarray_regarray(p, ip);
3290 idx = instr_regarray_idx_hbo(p, t, ip);
3291 src = ip->regarray.dstsrc_val;
3292 regarray[idx] += src;
3296 __instr_regadd_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3298 uint64_t *regarray, idx, src;
3300 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
3302 regarray = instr_regarray_regarray(p, ip);
3303 idx = instr_regarray_idx_imm(p, ip);
3304 src = instr_regarray_src_nbo(t, ip);
3305 regarray[idx] += src;
3309 __instr_regadd_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3311 uint64_t *regarray, idx, src;
3313 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
3315 regarray = instr_regarray_regarray(p, ip);
3316 idx = instr_regarray_idx_imm(p, ip);
3317 src = instr_regarray_src_hbo(t, ip);
3318 regarray[idx] += src;
3322 __instr_regadd_rii_exec(struct rte_swx_pipeline *p,
3323 struct thread *t __rte_unused,
3324 const struct instruction *ip)
3326 uint64_t *regarray, idx, src;
3328 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
3330 regarray = instr_regarray_regarray(p, ip);
3331 idx = instr_regarray_idx_imm(p, ip);
3332 src = ip->regarray.dstsrc_val;
3333 regarray[idx] += src;
3339 static inline struct meter *
3340 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3342 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3344 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3345 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3346 uint64_t idx64 = *idx64_ptr;
3347 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
3348 uint64_t idx = idx64 & idx64_mask & r->size_mask;
3350 return &r->metarray[idx];
3353 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3355 static inline struct meter *
3356 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3358 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3360 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3361 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3362 uint64_t idx64 = *idx64_ptr;
3363 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
3365 return &r->metarray[idx];
3370 #define instr_meter_idx_nbo instr_meter_idx_hbo
3374 static inline struct meter *
3375 instr_meter_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3377 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3379 uint64_t idx = ip->meter.idx_val & r->size_mask;
3381 return &r->metarray[idx];
3384 static inline uint32_t
3385 instr_meter_length_hbo(struct thread *t, const struct instruction *ip)
3387 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3388 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3389 uint64_t src64 = *src64_ptr;
3390 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
3391 uint64_t src = src64 & src64_mask;
3393 return (uint32_t)src;
3396 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3398 static inline uint32_t
3399 instr_meter_length_nbo(struct thread *t, const struct instruction *ip)
3401 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3402 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3403 uint64_t src64 = *src64_ptr;
3404 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
3406 return (uint32_t)src;
3411 #define instr_meter_length_nbo instr_meter_length_hbo
3415 static inline enum rte_color
3416 instr_meter_color_in_hbo(struct thread *t, const struct instruction *ip)
3418 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
3419 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
3420 uint64_t src64 = *src64_ptr;
3421 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
3422 uint64_t src = src64 & src64_mask;
3424 return (enum rte_color)src;
3428 instr_meter_color_out_hbo_set(struct thread *t,
3429 const struct instruction *ip,
3430 enum rte_color color_out)
3432 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
3433 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
3434 uint64_t dst64 = *dst64_ptr;
3435 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
3437 uint64_t src = (uint64_t)color_out;
3439 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3443 __instr_metprefetch_h_exec(struct rte_swx_pipeline *p,
3445 const struct instruction *ip)
3449 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
3451 m = instr_meter_idx_nbo(p, t, ip);
3456 __instr_metprefetch_m_exec(struct rte_swx_pipeline *p,
3458 const struct instruction *ip)
3462 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
3464 m = instr_meter_idx_hbo(p, t, ip);
3469 __instr_metprefetch_i_exec(struct rte_swx_pipeline *p,
3470 struct thread *t __rte_unused,
3471 const struct instruction *ip)
3475 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
3477 m = instr_meter_idx_imm(p, ip);
3482 __instr_meter_hhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3485 uint64_t time, n_pkts, n_bytes;
3487 enum rte_color color_in, color_out;
3489 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
3491 m = instr_meter_idx_nbo(p, t, ip);
3492 rte_prefetch0(m->n_pkts);
3493 time = rte_get_tsc_cycles();
3494 length = instr_meter_length_nbo(t, ip);
3495 color_in = instr_meter_color_in_hbo(t, ip);
3497 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3498 &m->profile->profile,
3503 color_out &= m->color_mask;
3505 n_pkts = m->n_pkts[color_out];
3506 n_bytes = m->n_bytes[color_out];
3508 instr_meter_color_out_hbo_set(t, ip, color_out);
3510 m->n_pkts[color_out] = n_pkts + 1;
3511 m->n_bytes[color_out] = n_bytes + length;
3515 __instr_meter_hhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3518 uint64_t time, n_pkts, n_bytes;
3520 enum rte_color color_in, color_out;
3522 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
3524 m = instr_meter_idx_nbo(p, t, ip);
3525 rte_prefetch0(m->n_pkts);
3526 time = rte_get_tsc_cycles();
3527 length = instr_meter_length_nbo(t, ip);
3528 color_in = (enum rte_color)ip->meter.color_in_val;
3530 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3531 &m->profile->profile,
3536 color_out &= m->color_mask;
3538 n_pkts = m->n_pkts[color_out];
3539 n_bytes = m->n_bytes[color_out];
3541 instr_meter_color_out_hbo_set(t, ip, color_out);
3543 m->n_pkts[color_out] = n_pkts + 1;
3544 m->n_bytes[color_out] = n_bytes + length;
3548 __instr_meter_hmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3551 uint64_t time, n_pkts, n_bytes;
3553 enum rte_color color_in, color_out;
3555 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
3557 m = instr_meter_idx_nbo(p, t, ip);
3558 rte_prefetch0(m->n_pkts);
3559 time = rte_get_tsc_cycles();
3560 length = instr_meter_length_hbo(t, ip);
3561 color_in = instr_meter_color_in_hbo(t, ip);
3563 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3564 &m->profile->profile,
3569 color_out &= m->color_mask;
3571 n_pkts = m->n_pkts[color_out];
3572 n_bytes = m->n_bytes[color_out];
3574 instr_meter_color_out_hbo_set(t, ip, color_out);
3576 m->n_pkts[color_out] = n_pkts + 1;
3577 m->n_bytes[color_out] = n_bytes + length;
3581 __instr_meter_hmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3584 uint64_t time, n_pkts, n_bytes;
3586 enum rte_color color_in, color_out;
3588 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
3590 m = instr_meter_idx_nbo(p, t, ip);
3591 rte_prefetch0(m->n_pkts);
3592 time = rte_get_tsc_cycles();
3593 length = instr_meter_length_hbo(t, ip);
3594 color_in = (enum rte_color)ip->meter.color_in_val;
3596 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3597 &m->profile->profile,
3602 color_out &= m->color_mask;
3604 n_pkts = m->n_pkts[color_out];
3605 n_bytes = m->n_bytes[color_out];
3607 instr_meter_color_out_hbo_set(t, ip, color_out);
3609 m->n_pkts[color_out] = n_pkts + 1;
3610 m->n_bytes[color_out] = n_bytes + length;
3614 __instr_meter_mhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3617 uint64_t time, n_pkts, n_bytes;
3619 enum rte_color color_in, color_out;
3621 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
3623 m = instr_meter_idx_hbo(p, t, ip);
3624 rte_prefetch0(m->n_pkts);
3625 time = rte_get_tsc_cycles();
3626 length = instr_meter_length_nbo(t, ip);
3627 color_in = instr_meter_color_in_hbo(t, ip);
3629 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3630 &m->profile->profile,
3635 color_out &= m->color_mask;
3637 n_pkts = m->n_pkts[color_out];
3638 n_bytes = m->n_bytes[color_out];
3640 instr_meter_color_out_hbo_set(t, ip, color_out);
3642 m->n_pkts[color_out] = n_pkts + 1;
3643 m->n_bytes[color_out] = n_bytes + length;
3647 __instr_meter_mhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3650 uint64_t time, n_pkts, n_bytes;
3652 enum rte_color color_in, color_out;
3654 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
3656 m = instr_meter_idx_hbo(p, t, ip);
3657 rte_prefetch0(m->n_pkts);
3658 time = rte_get_tsc_cycles();
3659 length = instr_meter_length_nbo(t, ip);
3660 color_in = (enum rte_color)ip->meter.color_in_val;
3662 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3663 &m->profile->profile,
3668 color_out &= m->color_mask;
3670 n_pkts = m->n_pkts[color_out];
3671 n_bytes = m->n_bytes[color_out];
3673 instr_meter_color_out_hbo_set(t, ip, color_out);
3675 m->n_pkts[color_out] = n_pkts + 1;
3676 m->n_bytes[color_out] = n_bytes + length;
3680 __instr_meter_mmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3683 uint64_t time, n_pkts, n_bytes;
3685 enum rte_color color_in, color_out;
3687 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
3689 m = instr_meter_idx_hbo(p, t, ip);
3690 rte_prefetch0(m->n_pkts);
3691 time = rte_get_tsc_cycles();
3692 length = instr_meter_length_hbo(t, ip);
3693 color_in = instr_meter_color_in_hbo(t, ip);
3695 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3696 &m->profile->profile,
3701 color_out &= m->color_mask;
3703 n_pkts = m->n_pkts[color_out];
3704 n_bytes = m->n_bytes[color_out];
3706 instr_meter_color_out_hbo_set(t, ip, color_out);
3708 m->n_pkts[color_out] = n_pkts + 1;
3709 m->n_bytes[color_out] = n_bytes + length;
3713 __instr_meter_mmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3716 uint64_t time, n_pkts, n_bytes;
3718 enum rte_color color_in, color_out;
3720 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
3722 m = instr_meter_idx_hbo(p, t, ip);
3723 rte_prefetch0(m->n_pkts);
3724 time = rte_get_tsc_cycles();
3725 length = instr_meter_length_hbo(t, ip);
3726 color_in = (enum rte_color)ip->meter.color_in_val;
3728 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3729 &m->profile->profile,
3734 color_out &= m->color_mask;
3736 n_pkts = m->n_pkts[color_out];
3737 n_bytes = m->n_bytes[color_out];
3739 instr_meter_color_out_hbo_set(t, ip, color_out);
3741 m->n_pkts[color_out] = n_pkts + 1;
3742 m->n_bytes[color_out] = n_bytes + length;
3746 __instr_meter_ihm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3749 uint64_t time, n_pkts, n_bytes;
3751 enum rte_color color_in, color_out;
3753 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
3755 m = instr_meter_idx_imm(p, ip);
3756 rte_prefetch0(m->n_pkts);
3757 time = rte_get_tsc_cycles();
3758 length = instr_meter_length_nbo(t, ip);
3759 color_in = instr_meter_color_in_hbo(t, ip);
3761 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3762 &m->profile->profile,
3767 color_out &= m->color_mask;
3769 n_pkts = m->n_pkts[color_out];
3770 n_bytes = m->n_bytes[color_out];
3772 instr_meter_color_out_hbo_set(t, ip, color_out);
3774 m->n_pkts[color_out] = n_pkts + 1;
3775 m->n_bytes[color_out] = n_bytes + length;
3779 __instr_meter_ihi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3782 uint64_t time, n_pkts, n_bytes;
3784 enum rte_color color_in, color_out;
3786 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
3788 m = instr_meter_idx_imm(p, ip);
3789 rte_prefetch0(m->n_pkts);
3790 time = rte_get_tsc_cycles();
3791 length = instr_meter_length_nbo(t, ip);
3792 color_in = (enum rte_color)ip->meter.color_in_val;
3794 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3795 &m->profile->profile,
3800 color_out &= m->color_mask;
3802 n_pkts = m->n_pkts[color_out];
3803 n_bytes = m->n_bytes[color_out];
3805 instr_meter_color_out_hbo_set(t, ip, color_out);
3807 m->n_pkts[color_out] = n_pkts + 1;
3808 m->n_bytes[color_out] = n_bytes + length;
3812 __instr_meter_imm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3815 uint64_t time, n_pkts, n_bytes;
3817 enum rte_color color_in, color_out;
3819 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
3821 m = instr_meter_idx_imm(p, ip);
3822 rte_prefetch0(m->n_pkts);
3823 time = rte_get_tsc_cycles();
3824 length = instr_meter_length_hbo(t, ip);
3825 color_in = instr_meter_color_in_hbo(t, ip);
3827 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3828 &m->profile->profile,
3833 color_out &= m->color_mask;
3835 n_pkts = m->n_pkts[color_out];
3836 n_bytes = m->n_bytes[color_out];
3838 instr_meter_color_out_hbo_set(t, ip, color_out);
3840 m->n_pkts[color_out] = n_pkts + 1;
3841 m->n_bytes[color_out] = n_bytes + length;
3845 __instr_meter_imi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3848 uint64_t time, n_pkts, n_bytes;
3850 enum rte_color color_in, color_out;
3852 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
3854 m = instr_meter_idx_imm(p, ip);
3855 rte_prefetch0(m->n_pkts);
3856 time = rte_get_tsc_cycles();
3857 length = instr_meter_length_hbo(t, ip);
3858 color_in = (enum rte_color)ip->meter.color_in_val;
3860 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3861 &m->profile->profile,
3866 color_out &= m->color_mask;
3868 n_pkts = m->n_pkts[color_out];
3869 n_bytes = m->n_bytes[color_out];
3871 instr_meter_color_out_hbo_set(t, ip, color_out);
3873 m->n_pkts[color_out] = n_pkts + 1;
3874 m->n_bytes[color_out] = n_bytes + length;