def make_allmetas_node(hlir): ctl_local_vars = hlir.controls.flatmap('controlLocals').filter( 'node_type', 'Declaration_Variable') clv_to_struct = {} fldinfos = unique_everseen( (fld.name, fld.urtype) for fld in hlir.news.meta.flatmap('fields')) check_meta_fields(fldinfos) fldname_to_hdrfield = { fld.name: (hdr, fld, fld) for hdr in hlir.news.meta for fld in hdr.fields } allmeta_flds = list(make_metaflds(fldname_to_hdrfield)) + list( make_metaflds(clv_to_struct)) hlir.allmetas = P4Node({'node_type': 'StructField'}) hlir.allmetas.name = 'all_metadatas' hlir.allmetas.type = P4Node({'node_type': 'Type_Name'}) hlir.allmetas.type.path = P4Node({'node_type': 'Path'}) hlir.allmetas.type.path.absolute = True hlir.allmetas.type.type_ref = P4Node({'node_type': 'Type_Header'}) hlir.allmetas.type.type_ref.name = 'all_metadatas_t' hlir.allmetas.type.type_ref.fields = P4Node(allmeta_flds)
def attrs_regroup_structs(hlir): structs = hlir.objects['Type_Struct'] act_param_types = hlir.all_nodes.by_type('P4Control').flatmap( 'controlLocals').filter( 'node_type', 'P4Action').flatmap('parameters.parameters').filter( 'type.node_type', 'Type_Name').map('type.type_ref') metas_by_varname = hlir.all_nodes.by_type('PathExpression').filter( 'type.node_type', 'Type_Struct').filter('path.name', hlir.news.user_meta_var).map('type.name') param_metas = hlir.all_nodes.by_type('Parameter').filter( 'name', hlir.news.user_meta_var).map('urtype').filter( 'node_type', 'Type_Struct').map('name') meta_type_names = unique_everseen(hlir.news.meta_types + metas_by_varname + param_metas) hlir.news.meta = remove_nodes( structs.filter(lambda s: s.name in meta_type_names), hlir.objects) hlir.news.data = remove_nodes(hlir.objects['Type_Struct'], hlir.objects) assert (remaining := len(hlir.objects['Type_Struct']) ) == 0, f'{remaining} structs are not identified'
def attrs_hdr_metadata_insts(hlir): """Metadata instances and header instances""" def is_hdr(fld): return fld.urtype.node_type == 'Type_Header' def is_named_hdr(fld): return fld.urtype.node_type == 'Type_Name' and ( res := resolve_type_name( hlir, fld.urtype)) is not None and res.node_type == 'Type_Header' for stk in hlir.header_stacks: # note: the 'size' attribute in T4P4S refers to the bitsize of the header # this renaming avoids collision stk.type.stk_size = stk.type.size stk.type.del_attr('size') stack_infos = hlir.header_stacks.map( lambda stack: (stack, stack.name, stack.urtype.stk_size.value, stack. urtype.elementType)) hdr_names = unique_everseen( hlir.groups.pathexprs.under_header.flatmap('type.fields').map('name')) hdrs = hlir.news.data.flatmap('fields').filter( lambda fld: is_hdr(fld) or is_named_hdr(fld) and fld.name in hdr_names) hdr_stacks = list( create_hdr(hlir, f'{name}_{idx}', type, idx=idx, stack=stack) for (stack, name, stk_size, type) in stack_infos for idx in range(stk_size)) local_hdrs = hlir.locals \ .filter('node_type', 'Declaration_Variable') \ .filter('type.node_type', 'Type_Name') \ .filter(lambda hdr: hlir.headers.get(hdr.urtype.path.name) is not None) \ .map(lambda hdr: create_hdr(hlir, hdr.name, hdr.type)) local_hdr_node_ids = set(local_hdrs.map('Node_ID')) insts = hdrs + hdr_stacks + local_hdrs for hdrinst in insts: hdrinst.is_local = hdrinst.Node_ID in local_hdr_node_ids if 'path' in hdrinst.urtype and not hdrinst.urtype.path.absolute: hdrinst.type.type_ref = hlir.headers.get(hdrinst.urtype.path.name) is_stack = 'stack' in hdrinst and hdrinst.stack is not None # TODO find an even more reliable way to see if the header is skipped (extracted as _) hdrinst.is_skipped = not is_stack and hdrinst.is_local and 'annotations' not in hdrinst and hdrinst.name.startswith( 'arg') set_header_meta_preparsed(hlir.allmetas, True) for hdr in hlir.headers: set_header_meta_preparsed(hdr, False) hlir.headers.append(hlir.allmetas.urtype) hlir.header_instances = P4Node(insts + [hlir.allmetas])
def resolve_metadata_hdr(hlir, typename_node, fld): results = hlir.news.meta.flatmap('fields').filter('name', fld.name) if len(results) == 1: return results[0] results = results.filterfalse('type.path.absolute') typenames = unique_everseen(results.map('urtype.name')) if len(typenames) > 1: hdrname = typename_node.parents.filter( lambda n: n.node_type == 'Type_Struct')[0].name typenames = ', '.join(typenames) assert False, f'Metadata field {hdrname}.{fld.name} has conflicting types ({typenames})' return results[0]
from compiler_log_warnings_errors import addError, addWarning from compiler_common import types, generate_var_name, get_hdrfld_name, unique_everseen #[ #include "dataplane_impl.h" #[ #include "dataplane.h" #[ #include "dataplane_stages.h" # TODO make this an import from hardware_indep #[ #include "dpdk_smem.h" table_infos = [(table, table.short_name + ("/keyless" if table.key_length_bits == 0 else "") + ("/hidden" if table.is_hidden else "")) for table in hlir.tables] ################################################################################ # Table application for type in unique_everseen([comp['type'] for table in hlir.tables for smem in table.direct_meters + table.direct_counters for comp in smem.components]): #[ void apply_direct_smem_$type(register_uint32_t* smem, uint32_t value, char* table_name, char* smem_type_name, char* smem_name) { #[ debug(" : applying apply_direct_smem_$type(register_uint32_t (*smem)[1], uint32_t value, char* table_name, char* smem_type_name, char* smem_name)"); #[ } ################################################################################ #{ void reset_vw_fields(SHORT_STDPARAMS) { for hdr in hlir.header_instances.filter('urtype.is_metadata', False): for fld in hdr.urtype.fields: if fld.is_vw: #[ pd->headers[HDR(${hdr.name})].var_width_field_bitwidth = 0; #} } #{ void reset_headers(SHORT_STDPARAMS) { for hdr in hlir.header_instances.filter('urtype.is_metadata', False):
#[ #include "gen_include.h" #[ #include "util_packet.h" # Note: this is for Digest_t #[ #include "ctrl_plane_backend.h" # TODO this should not be here in the indep section #[ #include "dpdk_smem.h" #[ #define FIELD(name, length) uint8_t name[(length + 7) / 8]; #{ typedef enum { for table in hlir.tables: for action in unique_everseen(table.actions): #[ action_${action.action_object.name}, if len(table.actions) == 0: #[ action_, #} } actions_t; for ctl in hlir.controls: for act in ctl.actions: #{ typedef struct { for param in act.parameters.parameters: paramtype = param.urtype #[ ${format_type(param.urtype, varname = param.name)}; if len(act.parameters.parameters) == 0: #[ FIELD(DUMMY_FIELD, 0); #} } action_${act.name}_params_t;
#{ void ctrl_setdefault(struct p4_ctrl_msg* ctrl_m) { for table in hlir.tables: #{ if (strcmp("${table.canonical_name}", ctrl_m->table_name) == 0) { #[ ${table.name}_set_default_table_action(ctrl_m); #[ return; #} } #[ debug(" $$[warning]{}{!!!! Table set default}: $$[warning]{}{unknown table name} $$[table]{}{%s}\n", ctrl_m->table_name); #{ #ifdef T4P4S_DEBUG #[ debug_show_possible_tables(); #} #endif #} } hack_i = 0 for smem in unique_everseen([smem for table, smem in hlir.all_counters]): for target in smem.smem_for: if not smem.smem_for[target]: continue hack_i += 1 if hack_i%2==1: for c in smem.components: cname = c['name'] if smem.smem_type not in ["register", "direct_counter", "direct_meter"]: #[ uint32_t ctrl_${cname}[${smem.amount}]; #{ uint32_t* read_counter_value_by_name(char* counter_name, int* size, bool is_bytes){ #[ int i; hack_i = 0 for smem in unique_everseen([smem for table, smem in hlir.all_counters]): for target in smem.smem_for:
#[ #[ #pragma once #[ #include "common.h" #[ #include "aliases.h" #[ #include "dpdk_smem.h" #[ #include "gen_include.h" #{ typedef struct global_state_s { for table, smem in hlir.all_meters + hlir.all_counters: if smem.smem_type not in ["direct_counter", "direct_meter"]: continue #= gen_make_smem_code(smem, table) for smem in unique_everseen([smem for table, smem in hlir.all_meters + hlir.all_counters if smem.smem_type not in ["direct_counter", "direct_meter"]]): #= gen_make_smem_code(smem) for smem in hlir.registers: #= gen_make_smem_code(smem) all_locals = unique_everseen([(param.name, format_type(param.type)) for table in hlir.tables for local in table.control.controlLocals["P4Action"] for param in local.parameters.parameters]) all_locals_dict = dict(all_locals) if len(all_locals) != len(all_locals_dict): names = [name for name, _type in all_locals] dups = unique_everseen([name for name in names if names.count(name) > 1]) addError("Collecting counters, meters, registers and controls' local variables", "The following names are used with different types, which is currently unsupported: {}".format(", ".join(dups))) for locname, loctype in all_locals: #[ $loctype $locname;
tname = hexpr.urtype.name name = hexpr._expr.path.name if hexpr.type.name in hlir.news.meta_types: hexpr.hdr_ref = hlir.allmetas elif (found := hlir.news.data.get(tname)): hexpr.hdr_ref = found elif (found := hlir.news.meta.get(tname)): hexpr.hdr_ref = hlir.allmetas elif (found := hexpr.parents.filter( 'node_type', ('P4Parser', 'P4Control')).flatmap('locals').get(name)): hexpr.hdr_ref = found elif len(founds := [ hdrt for hdrt in unique_everseen( hlir.header_instances.map('urtype').filter( 'name', hexpr.type.name)) ]) == 1: hexpr.hdr_ref = founds[0] hexpr.type.type_ref = founds[0].urtype for pe in hlir.groups.pathexprs.table: pe.table_ref = hlir.map('controls').flatmap('locals').get(pe.path.name) for mcexpr in hlir.groups.pathexprs.under_mcall: mname = mcexpr.path.name if (found := hlir.methods.get(mname)): mcexpr.action_ref = found else: mcexpr.action_ref = hlir.controls.flatmap('locals').get(mname)