X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pipeline%2Frte_swx_pipeline.c;h=3dd578439386800c354c3d4b23a330c1be20d18f;hb=64cfcebd6890fdc60c12eac09e1f066223a3d4e6;hp=9d64611018d4dd39e54af8f3eb303b8fb1821f8c;hpb=ccbbb7f23fe3c88e19d1124ec48f0d636272eefb;p=dpdk.git diff --git a/lib/librte_pipeline/rte_swx_pipeline.c b/lib/librte_pipeline/rte_swx_pipeline.c index 9d64611018..3dd5784393 100644 --- a/lib/librte_pipeline/rte_swx_pipeline.c +++ b/lib/librte_pipeline/rte_swx_pipeline.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,17 @@ do { \ } while (0) #define CHECK_NAME(name, err_code) \ - CHECK((name) && (name)[0], err_code) + CHECK((name) && \ + (name)[0] && \ + (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \ + err_code) + +#define CHECK_INSTRUCTION(instr, err_code) \ + CHECK((instr) && \ + (instr)[0] && \ + (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \ + RTE_SWX_INSTRUCTION_SIZE), \ + err_code) #ifndef TRACE_LEVEL #define TRACE_LEVEL 0 @@ -34,9 +45,59 @@ do { \ #define TRACE(...) #endif +/* + * Environment. + */ #define ntoh64(x) rte_be_to_cpu_64(x) #define hton64(x) rte_cpu_to_be_64(x) +#ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE + +#include + +static void * +env_malloc(size_t size, size_t alignment, int numa_node) +{ + return rte_zmalloc_socket(NULL, size, alignment, numa_node); +} + +static void +env_free(void *start, size_t size __rte_unused) +{ + rte_free(start); +} + +#else + +#include + +static void * +env_malloc(size_t size, size_t alignment __rte_unused, int numa_node) +{ + void *start; + + if (numa_available() == -1) + return NULL; + + start = numa_alloc_onnode(size, numa_node); + if (!start) + return NULL; + + memset(start, 0, size); + return start; +} + +static void +env_free(void *start, size_t size) +{ + if (numa_available() == -1) + return; + + numa_free(start, size); +} + +#endif + /* * Struct. */ @@ -350,6 +411,53 @@ enum instruction_type { INSTR_ALU_SHR_MI, /* dst = MEF, src = I */ INSTR_ALU_SHR_HI, /* dst = H, src = I */ + /* regprefetch REGARRAY index + * prefetch REGARRAY[index] + * index = HMEFTI + */ + INSTR_REGPREFETCH_RH, /* index = H */ + INSTR_REGPREFETCH_RM, /* index = MEFT */ + INSTR_REGPREFETCH_RI, /* index = I */ + + /* regrd dst REGARRAY index + * dst = REGARRAY[index] + * dst = HMEF, index = HMEFTI + */ + INSTR_REGRD_HRH, /* dst = H, index = H */ + INSTR_REGRD_HRM, /* dst = H, index = MEFT */ + INSTR_REGRD_HRI, /* dst = H, index = I */ + INSTR_REGRD_MRH, /* dst = MEF, index = H */ + INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */ + INSTR_REGRD_MRI, /* dst = MEF, index = I */ + + /* regwr REGARRAY index src + * REGARRAY[index] = src + * index = HMEFTI, src = HMEFTI + */ + INSTR_REGWR_RHH, /* index = H, src = H */ + INSTR_REGWR_RHM, /* index = H, src = MEFT */ + INSTR_REGWR_RHI, /* index = H, src = I */ + INSTR_REGWR_RMH, /* index = MEFT, src = H */ + INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */ + INSTR_REGWR_RMI, /* index = MEFT, src = I */ + INSTR_REGWR_RIH, /* index = I, src = H */ + INSTR_REGWR_RIM, /* index = I, src = MEFT */ + INSTR_REGWR_RII, /* index = I, src = I */ + + /* regadd REGARRAY index src + * REGARRAY[index] += src + * index = HMEFTI, src = HMEFTI + */ + INSTR_REGADD_RHH, /* index = H, src = H */ + INSTR_REGADD_RHM, /* index = H, src = MEFT */ + INSTR_REGADD_RHI, /* index = H, src = I */ + INSTR_REGADD_RMH, /* index = MEFT, src = H */ + INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */ + INSTR_REGADD_RMI, /* index = MEFT, src = I */ + INSTR_REGADD_RIH, /* index = I, src = H */ + INSTR_REGADD_RIM, /* index = I, src = MEFT */ + INSTR_REGADD_RII, /* index = I, src = I */ + /* table TABLE */ INSTR_TABLE, @@ -480,7 +588,22 @@ struct instr_dst_src { struct instr_operand dst; union { struct instr_operand src; - uint32_t src_val; + uint64_t src_val; + }; +}; + +struct instr_regarray { + uint8_t regarray_id; + uint8_t pad[3]; + + union { + struct instr_operand idx; + uint32_t idx_val; + }; + + union { + struct instr_operand dstsrc; + uint64_t dstsrc_val; }; }; @@ -508,7 +631,7 @@ struct instr_jmp { union { struct instr_operand b; - uint32_t b_val; + uint64_t b_val; }; }; @@ -518,6 +641,7 @@ struct instruction { struct instr_io io; struct instr_hdr_validity valid; struct instr_dst_src mov; + struct instr_regarray regarray; struct instr_dma dma; struct instr_dst_src alu; struct instr_table table; @@ -597,6 +721,24 @@ struct table_runtime { uint8_t **key; }; +/* + * Register array. + */ +struct regarray { + TAILQ_ENTRY(regarray) node; + char name[RTE_SWX_NAME_SIZE]; + uint64_t init_val; + uint32_t size; + uint32_t id; +}; + +TAILQ_HEAD(regarray_tailq, regarray); + +struct regarray_runtime { + uint64_t *regarray; + uint32_t size_mask; +}; + /* * Pipeline. */ @@ -972,11 +1114,13 @@ struct rte_swx_pipeline { struct action_tailq actions; struct table_type_tailq table_types; struct table_tailq tables; + struct regarray_tailq regarrays; struct port_in_runtime *in; struct port_out_runtime *out; struct instruction **action_instructions; struct rte_swx_table_state *table_state; + struct regarray_runtime *regarray_runtime; struct instruction *instructions; struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX]; @@ -987,6 +1131,7 @@ struct rte_swx_pipeline { uint32_t n_extern_funcs; uint32_t n_actions; uint32_t n_tables; + uint32_t n_regarrays; uint32_t n_headers; uint32_t thread_id; uint32_t port_id; @@ -1635,12 +1780,12 @@ rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p, CHECK(p, EINVAL); - CHECK(extern_type_name, EINVAL); + CHECK_NAME(extern_type_name, EINVAL); type = extern_type_find(p, extern_type_name); CHECK(type, EINVAL); CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC); - CHECK(name, EINVAL); + CHECK_NAME(name, EINVAL); CHECK(!extern_type_member_func_find(type, name), EEXIST); CHECK(member_func, EINVAL); @@ -3189,7 +3334,8 @@ instr_mov_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3214,17 +3360,17 @@ instr_mov_translate(struct rte_swx_pipeline *p, } /* MOV_I. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); if (dst[0] == 'h') - src_val = htonl(src_val); + src_val = hton64(src_val) >> (64 - fdst->n_bits); instr->type = INSTR_MOV_I; instr->mov.dst.struct_id = (uint8_t)dst_struct_id; instr->mov.dst.n_bits = fdst->n_bits; instr->mov.dst.offset = fdst->offset / 8; - instr->mov.src_val = (uint32_t)src_val; + instr->mov.src_val = src_val; return 0; } @@ -3264,7 +3410,7 @@ instr_mov_i_exec(struct rte_swx_pipeline *p) struct thread *t = &p->threads[p->thread_id]; struct instruction *ip = t->ip; - TRACE("[Thread %2u] mov m.f %x\n", + TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val); @@ -3451,7 +3597,8 @@ instr_alu_add_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3462,9 +3609,9 @@ instr_alu_add_translate(struct rte_swx_pipeline *p, fsrc = struct_field_parse(p, action, src, &src_struct_id); if (fsrc) { instr->type = INSTR_ALU_ADD; - if (dst[0] == 'h' && src[0] == 'm') + if (dst[0] == 'h' && src[0] != 'h') instr->type = INSTR_ALU_ADD_HM; - if (dst[0] == 'm' && src[0] == 'h') + if (dst[0] != 'h' && src[0] == 'h') instr->type = INSTR_ALU_ADD_MH; if (dst[0] == 'h' && src[0] == 'h') instr->type = INSTR_ALU_ADD_HH; @@ -3479,7 +3626,7 @@ instr_alu_add_translate(struct rte_swx_pipeline *p, } /* ADD_MI, ADD_HI. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); instr->type = INSTR_ALU_ADD_MI; @@ -3489,7 +3636,7 @@ instr_alu_add_translate(struct rte_swx_pipeline *p, instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -3503,7 +3650,8 @@ instr_alu_sub_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3514,9 +3662,9 @@ instr_alu_sub_translate(struct rte_swx_pipeline *p, fsrc = struct_field_parse(p, action, src, &src_struct_id); if (fsrc) { instr->type = INSTR_ALU_SUB; - if (dst[0] == 'h' && src[0] == 'm') + if (dst[0] == 'h' && src[0] != 'h') instr->type = INSTR_ALU_SUB_HM; - if (dst[0] == 'm' && src[0] == 'h') + if (dst[0] != 'h' && src[0] == 'h') instr->type = INSTR_ALU_SUB_MH; if (dst[0] == 'h' && src[0] == 'h') instr->type = INSTR_ALU_SUB_HH; @@ -3531,7 +3679,7 @@ instr_alu_sub_translate(struct rte_swx_pipeline *p, } /* SUB_MI, SUB_HI. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); instr->type = INSTR_ALU_SUB_MI; @@ -3541,7 +3689,7 @@ instr_alu_sub_translate(struct rte_swx_pipeline *p, instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -3632,7 +3780,8 @@ instr_alu_shl_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3643,9 +3792,9 @@ instr_alu_shl_translate(struct rte_swx_pipeline *p, fsrc = struct_field_parse(p, action, src, &src_struct_id); if (fsrc) { instr->type = INSTR_ALU_SHL; - if (dst[0] == 'h' && src[0] == 'm') + if (dst[0] == 'h' && src[0] != 'h') instr->type = INSTR_ALU_SHL_HM; - if (dst[0] == 'm' && src[0] == 'h') + if (dst[0] != 'h' && src[0] == 'h') instr->type = INSTR_ALU_SHL_MH; if (dst[0] == 'h' && src[0] == 'h') instr->type = INSTR_ALU_SHL_HH; @@ -3660,7 +3809,7 @@ instr_alu_shl_translate(struct rte_swx_pipeline *p, } /* SHL_MI, SHL_HI. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); instr->type = INSTR_ALU_SHL_MI; @@ -3670,7 +3819,7 @@ instr_alu_shl_translate(struct rte_swx_pipeline *p, instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -3684,7 +3833,8 @@ instr_alu_shr_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3695,9 +3845,9 @@ instr_alu_shr_translate(struct rte_swx_pipeline *p, fsrc = struct_field_parse(p, action, src, &src_struct_id); if (fsrc) { instr->type = INSTR_ALU_SHR; - if (dst[0] == 'h' && src[0] == 'm') + if (dst[0] == 'h' && src[0] != 'h') instr->type = INSTR_ALU_SHR_HM; - if (dst[0] == 'm' && src[0] == 'h') + if (dst[0] != 'h' && src[0] == 'h') instr->type = INSTR_ALU_SHR_MH; if (dst[0] == 'h' && src[0] == 'h') instr->type = INSTR_ALU_SHR_HH; @@ -3712,7 +3862,7 @@ instr_alu_shr_translate(struct rte_swx_pipeline *p, } /* SHR_MI, SHR_HI. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); instr->type = INSTR_ALU_SHR_MI; @@ -3722,7 +3872,7 @@ instr_alu_shr_translate(struct rte_swx_pipeline *p, instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -3736,7 +3886,8 @@ instr_alu_and_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3761,17 +3912,17 @@ instr_alu_and_translate(struct rte_swx_pipeline *p, } /* AND_I. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); if (dst[0] == 'h') - src_val = htonl(src_val); + src_val = hton64(src_val) >> (64 - fdst->n_bits); instr->type = INSTR_ALU_AND_I; instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -3785,7 +3936,8 @@ instr_alu_or_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3810,17 +3962,17 @@ instr_alu_or_translate(struct rte_swx_pipeline *p, } /* OR_I. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); if (dst[0] == 'h') - src_val = htonl(src_val); + src_val = hton64(src_val) >> (64 - fdst->n_bits); instr->type = INSTR_ALU_OR_I; instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -3834,7 +3986,8 @@ instr_alu_xor_translate(struct rte_swx_pipeline *p, { char *dst = tokens[1], *src = tokens[2]; struct field *fdst, *fsrc; - uint32_t dst_struct_id, src_struct_id, src_val; + uint64_t src_val; + uint32_t dst_struct_id, src_struct_id; CHECK(n_tokens == 3, EINVAL); @@ -3859,17 +4012,17 @@ instr_alu_xor_translate(struct rte_swx_pipeline *p, } /* XOR_I. */ - src_val = strtoul(src, &src, 0); + src_val = strtoull(src, &src, 0); CHECK(!src[0], EINVAL); if (dst[0] == 'h') - src_val = htonl(src_val); + src_val = hton64(src_val) >> (64 - fdst->n_bits); instr->type = INSTR_ALU_XOR_I; instr->alu.dst.struct_id = (uint8_t)dst_struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; - instr->alu.src_val = (uint32_t)src_val; + instr->alu.src_val = src_val; return 0; } @@ -4603,229 +4756,1133 @@ instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p) } /* - * jmp. + * Register array. */ -static struct action * -action_find(struct rte_swx_pipeline *p, const char *name); - -static int -instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused, - struct action *action __rte_unused, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) -{ - CHECK(n_tokens == 2, EINVAL); - - strcpy(data->jmp_label, tokens[1]); - - instr->type = INSTR_JMP; - instr->jmp.ip = NULL; /* Resolved later. */ - return 0; -} +static struct regarray * +regarray_find(struct rte_swx_pipeline *p, const char *name); static int -instr_jmp_valid_translate(struct rte_swx_pipeline *p, - struct action *action __rte_unused, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) +instr_regprefetch_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data __rte_unused) { - struct header *h; + char *regarray = tokens[1], *idx = tokens[2]; + struct regarray *r; + struct field *fidx; + uint32_t idx_struct_id, idx_val; CHECK(n_tokens == 3, EINVAL); - strcpy(data->jmp_label, tokens[1]); + r = regarray_find(p, regarray); + CHECK(r, EINVAL); + + /* REGPREFETCH_RH, REGPREFETCH_RM. */ + fidx = struct_field_parse(p, action, idx, &idx_struct_id); + if (fidx) { + instr->type = INSTR_REGPREFETCH_RM; + if (idx[0] == 'h') + instr->type = INSTR_REGPREFETCH_RH; + + instr->regarray.regarray_id = r->id; + instr->regarray.idx.struct_id = (uint8_t)idx_struct_id; + instr->regarray.idx.n_bits = fidx->n_bits; + instr->regarray.idx.offset = fidx->offset / 8; + instr->regarray.dstsrc_val = 0; /* Unused. */ + return 0; + } - h = header_parse(p, tokens[2]); - CHECK(h, EINVAL); + /* REGPREFETCH_RI. */ + idx_val = strtoul(idx, &idx, 0); + CHECK(!idx[0], EINVAL); - instr->type = INSTR_JMP_VALID; - instr->jmp.ip = NULL; /* Resolved later. */ - instr->jmp.header_id = h->id; + instr->type = INSTR_REGPREFETCH_RI; + instr->regarray.regarray_id = r->id; + instr->regarray.idx_val = idx_val; + instr->regarray.dstsrc_val = 0; /* Unused. */ return 0; } static int -instr_jmp_invalid_translate(struct rte_swx_pipeline *p, - struct action *action __rte_unused, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) +instr_regrd_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data __rte_unused) { - struct header *h; + char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3]; + struct regarray *r; + struct field *fdst, *fidx; + uint32_t dst_struct_id, idx_struct_id, idx_val; - CHECK(n_tokens == 3, EINVAL); + CHECK(n_tokens == 4, EINVAL); - strcpy(data->jmp_label, tokens[1]); + r = regarray_find(p, regarray); + CHECK(r, EINVAL); - h = header_parse(p, tokens[2]); - CHECK(h, EINVAL); + fdst = struct_field_parse(p, NULL, dst, &dst_struct_id); + CHECK(fdst, EINVAL); - instr->type = INSTR_JMP_INVALID; - instr->jmp.ip = NULL; /* Resolved later. */ - instr->jmp.header_id = h->id; - return 0; -} + /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */ + fidx = struct_field_parse(p, action, idx, &idx_struct_id); + if (fidx) { + instr->type = INSTR_REGRD_MRM; + if (dst[0] == 'h' && idx[0] != 'h') + instr->type = INSTR_REGRD_HRM; + if (dst[0] != 'h' && idx[0] == 'h') + instr->type = INSTR_REGRD_MRH; + if (dst[0] == 'h' && idx[0] == 'h') + instr->type = INSTR_REGRD_HRH; + + instr->regarray.regarray_id = r->id; + instr->regarray.idx.struct_id = (uint8_t)idx_struct_id; + instr->regarray.idx.n_bits = fidx->n_bits; + instr->regarray.idx.offset = fidx->offset / 8; + instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id; + instr->regarray.dstsrc.n_bits = fdst->n_bits; + instr->regarray.dstsrc.offset = fdst->offset / 8; + return 0; + } -static int -instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused, - struct action *action, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) -{ - CHECK(!action, EINVAL); - CHECK(n_tokens == 2, EINVAL); + /* REGRD_MRI, REGRD_HRI. */ + idx_val = strtoul(idx, &idx, 0); + CHECK(!idx[0], EINVAL); - strcpy(data->jmp_label, tokens[1]); + instr->type = INSTR_REGRD_MRI; + if (dst[0] == 'h') + instr->type = INSTR_REGRD_HRI; - instr->type = INSTR_JMP_HIT; - instr->jmp.ip = NULL; /* Resolved later. */ + instr->regarray.regarray_id = r->id; + instr->regarray.idx_val = idx_val; + instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id; + instr->regarray.dstsrc.n_bits = fdst->n_bits; + instr->regarray.dstsrc.offset = fdst->offset / 8; return 0; } static int -instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused, - struct action *action, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) +instr_regwr_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data __rte_unused) { - CHECK(!action, EINVAL); - CHECK(n_tokens == 2, EINVAL); + char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3]; + struct regarray *r; + struct field *fidx, *fsrc; + uint64_t src_val; + uint32_t idx_struct_id, idx_val, src_struct_id; - strcpy(data->jmp_label, tokens[1]); + CHECK(n_tokens == 4, EINVAL); - instr->type = INSTR_JMP_MISS; - instr->jmp.ip = NULL; /* Resolved later. */ - return 0; -} + r = regarray_find(p, regarray); + CHECK(r, EINVAL); -static int -instr_jmp_action_hit_translate(struct rte_swx_pipeline *p, - struct action *action, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) -{ - struct action *a; + /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */ + fidx = struct_field_parse(p, action, idx, &idx_struct_id); + fsrc = struct_field_parse(p, action, src, &src_struct_id); + if (fidx && fsrc) { + instr->type = INSTR_REGWR_RMM; + if (idx[0] == 'h' && src[0] != 'h') + instr->type = INSTR_REGWR_RHM; + if (idx[0] != 'h' && src[0] == 'h') + instr->type = INSTR_REGWR_RMH; + if (idx[0] == 'h' && src[0] == 'h') + instr->type = INSTR_REGWR_RHH; + + instr->regarray.regarray_id = r->id; + instr->regarray.idx.struct_id = (uint8_t)idx_struct_id; + instr->regarray.idx.n_bits = fidx->n_bits; + instr->regarray.idx.offset = fidx->offset / 8; + instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id; + instr->regarray.dstsrc.n_bits = fsrc->n_bits; + instr->regarray.dstsrc.offset = fsrc->offset / 8; + return 0; + } - CHECK(!action, EINVAL); - CHECK(n_tokens == 3, EINVAL); + /* REGWR_RHI, REGWR_RMI. */ + if (fidx && !fsrc) { + src_val = strtoull(src, &src, 0); + CHECK(!src[0], EINVAL); - strcpy(data->jmp_label, tokens[1]); + instr->type = INSTR_REGWR_RMI; + if (idx[0] == 'h') + instr->type = INSTR_REGWR_RHI; - a = action_find(p, tokens[2]); - CHECK(a, EINVAL); + instr->regarray.regarray_id = r->id; + instr->regarray.idx.struct_id = (uint8_t)idx_struct_id; + instr->regarray.idx.n_bits = fidx->n_bits; + instr->regarray.idx.offset = fidx->offset / 8; + instr->regarray.dstsrc_val = src_val; + return 0; + } - instr->type = INSTR_JMP_ACTION_HIT; - instr->jmp.ip = NULL; /* Resolved later. */ - instr->jmp.action_id = a->id; - return 0; -} + /* REGWR_RIH, REGWR_RIM. */ + if (!fidx && fsrc) { + idx_val = strtoul(idx, &idx, 0); + CHECK(!idx[0], EINVAL); -static int -instr_jmp_action_miss_translate(struct rte_swx_pipeline *p, - struct action *action, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) -{ - struct action *a; + instr->type = INSTR_REGWR_RIM; + if (src[0] == 'h') + instr->type = INSTR_REGWR_RIH; - CHECK(!action, EINVAL); - CHECK(n_tokens == 3, EINVAL); + instr->regarray.regarray_id = r->id; + instr->regarray.idx_val = idx_val; + instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id; + instr->regarray.dstsrc.n_bits = fsrc->n_bits; + instr->regarray.dstsrc.offset = fsrc->offset / 8; + return 0; + } - strcpy(data->jmp_label, tokens[1]); + /* REGWR_RII. */ + src_val = strtoull(src, &src, 0); + CHECK(!src[0], EINVAL); - a = action_find(p, tokens[2]); - CHECK(a, EINVAL); + idx_val = strtoul(idx, &idx, 0); + CHECK(!idx[0], EINVAL); + + instr->type = INSTR_REGWR_RII; + instr->regarray.idx_val = idx_val; + instr->regarray.dstsrc_val = src_val; - instr->type = INSTR_JMP_ACTION_MISS; - instr->jmp.ip = NULL; /* Resolved later. */ - instr->jmp.action_id = a->id; return 0; } static int -instr_jmp_eq_translate(struct rte_swx_pipeline *p, +instr_regadd_translate(struct rte_swx_pipeline *p, struct action *action, char **tokens, int n_tokens, struct instruction *instr, - struct instruction_data *data) + struct instruction_data *data __rte_unused) { - char *a = tokens[2], *b = tokens[3]; - struct field *fa, *fb; - uint32_t a_struct_id, b_struct_id, b_val; + char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3]; + struct regarray *r; + struct field *fidx, *fsrc; + uint64_t src_val; + uint32_t idx_struct_id, idx_val, src_struct_id; CHECK(n_tokens == 4, EINVAL); - strcpy(data->jmp_label, tokens[1]); + r = regarray_find(p, regarray); + CHECK(r, EINVAL); - fa = struct_field_parse(p, action, a, &a_struct_id); - CHECK(fa, EINVAL); + /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */ + fidx = struct_field_parse(p, action, idx, &idx_struct_id); + fsrc = struct_field_parse(p, action, src, &src_struct_id); + if (fidx && fsrc) { + instr->type = INSTR_REGADD_RMM; + if (idx[0] == 'h' && src[0] != 'h') + instr->type = INSTR_REGADD_RHM; + if (idx[0] != 'h' && src[0] == 'h') + instr->type = INSTR_REGADD_RMH; + if (idx[0] == 'h' && src[0] == 'h') + instr->type = INSTR_REGADD_RHH; + + instr->regarray.regarray_id = r->id; + instr->regarray.idx.struct_id = (uint8_t)idx_struct_id; + instr->regarray.idx.n_bits = fidx->n_bits; + instr->regarray.idx.offset = fidx->offset / 8; + instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id; + instr->regarray.dstsrc.n_bits = fsrc->n_bits; + instr->regarray.dstsrc.offset = fsrc->offset / 8; + return 0; + } - /* JMP_EQ or JMP_EQ_S. */ - fb = struct_field_parse(p, action, b, &b_struct_id); - if (fb) { - instr->type = INSTR_JMP_EQ; - if ((a[0] == 'h' && b[0] != 'h') || - (a[0] != 'h' && b[0] == 'h')) - instr->type = INSTR_JMP_EQ_S; - instr->jmp.ip = NULL; /* Resolved later. */ + /* REGADD_RHI, REGADD_RMI. */ + if (fidx && !fsrc) { + src_val = strtoull(src, &src, 0); + CHECK(!src[0], EINVAL); - instr->jmp.a.struct_id = (uint8_t)a_struct_id; - instr->jmp.a.n_bits = fa->n_bits; - instr->jmp.a.offset = fa->offset / 8; - instr->jmp.b.struct_id = (uint8_t)b_struct_id; - instr->jmp.b.n_bits = fb->n_bits; - instr->jmp.b.offset = fb->offset / 8; + instr->type = INSTR_REGADD_RMI; + if (idx[0] == 'h') + instr->type = INSTR_REGADD_RHI; + + instr->regarray.regarray_id = r->id; + instr->regarray.idx.struct_id = (uint8_t)idx_struct_id; + instr->regarray.idx.n_bits = fidx->n_bits; + instr->regarray.idx.offset = fidx->offset / 8; + instr->regarray.dstsrc_val = src_val; return 0; } - /* JMP_EQ_I. */ - b_val = strtoul(b, &b, 0); - CHECK(!b[0], EINVAL); + /* REGADD_RIH, REGADD_RIM. */ + if (!fidx && fsrc) { + idx_val = strtoul(idx, &idx, 0); + CHECK(!idx[0], EINVAL); - if (a[0] == 'h') - b_val = htonl(b_val); + instr->type = INSTR_REGADD_RIM; + if (src[0] == 'h') + instr->type = INSTR_REGADD_RIH; - instr->type = INSTR_JMP_EQ_I; - instr->jmp.ip = NULL; /* Resolved later. */ - instr->jmp.a.struct_id = (uint8_t)a_struct_id; - instr->jmp.a.n_bits = fa->n_bits; - instr->jmp.a.offset = fa->offset / 8; - instr->jmp.b_val = (uint32_t)b_val; + instr->regarray.regarray_id = r->id; + instr->regarray.idx_val = idx_val; + instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id; + instr->regarray.dstsrc.n_bits = fsrc->n_bits; + instr->regarray.dstsrc.offset = fsrc->offset / 8; + return 0; + } + + /* REGADD_RII. */ + src_val = strtoull(src, &src, 0); + CHECK(!src[0], EINVAL); + + idx_val = strtoul(idx, &idx, 0); + CHECK(!idx[0], EINVAL); + + instr->type = INSTR_REGADD_RII; + instr->regarray.idx_val = idx_val; + instr->regarray.dstsrc_val = src_val; return 0; } -static int -instr_jmp_neq_translate(struct rte_swx_pipeline *p, - struct action *action, - char **tokens, - int n_tokens, - struct instruction *instr, - struct instruction_data *data) +static inline uint64_t * +instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip) { - char *a = tokens[2], *b = tokens[3]; - struct field *fa, *fb; - uint32_t a_struct_id, b_struct_id, b_val; + struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id]; + return r->regarray; +} - CHECK(n_tokens == 4, EINVAL); +static inline uint64_t +instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip) +{ + struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id]; - strcpy(data->jmp_label, tokens[1]); + uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id]; + uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset]; + uint64_t idx64 = *idx64_ptr; + uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits); + uint64_t idx = idx64 & idx64_mask & r->size_mask; - fa = struct_field_parse(p, action, a, &a_struct_id); - CHECK(fa, EINVAL); + return idx; +} + +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + +static inline uint64_t +instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip) +{ + struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id]; + + uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id]; + uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset]; + uint64_t idx64 = *idx64_ptr; + uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask; + + return idx; +} + +#else + +#define instr_regarray_idx_nbo instr_regarray_idx_hbo + +#endif + +static inline uint64_t +instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip) +{ + struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id]; + + uint64_t idx = ip->regarray.idx_val & r->size_mask; + + return idx; +} + +static inline uint64_t +instr_regarray_src_hbo(struct thread *t, struct instruction *ip) +{ + uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id]; + uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset]; + uint64_t src64 = *src64_ptr; + uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits); + uint64_t src = src64 & src64_mask; + + return src; +} + +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + +static inline uint64_t +instr_regarray_src_nbo(struct thread *t, struct instruction *ip) +{ + uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id]; + uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset]; + uint64_t src64 = *src64_ptr; + uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits); + + return src; +} + +#else + +#define instr_regarray_src_nbo instr_regarray_src_hbo + +#endif + +static inline void +instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src) +{ + uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id]; + uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset]; + uint64_t dst64 = *dst64_ptr; + uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits); + + *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); + +} + +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + +static inline void +instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src) +{ + uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id]; + uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset]; + uint64_t dst64 = *dst64_ptr; + uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits); + + src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits); + *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); +} + +#else + +#define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set + +#endif + +static inline void +instr_regprefetch_rh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + rte_prefetch0(®array[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regprefetch_rm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + rte_prefetch0(®array[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regprefetch_ri_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + rte_prefetch0(®array[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regrd_hrh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regrd_hrm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regrd_mrh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regrd_mrm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regrd_hri_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regrd_mri_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx; + + TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rhh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + src = instr_regarray_src_nbo(t, ip); + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rhm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + src = instr_regarray_src_hbo(t, ip); + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rmh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + src = instr_regarray_src_nbo(t, ip); + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rmm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + src = instr_regarray_src_hbo(t, ip); + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rhi_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + src = ip->regarray.dstsrc_val; + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rmi_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + src = ip->regarray.dstsrc_val; + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rih_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + src = instr_regarray_src_nbo(t, ip); + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rim_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + src = instr_regarray_src_hbo(t, ip); + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regwr_rii_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + src = ip->regarray.dstsrc_val; + regarray[idx] = src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rhh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + src = instr_regarray_src_nbo(t, ip); + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rhm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + src = instr_regarray_src_hbo(t, ip); + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rmh_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + src = instr_regarray_src_nbo(t, ip); + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rmm_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + src = instr_regarray_src_hbo(t, ip); + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rhi_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_nbo(p, t, ip); + src = ip->regarray.dstsrc_val; + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rmi_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_hbo(p, t, ip); + src = ip->regarray.dstsrc_val; + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rih_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + src = instr_regarray_src_nbo(t, ip); + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rim_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + src = instr_regarray_src_hbo(t, ip); + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_regadd_rii_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint64_t *regarray, idx, src; + + TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id); + + /* Structs. */ + regarray = instr_regarray_regarray(p, ip); + idx = instr_regarray_idx_imm(p, ip); + src = ip->regarray.dstsrc_val; + regarray[idx] += src; + + /* Thread. */ + thread_ip_inc(p); +} + +/* + * jmp. + */ +static struct action * +action_find(struct rte_swx_pipeline *p, const char *name); + +static int +instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused, + struct action *action __rte_unused, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + CHECK(n_tokens == 2, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + instr->type = INSTR_JMP; + instr->jmp.ip = NULL; /* Resolved later. */ + return 0; +} + +static int +instr_jmp_valid_translate(struct rte_swx_pipeline *p, + struct action *action __rte_unused, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + struct header *h; + + CHECK(n_tokens == 3, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + h = header_parse(p, tokens[2]); + CHECK(h, EINVAL); + + instr->type = INSTR_JMP_VALID; + instr->jmp.ip = NULL; /* Resolved later. */ + instr->jmp.header_id = h->id; + return 0; +} + +static int +instr_jmp_invalid_translate(struct rte_swx_pipeline *p, + struct action *action __rte_unused, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + struct header *h; + + CHECK(n_tokens == 3, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + h = header_parse(p, tokens[2]); + CHECK(h, EINVAL); + + instr->type = INSTR_JMP_INVALID; + instr->jmp.ip = NULL; /* Resolved later. */ + instr->jmp.header_id = h->id; + return 0; +} + +static int +instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + CHECK(!action, EINVAL); + CHECK(n_tokens == 2, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + instr->type = INSTR_JMP_HIT; + instr->jmp.ip = NULL; /* Resolved later. */ + return 0; +} + +static int +instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + CHECK(!action, EINVAL); + CHECK(n_tokens == 2, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + instr->type = INSTR_JMP_MISS; + instr->jmp.ip = NULL; /* Resolved later. */ + return 0; +} + +static int +instr_jmp_action_hit_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + struct action *a; + + CHECK(!action, EINVAL); + CHECK(n_tokens == 3, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + a = action_find(p, tokens[2]); + CHECK(a, EINVAL); + + instr->type = INSTR_JMP_ACTION_HIT; + instr->jmp.ip = NULL; /* Resolved later. */ + instr->jmp.action_id = a->id; + return 0; +} + +static int +instr_jmp_action_miss_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + struct action *a; + + CHECK(!action, EINVAL); + CHECK(n_tokens == 3, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + a = action_find(p, tokens[2]); + CHECK(a, EINVAL); + + instr->type = INSTR_JMP_ACTION_MISS; + instr->jmp.ip = NULL; /* Resolved later. */ + instr->jmp.action_id = a->id; + return 0; +} + +static int +instr_jmp_eq_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + char *a = tokens[2], *b = tokens[3]; + struct field *fa, *fb; + uint64_t b_val; + uint32_t a_struct_id, b_struct_id; + + CHECK(n_tokens == 4, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + fa = struct_field_parse(p, action, a, &a_struct_id); + CHECK(fa, EINVAL); + + /* JMP_EQ or JMP_EQ_S. */ + fb = struct_field_parse(p, action, b, &b_struct_id); + if (fb) { + instr->type = INSTR_JMP_EQ; + if ((a[0] == 'h' && b[0] != 'h') || + (a[0] != 'h' && b[0] == 'h')) + instr->type = INSTR_JMP_EQ_S; + instr->jmp.ip = NULL; /* Resolved later. */ + + instr->jmp.a.struct_id = (uint8_t)a_struct_id; + instr->jmp.a.n_bits = fa->n_bits; + instr->jmp.a.offset = fa->offset / 8; + instr->jmp.b.struct_id = (uint8_t)b_struct_id; + instr->jmp.b.n_bits = fb->n_bits; + instr->jmp.b.offset = fb->offset / 8; + return 0; + } + + /* JMP_EQ_I. */ + b_val = strtoull(b, &b, 0); + CHECK(!b[0], EINVAL); + + if (a[0] == 'h') + b_val = hton64(b_val) >> (64 - fa->n_bits); + + instr->type = INSTR_JMP_EQ_I; + instr->jmp.ip = NULL; /* Resolved later. */ + instr->jmp.a.struct_id = (uint8_t)a_struct_id; + instr->jmp.a.n_bits = fa->n_bits; + instr->jmp.a.offset = fa->offset / 8; + instr->jmp.b_val = b_val; + return 0; +} + +static int +instr_jmp_neq_translate(struct rte_swx_pipeline *p, + struct action *action, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data) +{ + char *a = tokens[2], *b = tokens[3]; + struct field *fa, *fb; + uint64_t b_val; + uint32_t a_struct_id, b_struct_id; + + CHECK(n_tokens == 4, EINVAL); + + strcpy(data->jmp_label, tokens[1]); + + fa = struct_field_parse(p, action, a, &a_struct_id); + CHECK(fa, EINVAL); /* JMP_NEQ or JMP_NEQ_S. */ fb = struct_field_parse(p, action, b, &b_struct_id); @@ -4846,18 +5903,18 @@ instr_jmp_neq_translate(struct rte_swx_pipeline *p, } /* JMP_NEQ_I. */ - b_val = strtoul(b, &b, 0); + b_val = strtoull(b, &b, 0); CHECK(!b[0], EINVAL); if (a[0] == 'h') - b_val = htonl(b_val); + b_val = hton64(b_val) >> (64 - fa->n_bits); instr->type = INSTR_JMP_NEQ_I; instr->jmp.ip = NULL; /* Resolved later. */ instr->jmp.a.struct_id = (uint8_t)a_struct_id; instr->jmp.a.n_bits = fa->n_bits; instr->jmp.a.offset = fa->offset / 8; - instr->jmp.b_val = (uint32_t)b_val; + instr->jmp.b_val = b_val; return 0; } @@ -4871,7 +5928,8 @@ instr_jmp_lt_translate(struct rte_swx_pipeline *p, { char *a = tokens[2], *b = tokens[3]; struct field *fa, *fb; - uint32_t a_struct_id, b_struct_id, b_val; + uint64_t b_val; + uint32_t a_struct_id, b_struct_id; CHECK(n_tokens == 4, EINVAL); @@ -4884,9 +5942,9 @@ instr_jmp_lt_translate(struct rte_swx_pipeline *p, fb = struct_field_parse(p, action, b, &b_struct_id); if (fb) { instr->type = INSTR_JMP_LT; - if (a[0] == 'h' && b[0] == 'm') + if (a[0] == 'h' && b[0] != 'h') instr->type = INSTR_JMP_LT_HM; - if (a[0] == 'm' && b[0] == 'h') + if (a[0] != 'h' && b[0] == 'h') instr->type = INSTR_JMP_LT_MH; if (a[0] == 'h' && b[0] == 'h') instr->type = INSTR_JMP_LT_HH; @@ -4902,7 +5960,7 @@ instr_jmp_lt_translate(struct rte_swx_pipeline *p, } /* JMP_LT_MI, JMP_LT_HI. */ - b_val = strtoul(b, &b, 0); + b_val = strtoull(b, &b, 0); CHECK(!b[0], EINVAL); instr->type = INSTR_JMP_LT_MI; @@ -4913,7 +5971,7 @@ instr_jmp_lt_translate(struct rte_swx_pipeline *p, instr->jmp.a.struct_id = (uint8_t)a_struct_id; instr->jmp.a.n_bits = fa->n_bits; instr->jmp.a.offset = fa->offset / 8; - instr->jmp.b_val = (uint32_t)b_val; + instr->jmp.b_val = b_val; return 0; } @@ -4927,7 +5985,8 @@ instr_jmp_gt_translate(struct rte_swx_pipeline *p, { char *a = tokens[2], *b = tokens[3]; struct field *fa, *fb; - uint32_t a_struct_id, b_struct_id, b_val; + uint64_t b_val; + uint32_t a_struct_id, b_struct_id; CHECK(n_tokens == 4, EINVAL); @@ -4940,9 +5999,9 @@ instr_jmp_gt_translate(struct rte_swx_pipeline *p, fb = struct_field_parse(p, action, b, &b_struct_id); if (fb) { instr->type = INSTR_JMP_GT; - if (a[0] == 'h' && b[0] == 'm') + if (a[0] == 'h' && b[0] != 'h') instr->type = INSTR_JMP_GT_HM; - if (a[0] == 'm' && b[0] == 'h') + if (a[0] != 'h' && b[0] == 'h') instr->type = INSTR_JMP_GT_MH; if (a[0] == 'h' && b[0] == 'h') instr->type = INSTR_JMP_GT_HH; @@ -4958,7 +6017,7 @@ instr_jmp_gt_translate(struct rte_swx_pipeline *p, } /* JMP_GT_MI, JMP_GT_HI. */ - b_val = strtoul(b, &b, 0); + b_val = strtoull(b, &b, 0); CHECK(!b[0], EINVAL); instr->type = INSTR_JMP_GT_MI; @@ -4969,7 +6028,7 @@ instr_jmp_gt_translate(struct rte_swx_pipeline *p, instr->jmp.a.struct_id = (uint8_t)a_struct_id; instr->jmp.a.n_bits = fa->n_bits; instr->jmp.a.offset = fa->offset / 8; - instr->jmp.b_val = (uint32_t)b_val; + instr->jmp.b_val = b_val; return 0; } @@ -5280,8 +6339,6 @@ instr_return_exec(struct rte_swx_pipeline *p) t->ip = t->ret; } -#define RTE_SWX_INSTRUCTION_TOKENS_MAX 16 - static int instr_translate(struct rte_swx_pipeline *p, struct action *action, @@ -5301,6 +6358,7 @@ instr_translate(struct rte_swx_pipeline *p, break; CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL); + CHECK_NAME(token, EINVAL); tokens[n_tokens] = token; n_tokens++; @@ -5453,6 +6511,38 @@ instr_translate(struct rte_swx_pipeline *p, instr, data); + if (!strcmp(tokens[tpos], "regprefetch")) + return instr_regprefetch_translate(p, + action, + &tokens[tpos], + n_tokens - tpos, + instr, + data); + + if (!strcmp(tokens[tpos], "regrd")) + return instr_regrd_translate(p, + action, + &tokens[tpos], + n_tokens - tpos, + instr, + data); + + if (!strcmp(tokens[tpos], "regwr")) + return instr_regwr_translate(p, + action, + &tokens[tpos], + n_tokens - tpos, + instr, + data); + + if (!strcmp(tokens[tpos], "regadd")) + return instr_regadd_translate(p, + action, + &tokens[tpos], + n_tokens - tpos, + instr, + data); + if (!strcmp(tokens[tpos], "table")) return instr_table_translate(p, action, @@ -5774,6 +6864,9 @@ instr_pattern_emit_many_tx_detect(struct instruction *instr, if (instr[i].type != INSTR_TX) return 0; + if (data[i].n_users) + return 0; + i++; *n_pattern_instr = i; @@ -5938,7 +7031,7 @@ instruction_config(struct rte_swx_pipeline *p, CHECK(n_instructions, EINVAL); CHECK(instructions, EINVAL); for (i = 0; i < n_instructions; i++) - CHECK(instructions[i], EINVAL); + CHECK_INSTRUCTION(instructions[i], EINVAL); /* Memory allocation. */ instr = calloc(n_instructions, sizeof(struct instruction)); @@ -6086,6 +7179,37 @@ static instr_exec_t instruction_table[] = { [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec, [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec, + [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec, + [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec, + [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec, + + [INSTR_REGRD_HRH] = instr_regrd_hrh_exec, + [INSTR_REGRD_HRM] = instr_regrd_hrm_exec, + [INSTR_REGRD_MRH] = instr_regrd_mrh_exec, + [INSTR_REGRD_MRM] = instr_regrd_mrm_exec, + [INSTR_REGRD_HRI] = instr_regrd_hri_exec, + [INSTR_REGRD_MRI] = instr_regrd_mri_exec, + + [INSTR_REGWR_RHH] = instr_regwr_rhh_exec, + [INSTR_REGWR_RHM] = instr_regwr_rhm_exec, + [INSTR_REGWR_RMH] = instr_regwr_rmh_exec, + [INSTR_REGWR_RMM] = instr_regwr_rmm_exec, + [INSTR_REGWR_RHI] = instr_regwr_rhi_exec, + [INSTR_REGWR_RMI] = instr_regwr_rmi_exec, + [INSTR_REGWR_RIH] = instr_regwr_rih_exec, + [INSTR_REGWR_RIM] = instr_regwr_rim_exec, + [INSTR_REGWR_RII] = instr_regwr_rii_exec, + + [INSTR_REGADD_RHH] = instr_regadd_rhh_exec, + [INSTR_REGADD_RHM] = instr_regadd_rhm_exec, + [INSTR_REGADD_RMH] = instr_regadd_rmh_exec, + [INSTR_REGADD_RMM] = instr_regadd_rmm_exec, + [INSTR_REGADD_RHI] = instr_regadd_rhi_exec, + [INSTR_REGADD_RMI] = instr_regadd_rmi_exec, + [INSTR_REGADD_RIH] = instr_regadd_rih_exec, + [INSTR_REGADD_RIM] = instr_regadd_rim_exec, + [INSTR_REGADD_RII] = instr_regadd_rii_exec, + [INSTR_TABLE] = instr_table_exec, [INSTR_EXTERN_OBJ] = instr_extern_obj_exec, [INSTR_EXTERN_FUNC] = instr_extern_func_exec, @@ -6442,7 +7566,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, struct action *a; uint32_t action_data_size; - CHECK(action_name, EINVAL); + CHECK_NAME(action_name, EINVAL); a = action_find(p, action_name); CHECK(a, EINVAL); @@ -6452,7 +7576,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, action_data_size_max = action_data_size; } - CHECK(params->default_action_name, EINVAL); + CHECK_NAME(params->default_action_name, EINVAL); for (i = 0; i < p->n_actions; i++) if (!strcmp(params->action_names[i], params->default_action_name)) @@ -6463,6 +7587,9 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, !params->default_action_data, EINVAL); /* Table type checks. */ + if (recommended_table_type_name) + CHECK_NAME(recommended_table_type_name, EINVAL); + if (params->n_fields) { enum rte_swx_table_match_type match_type; @@ -6795,6 +7922,132 @@ table_free(struct rte_swx_pipeline *p) } } +/* + * Register array. + */ +static struct regarray * +regarray_find(struct rte_swx_pipeline *p, const char *name) +{ + struct regarray *elem; + + TAILQ_FOREACH(elem, &p->regarrays, node) + if (!strcmp(elem->name, name)) + return elem; + + return NULL; +} + +static struct regarray * +regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id) +{ + struct regarray *elem = NULL; + + TAILQ_FOREACH(elem, &p->regarrays, node) + if (elem->id == id) + return elem; + + return NULL; +} + +int +rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p, + const char *name, + uint32_t size, + uint64_t init_val) +{ + struct regarray *r; + + CHECK(p, EINVAL); + + CHECK_NAME(name, EINVAL); + CHECK(!regarray_find(p, name), EEXIST); + + CHECK(size, EINVAL); + size = rte_align32pow2(size); + + /* Memory allocation. */ + r = calloc(1, sizeof(struct regarray)); + CHECK(r, ENOMEM); + + /* Node initialization. */ + strcpy(r->name, name); + r->init_val = init_val; + r->size = size; + r->id = p->n_regarrays; + + /* Node add to tailq. */ + TAILQ_INSERT_TAIL(&p->regarrays, r, node); + p->n_regarrays++; + + return 0; +} + +static int +regarray_build(struct rte_swx_pipeline *p) +{ + struct regarray *regarray; + + if (!p->n_regarrays) + return 0; + + p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime)); + CHECK(p->regarray_runtime, ENOMEM); + + TAILQ_FOREACH(regarray, &p->regarrays, node) { + struct regarray_runtime *r = &p->regarray_runtime[regarray->id]; + uint32_t i; + + r->regarray = env_malloc(regarray->size * sizeof(uint64_t), + RTE_CACHE_LINE_SIZE, + p->numa_node); + CHECK(r->regarray, ENOMEM); + + if (regarray->init_val) + for (i = 0; i < regarray->size; i++) + r->regarray[i] = regarray->init_val; + + r->size_mask = regarray->size - 1; + } + + return 0; +} + +static void +regarray_build_free(struct rte_swx_pipeline *p) +{ + uint32_t i; + + if (!p->regarray_runtime) + return; + + for (i = 0; i < p->n_regarrays; i++) { + struct regarray *regarray = regarray_find_by_id(p, i); + struct regarray_runtime *r = &p->regarray_runtime[i]; + + env_free(r->regarray, regarray->size * sizeof(uint64_t)); + } + + free(p->regarray_runtime); + p->regarray_runtime = NULL; +} + +static void +regarray_free(struct rte_swx_pipeline *p) +{ + regarray_build_free(p); + + for ( ; ; ) { + struct regarray *elem; + + elem = TAILQ_FIRST(&p->regarrays); + if (!elem) + break; + + TAILQ_REMOVE(&p->regarrays, elem, node); + free(elem); + } +} + /* * Pipeline. */ @@ -6823,6 +8076,7 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node) TAILQ_INIT(&pipeline->actions); TAILQ_INIT(&pipeline->table_types); TAILQ_INIT(&pipeline->tables); + TAILQ_INIT(&pipeline->regarrays); pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */ pipeline->numa_node = numa_node; @@ -6839,6 +8093,7 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p) free(p->instructions); + regarray_free(p); table_state_free(p); table_free(p); action_free(p); @@ -6923,10 +8178,15 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p) if (status) goto error; + status = regarray_build(p); + if (status) + goto error; + p->build_done = 1; return 0; error: + regarray_build_free(p); table_state_build_free(p); table_build_free(p); action_build_free(p); @@ -6987,6 +8247,7 @@ rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p, pipeline->n_ports_out = p->n_ports_out; pipeline->n_actions = n_actions; pipeline->n_tables = n_tables; + pipeline->n_regarrays = p->n_regarrays; return 0; } @@ -7194,3 +8455,64 @@ rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p, port->type->ops.stats_read(port->obj, stats); return 0; } + +int +rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p, + uint32_t regarray_id, + struct rte_swx_ctl_regarray_info *regarray) +{ + struct regarray *r; + + if (!p || !regarray) + return -EINVAL; + + r = regarray_find_by_id(p, regarray_id); + if (!r) + return -EINVAL; + + strcpy(regarray->name, r->name); + regarray->size = r->size; + return 0; +} + +int +rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p, + const char *regarray_name, + uint32_t regarray_index, + uint64_t *value) +{ + struct regarray *regarray; + struct regarray_runtime *r; + + if (!p || !regarray_name || !value) + return -EINVAL; + + regarray = regarray_find(p, regarray_name); + if (!regarray || (regarray_index >= regarray->size)) + return -EINVAL; + + r = &p->regarray_runtime[regarray->id]; + *value = r->regarray[regarray_index]; + return 0; +} + +int +rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p, + const char *regarray_name, + uint32_t regarray_index, + uint64_t value) +{ + struct regarray *regarray; + struct regarray_runtime *r; + + if (!p || !regarray_name) + return -EINVAL; + + regarray = regarray_find(p, regarray_name); + if (!regarray || (regarray_index >= regarray->size)) + return -EINVAL; + + r = &p->regarray_runtime[regarray->id]; + r->regarray[regarray_index] = value; + return 0; +}