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 = &t->headers_out[n_headers_out - 1];
1844 uint8_t *ho_ptr = NULL;
1845 uint32_t ho_nbytes = 0, first = 1, 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))
1860 TRACE("[Thread %2u]: emit header %u\n",
1868 if (!t->n_headers_out) {
1869 ho = &t->headers_out[0];
1875 ho_nbytes = n_bytes;
1882 ho_nbytes = ho->n_bytes;
1886 if (ho_ptr + ho_nbytes == hi_ptr) {
1887 ho_nbytes += n_bytes;
1889 ho->n_bytes = ho_nbytes;
1896 ho_nbytes = n_bytes;
1902 ho->n_bytes = ho_nbytes;
1903 t->n_headers_out = n_headers_out;
1907 __instr_hdr_emit_exec(struct rte_swx_pipeline *p,
1909 const struct instruction *ip)
1911 __instr_hdr_emit_many_exec(p, t, ip, 1);
1915 __instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p,
1917 const struct instruction *ip)
1919 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1921 __instr_hdr_emit_many_exec(p, t, ip, 1);
1922 __instr_tx_exec(p, t, ip);
1926 __instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p,
1928 const struct instruction *ip)
1930 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1932 __instr_hdr_emit_many_exec(p, t, ip, 2);
1933 __instr_tx_exec(p, t, ip);
1937 __instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p,
1939 const struct instruction *ip)
1941 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1943 __instr_hdr_emit_many_exec(p, t, ip, 3);
1944 __instr_tx_exec(p, t, ip);
1948 __instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p,
1950 const struct instruction *ip)
1952 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1954 __instr_hdr_emit_many_exec(p, t, ip, 4);
1955 __instr_tx_exec(p, t, ip);
1959 __instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p,
1961 const struct instruction *ip)
1963 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1965 __instr_hdr_emit_many_exec(p, t, ip, 5);
1966 __instr_tx_exec(p, t, ip);
1970 __instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p,
1972 const struct instruction *ip)
1974 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1976 __instr_hdr_emit_many_exec(p, t, ip, 6);
1977 __instr_tx_exec(p, t, ip);
1981 __instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p,
1983 const struct instruction *ip)
1985 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1987 __instr_hdr_emit_many_exec(p, t, ip, 7);
1988 __instr_tx_exec(p, t, ip);
1992 __instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p,
1994 const struct instruction *ip)
1996 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n", p->thread_id);
1998 __instr_hdr_emit_many_exec(p, t, ip, 8);
1999 __instr_tx_exec(p, t, ip);
2006 __instr_hdr_validate_exec(struct rte_swx_pipeline *p __rte_unused,
2008 const struct instruction *ip)
2010 uint32_t header_id = ip->valid.header_id;
2012 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2015 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2022 __instr_hdr_invalidate_exec(struct rte_swx_pipeline *p __rte_unused,
2024 const struct instruction *ip)
2026 uint32_t header_id = ip->valid.header_id;
2028 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2031 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2038 __instr_learn_exec(struct rte_swx_pipeline *p,
2040 const struct instruction *ip)
2042 uint64_t action_id = ip->learn.action_id;
2043 uint32_t mf_offset = ip->learn.mf_offset;
2044 uint32_t learner_id = t->learner_id;
2045 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2046 p->n_selectors + learner_id];
2047 struct learner_runtime *l = &t->learners[learner_id];
2048 struct learner_statistics *stats = &p->learner_stats[learner_id];
2052 status = rte_swx_table_learner_add(ts->obj,
2056 &t->metadata[mf_offset]);
2058 TRACE("[Thread %2u] learner %u learn %s\n",
2061 status ? "ok" : "error");
2063 stats->n_pkts_learn[status] += 1;
2070 __instr_forget_exec(struct rte_swx_pipeline *p,
2072 const struct instruction *ip __rte_unused)
2074 uint32_t learner_id = t->learner_id;
2075 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2076 p->n_selectors + learner_id];
2077 struct learner_runtime *l = &t->learners[learner_id];
2078 struct learner_statistics *stats = &p->learner_stats[learner_id];
2081 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2083 TRACE("[Thread %2u] learner %u forget\n",
2087 stats->n_pkts_forget += 1;
2093 static inline uint32_t
2094 __instr_extern_obj_exec(struct rte_swx_pipeline *p __rte_unused,
2096 const struct instruction *ip)
2098 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2099 uint32_t func_id = ip->ext_obj.func_id;
2100 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2101 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2104 TRACE("[Thread %2u] extern obj %u member func %u\n",
2109 done = func(obj->obj, obj->mailbox);
2114 static inline uint32_t
2115 __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
2117 const struct instruction *ip)
2119 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2120 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2121 rte_swx_extern_func_t func = ext_func->func;
2124 TRACE("[Thread %2u] extern func %u\n",
2128 done = func(ext_func->mailbox);
2137 __instr_mov_exec(struct rte_swx_pipeline *p __rte_unused,
2139 const struct instruction *ip)
2141 TRACE("[Thread %2u] mov\n", p->thread_id);
2147 __instr_mov_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2149 const struct instruction *ip)
2151 TRACE("[Thread %2u] mov (mh)\n", p->thread_id);
2157 __instr_mov_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2159 const struct instruction *ip)
2161 TRACE("[Thread %2u] mov (hm)\n", p->thread_id);
2167 __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2169 const struct instruction *ip)
2171 TRACE("[Thread %2u] mov (hh)\n", p->thread_id);
2177 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
2179 const struct instruction *ip)
2181 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val);
2190 __instr_dma_ht_many_exec(struct rte_swx_pipeline *p __rte_unused,
2192 const struct instruction *ip,
2195 uint8_t *action_data = t->structs[0];
2196 uint64_t valid_headers = t->valid_headers;
2199 for (i = 0; i < n_dma; i++) {
2200 uint32_t header_id = ip->dma.dst.header_id[i];
2201 uint32_t struct_id = ip->dma.dst.struct_id[i];
2202 uint32_t offset = ip->dma.src.offset[i];
2203 uint32_t n_bytes = ip->dma.n_bytes[i];
2205 struct header_runtime *h = &t->headers[header_id];
2206 uint8_t *h_ptr0 = h->ptr0;
2207 uint8_t *h_ptr = t->structs[struct_id];
2209 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2211 void *src = &action_data[offset];
2213 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2216 memcpy(dst, src, n_bytes);
2217 t->structs[struct_id] = dst;
2218 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2221 t->valid_headers = valid_headers;
2225 __instr_dma_ht_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2227 __instr_dma_ht_many_exec(p, t, ip, 1);
2231 __instr_dma_ht2_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2233 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2235 __instr_dma_ht_many_exec(p, t, ip, 2);
2239 __instr_dma_ht3_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2241 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2243 __instr_dma_ht_many_exec(p, t, ip, 3);
2247 __instr_dma_ht4_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2249 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2251 __instr_dma_ht_many_exec(p, t, ip, 4);
2255 __instr_dma_ht5_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2257 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2259 __instr_dma_ht_many_exec(p, t, ip, 5);
2263 __instr_dma_ht6_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2265 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2267 __instr_dma_ht_many_exec(p, t, ip, 6);
2271 __instr_dma_ht7_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2273 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2275 __instr_dma_ht_many_exec(p, t, ip, 7);
2279 __instr_dma_ht8_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2281 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2283 __instr_dma_ht_many_exec(p, t, ip, 8);
2290 __instr_alu_add_exec(struct rte_swx_pipeline *p __rte_unused,
2292 const struct instruction *ip)
2294 TRACE("[Thread %2u] add\n", p->thread_id);
2300 __instr_alu_add_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2302 const struct instruction *ip)
2304 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
2310 __instr_alu_add_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2312 const struct instruction *ip)
2314 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
2320 __instr_alu_add_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2322 const struct instruction *ip)
2324 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
2330 __instr_alu_add_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2332 const struct instruction *ip)
2334 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
2340 __instr_alu_add_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2342 const struct instruction *ip)
2344 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
2350 __instr_alu_sub_exec(struct rte_swx_pipeline *p __rte_unused,
2352 const struct instruction *ip)
2354 TRACE("[Thread %2u] sub\n", p->thread_id);
2360 __instr_alu_sub_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2362 const struct instruction *ip)
2364 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
2370 __instr_alu_sub_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2372 const struct instruction *ip)
2374 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
2380 __instr_alu_sub_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2382 const struct instruction *ip)
2384 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
2390 __instr_alu_sub_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2392 const struct instruction *ip)
2394 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
2400 __instr_alu_sub_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2402 const struct instruction *ip)
2404 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
2410 __instr_alu_shl_exec(struct rte_swx_pipeline *p __rte_unused,
2412 const struct instruction *ip)
2414 TRACE("[Thread %2u] shl\n", p->thread_id);
2420 __instr_alu_shl_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2422 const struct instruction *ip)
2424 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
2430 __instr_alu_shl_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2432 const struct instruction *ip)
2434 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
2440 __instr_alu_shl_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2442 const struct instruction *ip)
2444 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
2450 __instr_alu_shl_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2452 const struct instruction *ip)
2454 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
2460 __instr_alu_shl_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2462 const struct instruction *ip)
2464 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
2470 __instr_alu_shr_exec(struct rte_swx_pipeline *p __rte_unused,
2472 const struct instruction *ip)
2474 TRACE("[Thread %2u] shr\n", p->thread_id);
2480 __instr_alu_shr_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2482 const struct instruction *ip)
2484 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
2490 __instr_alu_shr_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2492 const struct instruction *ip)
2494 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
2500 __instr_alu_shr_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2502 const struct instruction *ip)
2504 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
2510 __instr_alu_shr_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2512 const struct instruction *ip)
2514 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
2521 __instr_alu_shr_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2523 const struct instruction *ip)
2525 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
2531 __instr_alu_and_exec(struct rte_swx_pipeline *p __rte_unused,
2533 const struct instruction *ip)
2535 TRACE("[Thread %2u] and\n", p->thread_id);
2541 __instr_alu_and_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2543 const struct instruction *ip)
2545 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
2551 __instr_alu_and_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2553 const struct instruction *ip)
2555 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
2557 ALU_HM_FAST(t, ip, &);
2561 __instr_alu_and_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2563 const struct instruction *ip)
2565 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
2567 ALU_HH_FAST(t, ip, &);
2571 __instr_alu_and_i_exec(struct rte_swx_pipeline *p __rte_unused,
2573 const struct instruction *ip)
2575 TRACE("[Thread %2u] and (i)\n", p->thread_id);
2581 __instr_alu_or_exec(struct rte_swx_pipeline *p __rte_unused,
2583 const struct instruction *ip)
2585 TRACE("[Thread %2u] or\n", p->thread_id);
2591 __instr_alu_or_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2593 const struct instruction *ip)
2595 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
2601 __instr_alu_or_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2603 const struct instruction *ip)
2605 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
2607 ALU_HM_FAST(t, ip, |);
2611 __instr_alu_or_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2613 const struct instruction *ip)
2615 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
2617 ALU_HH_FAST(t, ip, |);
2621 __instr_alu_or_i_exec(struct rte_swx_pipeline *p __rte_unused,
2623 const struct instruction *ip)
2625 TRACE("[Thread %2u] or (i)\n", p->thread_id);
2631 __instr_alu_xor_exec(struct rte_swx_pipeline *p __rte_unused,
2633 const struct instruction *ip)
2635 TRACE("[Thread %2u] xor\n", p->thread_id);
2641 __instr_alu_xor_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2643 const struct instruction *ip)
2645 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
2651 __instr_alu_xor_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2653 const struct instruction *ip)
2655 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
2657 ALU_HM_FAST(t, ip, ^);
2661 __instr_alu_xor_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2663 const struct instruction *ip)
2665 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
2667 ALU_HH_FAST(t, ip, ^);
2671 __instr_alu_xor_i_exec(struct rte_swx_pipeline *p __rte_unused,
2673 const struct instruction *ip)
2675 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
2681 __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
2683 const struct instruction *ip)
2685 uint8_t *dst_struct, *src_struct;
2686 uint16_t *dst16_ptr, dst;
2687 uint64_t *src64_ptr, src64, src64_mask, src;
2690 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
2693 dst_struct = t->structs[ip->alu.dst.struct_id];
2694 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2697 src_struct = t->structs[ip->alu.src.struct_id];
2698 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2700 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2701 src = src64 & src64_mask;
2703 /* Initialize the result with destination 1's complement. */
2707 /* The first input (r) is a 16-bit number. The second and the third
2708 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
2709 * three numbers (output r) is a 34-bit number.
2711 r += (src >> 32) + (src & 0xFFFFFFFF);
2713 /* The first input is a 16-bit number. The second input is an 18-bit
2714 * number. In the worst case scenario, the sum of the two numbers is a
2717 r = (r & 0xFFFF) + (r >> 16);
2719 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2720 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
2722 r = (r & 0xFFFF) + (r >> 16);
2724 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2725 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2726 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
2727 * therefore the output r is always a 16-bit number.
2729 r = (r & 0xFFFF) + (r >> 16);
2731 /* Apply 1's complement to the result. */
2735 *dst16_ptr = (uint16_t)r;
2739 __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
2741 const struct instruction *ip)
2743 uint8_t *dst_struct, *src_struct;
2744 uint16_t *dst16_ptr, dst;
2745 uint64_t *src64_ptr, src64, src64_mask, src;
2748 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
2751 dst_struct = t->structs[ip->alu.dst.struct_id];
2752 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2755 src_struct = t->structs[ip->alu.src.struct_id];
2756 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2758 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2759 src = src64 & src64_mask;
2761 /* Initialize the result with destination 1's complement. */
2765 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
2766 * the following sequence of operations in 2's complement arithmetic:
2767 * a '- b = (a - b) % 0xFFFF.
2769 * In order to prevent an underflow for the below subtraction, in which
2770 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
2771 * minuend), we first add a multiple of the 0xFFFF modulus to the
2772 * minuend. The number we add to the minuend needs to be a 34-bit number
2773 * or higher, so for readability reasons we picked the 36-bit multiple.
2774 * We are effectively turning the 16-bit minuend into a 36-bit number:
2775 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
2777 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
2779 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
2780 * result (the output r) is a 36-bit number.
2782 r -= (src >> 32) + (src & 0xFFFFFFFF);
2784 /* The first input is a 16-bit number. The second input is a 20-bit
2785 * number. Their sum is a 21-bit number.
2787 r = (r & 0xFFFF) + (r >> 16);
2789 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2790 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
2792 r = (r & 0xFFFF) + (r >> 16);
2794 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2795 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2796 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2797 * generated, therefore the output r is always a 16-bit number.
2799 r = (r & 0xFFFF) + (r >> 16);
2801 /* Apply 1's complement to the result. */
2805 *dst16_ptr = (uint16_t)r;
2809 __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
2811 const struct instruction *ip)
2813 uint8_t *dst_struct, *src_struct;
2814 uint16_t *dst16_ptr, dst;
2815 uint32_t *src32_ptr;
2818 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
2821 dst_struct = t->structs[ip->alu.dst.struct_id];
2822 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2825 src_struct = t->structs[ip->alu.src.struct_id];
2826 src32_ptr = (uint32_t *)&src_struct[0];
2828 /* Initialize the result with destination 1's complement. */
2832 r0 += src32_ptr[0]; /* The output r0 is a 33-bit number. */
2833 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
2834 r0 += src32_ptr[2]; /* The output r0 is a 34-bit number. */
2835 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
2836 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
2838 /* The first input is a 16-bit number. The second input is a 19-bit
2839 * number. Their sum is a 20-bit number.
2841 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2843 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2844 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
2846 r0 = (r0 & 0xFFFF) + (r0 >> 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 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
2851 * generated, therefore the output r is always a 16-bit number.
2853 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2855 /* Apply 1's complement to the result. */
2857 r0 = r0 ? r0 : 0xFFFF;
2859 *dst16_ptr = (uint16_t)r0;
2863 __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
2865 const struct instruction *ip)
2867 uint32_t src_header_id = ip->alu.src.n_bits; /* The src header ID is stored here. */
2868 uint32_t n_src_header_bytes = t->headers[src_header_id].n_bytes;
2869 uint8_t *dst_struct, *src_struct;
2870 uint16_t *dst16_ptr, dst;
2871 uint32_t *src32_ptr;
2875 if (n_src_header_bytes == 20) {
2876 __instr_alu_ckadd_struct20_exec(p, t, ip);
2880 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
2883 dst_struct = t->structs[ip->alu.dst.struct_id];
2884 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2887 src_struct = t->structs[ip->alu.src.struct_id];
2888 src32_ptr = (uint32_t *)&src_struct[0];
2890 /* Initialize the result with destination 1's complement. */
2894 /* The max number of 32-bit words in a 32K-byte header is 2^13.
2895 * Therefore, in the worst case scenario, a 45-bit number is added to a
2896 * 16-bit number (the input r), so the output r is 46-bit number.
2898 for (i = 0; i < n_src_header_bytes / 4; i++, src32_ptr++)
2901 /* The first input is a 16-bit number. The second input is a 30-bit
2902 * number. Their sum is a 31-bit number.
2904 r = (r & 0xFFFF) + (r >> 16);
2906 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2907 * a 15-bit number (0 .. 0x7FFF). The sum is a 17-bit number (0 .. 0x17FFE).
2909 r = (r & 0xFFFF) + (r >> 16);
2911 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2912 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2913 * 0x17FFE), the output r is (0 .. 0x7FFF). So no carry bit can be
2914 * generated, therefore the output r is always a 16-bit number.
2916 r = (r & 0xFFFF) + (r >> 16);
2918 /* Apply 1's complement to the result. */
2922 *dst16_ptr = (uint16_t)r;
2928 static inline uint64_t *
2929 instr_regarray_regarray(struct rte_swx_pipeline *p, const struct instruction *ip)
2931 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2935 static inline uint64_t
2936 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2938 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2940 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2941 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2942 uint64_t idx64 = *idx64_ptr;
2943 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
2944 uint64_t idx = idx64 & idx64_mask & r->size_mask;
2949 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2951 static inline uint64_t
2952 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2954 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2956 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2957 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2958 uint64_t idx64 = *idx64_ptr;
2959 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
2966 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
2970 static inline uint64_t
2971 instr_regarray_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
2973 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2975 uint64_t idx = ip->regarray.idx_val & r->size_mask;
2980 static inline uint64_t
2981 instr_regarray_src_hbo(struct thread *t, const struct instruction *ip)
2983 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
2984 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
2985 uint64_t src64 = *src64_ptr;
2986 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
2987 uint64_t src = src64 & src64_mask;
2992 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2994 static inline uint64_t
2995 instr_regarray_src_nbo(struct thread *t, const struct instruction *ip)
2997 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
2998 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
2999 uint64_t src64 = *src64_ptr;
3000 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
3007 #define instr_regarray_src_nbo instr_regarray_src_hbo
3012 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3014 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3015 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3016 uint64_t dst64 = *dst64_ptr;
3017 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3019 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3023 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3026 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3028 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3029 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3030 uint64_t dst64 = *dst64_ptr;
3031 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3033 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
3034 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3039 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
3044 __instr_regprefetch_rh_exec(struct rte_swx_pipeline *p,
3046 const struct instruction *ip)
3048 uint64_t *regarray, idx;
3050 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
3052 regarray = instr_regarray_regarray(p, ip);
3053 idx = instr_regarray_idx_nbo(p, t, ip);
3054 rte_prefetch0(®array[idx]);
3058 __instr_regprefetch_rm_exec(struct rte_swx_pipeline *p,
3060 const struct instruction *ip)
3062 uint64_t *regarray, idx;
3064 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
3066 regarray = instr_regarray_regarray(p, ip);
3067 idx = instr_regarray_idx_hbo(p, t, ip);
3068 rte_prefetch0(®array[idx]);
3072 __instr_regprefetch_ri_exec(struct rte_swx_pipeline *p,
3073 struct thread *t __rte_unused,
3074 const struct instruction *ip)
3076 uint64_t *regarray, idx;
3078 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
3080 regarray = instr_regarray_regarray(p, ip);
3081 idx = instr_regarray_idx_imm(p, ip);
3082 rte_prefetch0(®array[idx]);
3086 __instr_regrd_hrh_exec(struct rte_swx_pipeline *p,
3088 const struct instruction *ip)
3090 uint64_t *regarray, idx;
3092 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
3094 regarray = instr_regarray_regarray(p, ip);
3095 idx = instr_regarray_idx_nbo(p, t, ip);
3096 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3100 __instr_regrd_hrm_exec(struct rte_swx_pipeline *p,
3102 const struct instruction *ip)
3104 uint64_t *regarray, idx;
3106 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
3109 regarray = instr_regarray_regarray(p, ip);
3110 idx = instr_regarray_idx_hbo(p, t, ip);
3111 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3115 __instr_regrd_mrh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3117 uint64_t *regarray, idx;
3119 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
3121 regarray = instr_regarray_regarray(p, ip);
3122 idx = instr_regarray_idx_nbo(p, t, ip);
3123 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3127 __instr_regrd_mrm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3129 uint64_t *regarray, idx;
3131 TRACE("[Thread %2u] regrd (m = r[m])\n", p->thread_id);
3133 regarray = instr_regarray_regarray(p, ip);
3134 idx = instr_regarray_idx_hbo(p, t, ip);
3135 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3139 __instr_regrd_hri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3141 uint64_t *regarray, idx;
3143 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
3145 regarray = instr_regarray_regarray(p, ip);
3146 idx = instr_regarray_idx_imm(p, ip);
3147 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3151 __instr_regrd_mri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3153 uint64_t *regarray, idx;
3155 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
3157 regarray = instr_regarray_regarray(p, ip);
3158 idx = instr_regarray_idx_imm(p, ip);
3159 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3163 __instr_regwr_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3165 uint64_t *regarray, idx, src;
3167 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
3169 regarray = instr_regarray_regarray(p, ip);
3170 idx = instr_regarray_idx_nbo(p, t, ip);
3171 src = instr_regarray_src_nbo(t, ip);
3172 regarray[idx] = src;
3176 __instr_regwr_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3178 uint64_t *regarray, idx, src;
3180 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
3182 regarray = instr_regarray_regarray(p, ip);
3183 idx = instr_regarray_idx_nbo(p, t, ip);
3184 src = instr_regarray_src_hbo(t, ip);
3185 regarray[idx] = src;
3189 __instr_regwr_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3191 uint64_t *regarray, idx, src;
3193 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
3195 regarray = instr_regarray_regarray(p, ip);
3196 idx = instr_regarray_idx_hbo(p, t, ip);
3197 src = instr_regarray_src_nbo(t, ip);
3198 regarray[idx] = src;
3202 __instr_regwr_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3204 uint64_t *regarray, idx, src;
3206 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
3208 regarray = instr_regarray_regarray(p, ip);
3209 idx = instr_regarray_idx_hbo(p, t, ip);
3210 src = instr_regarray_src_hbo(t, ip);
3211 regarray[idx] = src;
3215 __instr_regwr_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3217 uint64_t *regarray, idx, src;
3219 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
3221 regarray = instr_regarray_regarray(p, ip);
3222 idx = instr_regarray_idx_nbo(p, t, ip);
3223 src = ip->regarray.dstsrc_val;
3224 regarray[idx] = src;
3228 __instr_regwr_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3230 uint64_t *regarray, idx, src;
3232 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
3234 regarray = instr_regarray_regarray(p, ip);
3235 idx = instr_regarray_idx_hbo(p, t, ip);
3236 src = ip->regarray.dstsrc_val;
3237 regarray[idx] = src;
3241 __instr_regwr_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3243 uint64_t *regarray, idx, src;
3245 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
3247 regarray = instr_regarray_regarray(p, ip);
3248 idx = instr_regarray_idx_imm(p, ip);
3249 src = instr_regarray_src_nbo(t, ip);
3250 regarray[idx] = src;
3254 __instr_regwr_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3256 uint64_t *regarray, idx, src;
3258 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
3260 regarray = instr_regarray_regarray(p, ip);
3261 idx = instr_regarray_idx_imm(p, ip);
3262 src = instr_regarray_src_hbo(t, ip);
3263 regarray[idx] = src;
3267 __instr_regwr_rii_exec(struct rte_swx_pipeline *p,
3268 struct thread *t __rte_unused,
3269 const struct instruction *ip)
3271 uint64_t *regarray, idx, src;
3273 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
3275 regarray = instr_regarray_regarray(p, ip);
3276 idx = instr_regarray_idx_imm(p, ip);
3277 src = ip->regarray.dstsrc_val;
3278 regarray[idx] = src;
3282 __instr_regadd_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3284 uint64_t *regarray, idx, src;
3286 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
3288 regarray = instr_regarray_regarray(p, ip);
3289 idx = instr_regarray_idx_nbo(p, t, ip);
3290 src = instr_regarray_src_nbo(t, ip);
3291 regarray[idx] += src;
3295 __instr_regadd_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3297 uint64_t *regarray, idx, src;
3299 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
3301 regarray = instr_regarray_regarray(p, ip);
3302 idx = instr_regarray_idx_nbo(p, t, ip);
3303 src = instr_regarray_src_hbo(t, ip);
3304 regarray[idx] += src;
3308 __instr_regadd_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3310 uint64_t *regarray, idx, src;
3312 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
3314 regarray = instr_regarray_regarray(p, ip);
3315 idx = instr_regarray_idx_hbo(p, t, ip);
3316 src = instr_regarray_src_nbo(t, ip);
3317 regarray[idx] += src;
3321 __instr_regadd_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3323 uint64_t *regarray, idx, src;
3325 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
3327 regarray = instr_regarray_regarray(p, ip);
3328 idx = instr_regarray_idx_hbo(p, t, ip);
3329 src = instr_regarray_src_hbo(t, ip);
3330 regarray[idx] += src;
3334 __instr_regadd_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3336 uint64_t *regarray, idx, src;
3338 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
3340 regarray = instr_regarray_regarray(p, ip);
3341 idx = instr_regarray_idx_nbo(p, t, ip);
3342 src = ip->regarray.dstsrc_val;
3343 regarray[idx] += src;
3347 __instr_regadd_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3349 uint64_t *regarray, idx, src;
3351 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
3353 regarray = instr_regarray_regarray(p, ip);
3354 idx = instr_regarray_idx_hbo(p, t, ip);
3355 src = ip->regarray.dstsrc_val;
3356 regarray[idx] += src;
3360 __instr_regadd_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3362 uint64_t *regarray, idx, src;
3364 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
3366 regarray = instr_regarray_regarray(p, ip);
3367 idx = instr_regarray_idx_imm(p, ip);
3368 src = instr_regarray_src_nbo(t, ip);
3369 regarray[idx] += src;
3373 __instr_regadd_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3375 uint64_t *regarray, idx, src;
3377 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
3379 regarray = instr_regarray_regarray(p, ip);
3380 idx = instr_regarray_idx_imm(p, ip);
3381 src = instr_regarray_src_hbo(t, ip);
3382 regarray[idx] += src;
3386 __instr_regadd_rii_exec(struct rte_swx_pipeline *p,
3387 struct thread *t __rte_unused,
3388 const struct instruction *ip)
3390 uint64_t *regarray, idx, src;
3392 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
3394 regarray = instr_regarray_regarray(p, ip);
3395 idx = instr_regarray_idx_imm(p, ip);
3396 src = ip->regarray.dstsrc_val;
3397 regarray[idx] += src;
3403 static inline struct meter *
3404 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3406 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3408 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3409 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3410 uint64_t idx64 = *idx64_ptr;
3411 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
3412 uint64_t idx = idx64 & idx64_mask & r->size_mask;
3414 return &r->metarray[idx];
3417 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3419 static inline struct meter *
3420 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3422 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3424 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3425 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3426 uint64_t idx64 = *idx64_ptr;
3427 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
3429 return &r->metarray[idx];
3434 #define instr_meter_idx_nbo instr_meter_idx_hbo
3438 static inline struct meter *
3439 instr_meter_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3441 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3443 uint64_t idx = ip->meter.idx_val & r->size_mask;
3445 return &r->metarray[idx];
3448 static inline uint32_t
3449 instr_meter_length_hbo(struct thread *t, const struct instruction *ip)
3451 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3452 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3453 uint64_t src64 = *src64_ptr;
3454 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
3455 uint64_t src = src64 & src64_mask;
3457 return (uint32_t)src;
3460 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3462 static inline uint32_t
3463 instr_meter_length_nbo(struct thread *t, const struct instruction *ip)
3465 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3466 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3467 uint64_t src64 = *src64_ptr;
3468 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
3470 return (uint32_t)src;
3475 #define instr_meter_length_nbo instr_meter_length_hbo
3479 static inline enum rte_color
3480 instr_meter_color_in_hbo(struct thread *t, const struct instruction *ip)
3482 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
3483 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
3484 uint64_t src64 = *src64_ptr;
3485 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
3486 uint64_t src = src64 & src64_mask;
3488 return (enum rte_color)src;
3492 instr_meter_color_out_hbo_set(struct thread *t,
3493 const struct instruction *ip,
3494 enum rte_color color_out)
3496 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
3497 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
3498 uint64_t dst64 = *dst64_ptr;
3499 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
3501 uint64_t src = (uint64_t)color_out;
3503 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3507 __instr_metprefetch_h_exec(struct rte_swx_pipeline *p,
3509 const struct instruction *ip)
3513 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
3515 m = instr_meter_idx_nbo(p, t, ip);
3520 __instr_metprefetch_m_exec(struct rte_swx_pipeline *p,
3522 const struct instruction *ip)
3526 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
3528 m = instr_meter_idx_hbo(p, t, ip);
3533 __instr_metprefetch_i_exec(struct rte_swx_pipeline *p,
3534 struct thread *t __rte_unused,
3535 const struct instruction *ip)
3539 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
3541 m = instr_meter_idx_imm(p, ip);
3546 __instr_meter_hhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3549 uint64_t time, n_pkts, n_bytes;
3551 enum rte_color color_in, color_out;
3553 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
3555 m = instr_meter_idx_nbo(p, t, ip);
3556 rte_prefetch0(m->n_pkts);
3557 time = rte_get_tsc_cycles();
3558 length = instr_meter_length_nbo(t, ip);
3559 color_in = instr_meter_color_in_hbo(t, ip);
3561 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3562 &m->profile->profile,
3567 color_out &= m->color_mask;
3569 n_pkts = m->n_pkts[color_out];
3570 n_bytes = m->n_bytes[color_out];
3572 instr_meter_color_out_hbo_set(t, ip, color_out);
3574 m->n_pkts[color_out] = n_pkts + 1;
3575 m->n_bytes[color_out] = n_bytes + length;
3579 __instr_meter_hhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3582 uint64_t time, n_pkts, n_bytes;
3584 enum rte_color color_in, color_out;
3586 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
3588 m = instr_meter_idx_nbo(p, t, ip);
3589 rte_prefetch0(m->n_pkts);
3590 time = rte_get_tsc_cycles();
3591 length = instr_meter_length_nbo(t, ip);
3592 color_in = (enum rte_color)ip->meter.color_in_val;
3594 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3595 &m->profile->profile,
3600 color_out &= m->color_mask;
3602 n_pkts = m->n_pkts[color_out];
3603 n_bytes = m->n_bytes[color_out];
3605 instr_meter_color_out_hbo_set(t, ip, color_out);
3607 m->n_pkts[color_out] = n_pkts + 1;
3608 m->n_bytes[color_out] = n_bytes + length;
3612 __instr_meter_hmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3615 uint64_t time, n_pkts, n_bytes;
3617 enum rte_color color_in, color_out;
3619 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
3621 m = instr_meter_idx_nbo(p, t, ip);
3622 rte_prefetch0(m->n_pkts);
3623 time = rte_get_tsc_cycles();
3624 length = instr_meter_length_hbo(t, ip);
3625 color_in = instr_meter_color_in_hbo(t, ip);
3627 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3628 &m->profile->profile,
3633 color_out &= m->color_mask;
3635 n_pkts = m->n_pkts[color_out];
3636 n_bytes = m->n_bytes[color_out];
3638 instr_meter_color_out_hbo_set(t, ip, color_out);
3640 m->n_pkts[color_out] = n_pkts + 1;
3641 m->n_bytes[color_out] = n_bytes + length;
3645 __instr_meter_hmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3648 uint64_t time, n_pkts, n_bytes;
3650 enum rte_color color_in, color_out;
3652 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
3654 m = instr_meter_idx_nbo(p, t, ip);
3655 rte_prefetch0(m->n_pkts);
3656 time = rte_get_tsc_cycles();
3657 length = instr_meter_length_hbo(t, ip);
3658 color_in = (enum rte_color)ip->meter.color_in_val;
3660 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3661 &m->profile->profile,
3666 color_out &= m->color_mask;
3668 n_pkts = m->n_pkts[color_out];
3669 n_bytes = m->n_bytes[color_out];
3671 instr_meter_color_out_hbo_set(t, ip, color_out);
3673 m->n_pkts[color_out] = n_pkts + 1;
3674 m->n_bytes[color_out] = n_bytes + length;
3678 __instr_meter_mhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3681 uint64_t time, n_pkts, n_bytes;
3683 enum rte_color color_in, color_out;
3685 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
3687 m = instr_meter_idx_hbo(p, t, ip);
3688 rte_prefetch0(m->n_pkts);
3689 time = rte_get_tsc_cycles();
3690 length = instr_meter_length_nbo(t, ip);
3691 color_in = instr_meter_color_in_hbo(t, ip);
3693 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3694 &m->profile->profile,
3699 color_out &= m->color_mask;
3701 n_pkts = m->n_pkts[color_out];
3702 n_bytes = m->n_bytes[color_out];
3704 instr_meter_color_out_hbo_set(t, ip, color_out);
3706 m->n_pkts[color_out] = n_pkts + 1;
3707 m->n_bytes[color_out] = n_bytes + length;
3711 __instr_meter_mhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3714 uint64_t time, n_pkts, n_bytes;
3716 enum rte_color color_in, color_out;
3718 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
3720 m = instr_meter_idx_hbo(p, t, ip);
3721 rte_prefetch0(m->n_pkts);
3722 time = rte_get_tsc_cycles();
3723 length = instr_meter_length_nbo(t, ip);
3724 color_in = (enum rte_color)ip->meter.color_in_val;
3726 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3727 &m->profile->profile,
3732 color_out &= m->color_mask;
3734 n_pkts = m->n_pkts[color_out];
3735 n_bytes = m->n_bytes[color_out];
3737 instr_meter_color_out_hbo_set(t, ip, color_out);
3739 m->n_pkts[color_out] = n_pkts + 1;
3740 m->n_bytes[color_out] = n_bytes + length;
3744 __instr_meter_mmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3747 uint64_t time, n_pkts, n_bytes;
3749 enum rte_color color_in, color_out;
3751 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
3753 m = instr_meter_idx_hbo(p, t, ip);
3754 rte_prefetch0(m->n_pkts);
3755 time = rte_get_tsc_cycles();
3756 length = instr_meter_length_hbo(t, ip);
3757 color_in = instr_meter_color_in_hbo(t, ip);
3759 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3760 &m->profile->profile,
3765 color_out &= m->color_mask;
3767 n_pkts = m->n_pkts[color_out];
3768 n_bytes = m->n_bytes[color_out];
3770 instr_meter_color_out_hbo_set(t, ip, color_out);
3772 m->n_pkts[color_out] = n_pkts + 1;
3773 m->n_bytes[color_out] = n_bytes + length;
3777 __instr_meter_mmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3780 uint64_t time, n_pkts, n_bytes;
3782 enum rte_color color_in, color_out;
3784 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
3786 m = instr_meter_idx_hbo(p, t, ip);
3787 rte_prefetch0(m->n_pkts);
3788 time = rte_get_tsc_cycles();
3789 length = instr_meter_length_hbo(t, ip);
3790 color_in = (enum rte_color)ip->meter.color_in_val;
3792 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3793 &m->profile->profile,
3798 color_out &= m->color_mask;
3800 n_pkts = m->n_pkts[color_out];
3801 n_bytes = m->n_bytes[color_out];
3803 instr_meter_color_out_hbo_set(t, ip, color_out);
3805 m->n_pkts[color_out] = n_pkts + 1;
3806 m->n_bytes[color_out] = n_bytes + length;
3810 __instr_meter_ihm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3813 uint64_t time, n_pkts, n_bytes;
3815 enum rte_color color_in, color_out;
3817 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
3819 m = instr_meter_idx_imm(p, ip);
3820 rte_prefetch0(m->n_pkts);
3821 time = rte_get_tsc_cycles();
3822 length = instr_meter_length_nbo(t, ip);
3823 color_in = instr_meter_color_in_hbo(t, ip);
3825 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3826 &m->profile->profile,
3831 color_out &= m->color_mask;
3833 n_pkts = m->n_pkts[color_out];
3834 n_bytes = m->n_bytes[color_out];
3836 instr_meter_color_out_hbo_set(t, ip, color_out);
3838 m->n_pkts[color_out] = n_pkts + 1;
3839 m->n_bytes[color_out] = n_bytes + length;
3843 __instr_meter_ihi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3846 uint64_t time, n_pkts, n_bytes;
3848 enum rte_color color_in, color_out;
3850 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
3852 m = instr_meter_idx_imm(p, ip);
3853 rte_prefetch0(m->n_pkts);
3854 time = rte_get_tsc_cycles();
3855 length = instr_meter_length_nbo(t, ip);
3856 color_in = (enum rte_color)ip->meter.color_in_val;
3858 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3859 &m->profile->profile,
3864 color_out &= m->color_mask;
3866 n_pkts = m->n_pkts[color_out];
3867 n_bytes = m->n_bytes[color_out];
3869 instr_meter_color_out_hbo_set(t, ip, color_out);
3871 m->n_pkts[color_out] = n_pkts + 1;
3872 m->n_bytes[color_out] = n_bytes + length;
3876 __instr_meter_imm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3879 uint64_t time, n_pkts, n_bytes;
3881 enum rte_color color_in, color_out;
3883 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
3885 m = instr_meter_idx_imm(p, ip);
3886 rte_prefetch0(m->n_pkts);
3887 time = rte_get_tsc_cycles();
3888 length = instr_meter_length_hbo(t, ip);
3889 color_in = instr_meter_color_in_hbo(t, ip);
3891 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3892 &m->profile->profile,
3897 color_out &= m->color_mask;
3899 n_pkts = m->n_pkts[color_out];
3900 n_bytes = m->n_bytes[color_out];
3902 instr_meter_color_out_hbo_set(t, ip, color_out);
3904 m->n_pkts[color_out] = n_pkts + 1;
3905 m->n_bytes[color_out] = n_bytes + length;
3909 __instr_meter_imi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3912 uint64_t time, n_pkts, n_bytes;
3914 enum rte_color color_in, color_out;
3916 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
3918 m = instr_meter_idx_imm(p, ip);
3919 rte_prefetch0(m->n_pkts);
3920 time = rte_get_tsc_cycles();
3921 length = instr_meter_length_hbo(t, ip);
3922 color_in = (enum rte_color)ip->meter.color_in_val;
3924 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3925 &m->profile->profile,
3930 color_out &= m->color_mask;
3932 n_pkts = m->n_pkts[color_out];
3933 n_bytes = m->n_bytes[color_out];
3935 instr_meter_color_out_hbo_set(t, ip, color_out);
3937 m->n_pkts[color_out] = n_pkts + 1;
3938 m->n_bytes[color_out] = n_bytes + length;