def regroup_attrs(hlir): """Groups hlir objects by their types into hlir attributes.""" hlir.groups = P4Node({'node_type': 'groups'}) groups = [ ('control_types', 'Type_Control'), ('controls', 'P4Control'), ('decl_consts', 'Declaration_Constant'), ('decl_instances', 'Declaration_Instance'), ('decl_matchkinds', 'Declaration_MatchKind'), ('enums', 'Type_Enum'), ('errors', 'Type_Error'), ('externs', 'Type_Extern'), ('headers', 'Type_Header'), ('methods', 'Method'), ('packages', 'Type_Package'), ('parsers', 'P4Parser'), # note: structs are separated using attrs_regroup_structs() # ('structs', 'Type_Struct'), ('typedefs', 'Type_Typedef'), ('type_parsers', 'Type_Parser'), ] for new_group_name, node_type_name in groups: make_node_group(hlir, new_group_name, hlir.objects[node_type_name], hlir.objects)
def attrs_regroup_path_expressions(hlir): """Makes hlir attributes for distinct kinds of structs.""" pes = hlir.all_nodes.by_type('PathExpression') hlir.groups.pathexprs = P4Node({'node_type': 'grouped'}) hlir.groups.pathexprs.under_mcall = remove_nodes( pes.filter(lambda m: m.parent().node_type == 'MethodCallExpression'), pes) hlir.groups.pathexprs.under_assign = remove_nodes( pes.filter(lambda m: m.parent().node_type == 'AssignmentStatement'), pes) hlir.groups.pathexprs.under_keyelement = remove_nodes( pes.filter(lambda m: m.parent().node_type == 'KeyElement'), pes) hlir.groups.pathexprs.extern_under_member = remove_nodes( pes.filter(lambda m: m.parent().node_type == 'Member' and m.type. node_type == 'Type_Extern'), pes) hlir.groups.pathexprs.under_header = remove_nodes( pes.filter(lambda m: m.parent().node_type == 'Member' and m.parent(). type.node_type == 'Type_Header'), pes) hlir.groups.pathexprs.under_unknown = remove_nodes( pes.filter(lambda m: m.parent().node_type == 'Member' and m.parent(). type.node_type == 'Type_Unknown'), pes) hlir.groups.pathexprs.action = remove_nodes( pes.filter('type.node_type', 'Type_Action'), pes) hlir.groups.pathexprs.io = remove_nodes( pes.filter('type.node_type', 'Type_Extern'), pes) hlir.groups.pathexprs.header = remove_nodes( pes.filter('type.node_type', 'Type_Header'), pes) hlir.groups.pathexprs.struct = remove_nodes( pes.filter('type.node_type', 'Type_Struct'), pes) hlir.groups.pathexprs.state = remove_nodes( pes.filter('type.node_type', 'Type_State'), pes) hlir.groups.pathexprs.method = remove_nodes( pes.filter('type.node_type', 'Type_Method'), pes) hlir.groups.pathexprs.matchkind = remove_nodes( pes.filter('type.node_type', 'Type_MatchKind'), pes) hlir.groups.pathexprs.table = remove_nodes( pes.filter('type.node_type', 'Type_Table'), pes) hlir.groups.pathexprs.boolean = remove_nodes( pes.filter('type.node_type', 'Type_Boolean'), pes) hlir.groups.pathexprs.specialized_canonical = remove_nodes( pes.filter('type.node_type', 'Type_SpecializedCanonical'), pes) hlir.groups.pathexprs.package = remove_nodes( pes.filter('type.node_type', 'Type_Package'), pes) hlir.groups.pathexprs.bits = remove_nodes( pes.filter('type.node_type', 'Type_Bits'), pes) hlir.groups.pathexprs.varbits = remove_nodes( pes.filter('type.node_type', 'Type_Varbits'), pes) hlir.groups.pathexprs.arithmetic = remove_nodes( pes.filter(lambda m: (op := m.parent().node_type) in simple_binary_ops or op in complex_binary_ops), pes) check_no_leftovers(hlir.groups.pathexprs, pes, "path expression")
def attrs_extern(hlir): infos = model_specific_infos[hlir.news.model] for extern in hlir.all_nodes.by_type('Type_Extern'): if 'smem_type' in extern: continue extern.constructors = P4Node( [ctor for ctor in extern.methods if ctor.name == extern.name]) extern.interface_methods = P4Node( [ctor for ctor in extern.methods if ctor.name != extern.name]) extern.is_repr_model_specific = extern.name in infos['extern_reprs'] if extern.is_repr_model_specific: extern.repr = infos['extern_reprs'][extern.name] extern.is_unused = False else: extern.repr = get_extern_repr(extern) extern.is_unused = is_extern_unused(extern, extern.repr)
def walk_json(node, fun, nodes, skip_elems=['Node_Type', 'Node_ID', 'Source_Info'], node_parent_chain=[]): rets = [] if type(node) is dict or type(node) is list: node_id = node['Node_ID'] if node_id not in nodes: nodes[node_id] = P4Node({ 'Node_ID': node_id, 'node_type': '(incomplete_json_data)', 'node_parents': [node_parent_chain], }) if 'vec' in node.keys(): elems = [(None, elem) for elem in node['vec']] else: elems = [(key, node[key]) for key in node.keys() if key not in skip_elems] rets = [(key, walk_json(elem, fun, nodes, skip_elems, node_parent_chain + [nodes[node_id]])) for (key, elem) in elems if elem != {}] return fun(node, rets, nodes, skip_elems, node_parent_chain)
"user_meta_var": "user_meta", "meta_types": [ "psa_ingress_parser_input_metadata_t", "psa_egress_parser_input_metadata_t", "psa_ingress_input_metadata_t", "psa_ingress_output_metadata_t", "psa_egress_input_metadata_t", "psa_egress_deparser_input_metadata_t", "psa_egress_output_metadata_t", ], "extern_reprs": { 'InternetChecksum': P4Node({ 'node_type': 'Type_Bits', 'isSigned': False, 'size': 16, 'padded_size': 16 }), 'Digest': P4Node({ 'node_type': 'Type_Bits', 'isSigned': False, 'size': 32, 'padded_size': 32 }), }, # psa.p4 does not mark deparsers with @deparser, hence this hack "deparsers": ["IngressDeparser", "EgressDeparser"], }, }
def attrs_regroup_members(hlir): mes = hlir.all_nodes.by_type('Member') hlir.groups.member_exprs = P4Node({'node_type': 'grouped'}) mem_exprs = hlir.groups.member_exprs mem_methods = mes.filter('type.node_type', 'Type_Method') mem_path_members = mem_methods.filter(lambda m: 'member' in m) mem_path_methods = mem_methods.filter(lambda m: 'path' in m.expr) mem_path_pathexpressions = mes.filter('expr.node_type', 'PathExpression') hlir.groups.member_exprs.enums = remove_nodes( mes.filter('type.node_type', 'Type_Enum'), mes) hlir.groups.member_exprs.booleans = remove_nodes( mes.filter('type.node_type', 'Type_Boolean'), mes) hlir.groups.member_exprs.errors = remove_nodes( mes.filter('type.node_type', 'Type_Error'), mes) hlir.groups.member_exprs.action_enums = remove_nodes( mes.filter('type.node_type', 'Type_ActionEnum'), mes) hlir.groups.member_exprs.header_stacks = remove_nodes( mes.filter('type.node_type', 'Type_Stack'), mes) hlir.groups.member_exprs.indexed_header_stack = remove_nodes( mes.filter('expr.node_type', 'ArrayIndex'), mes) hlir.groups.member_exprs.specialized_canonical = remove_nodes( mes.filter('expr.type.node_type', 'Type_SpecializedCanonical'), mes) hlir.groups.member_exprs.tables = remove_nodes( mem_path_methods.filter('expr.type.node_type', 'Type_Table'), mes) hlir.groups.member_exprs.externs = remove_nodes( mem_path_methods.filter('expr.type.node_type', 'Type_Extern'), mes) hlir.groups.member_exprs.headers = remove_nodes( mem_path_pathexpressions.filter('type.node_type', 'Type_Header'), mes) hlir.groups.member_exprs.structs = remove_nodes( mem_path_pathexpressions.filter('type.node_type', 'Type_Struct'), mes) hlir.groups.member_exprs.bits = remove_nodes( mem_path_pathexpressions.filter('type.node_type', 'Type_Bits'), mes) hlir.groups.member_exprs.varbits = remove_nodes( mem_path_pathexpressions.filter('type.node_type', 'Type_Varbits'), mes) hlir.groups.member_exprs.members = remove_nodes( mem_methods.filter(lambda m: 'member' in m.expr), mes) hlir.groups.member_exprs.exprs = remove_nodes( mes.filter(lambda m: 'expr' in m.expr), mes) hlir.groups.member_exprs.under_mcall = remove_nodes( mes.filter(lambda m: m.parent().node_type == 'MethodCallExpression'), mes) hlir.groups.member_exprs.keyelement = remove_nodes( mes.filter(lambda m: m.parent().node_type == 'KeyElement'), mes) check_no_leftovers(hlir.groups.member_exprs, mes, "member expression") hlir.object_groups = P4Node([ hlir.control_types, hlir.controls, hlir.decl_instances, hlir.decl_matchkinds, hlir.enums, hlir.errors, hlir.externs, hlir.headers, hlir.methods, hlir.packages, hlir.parsers, hlir.typedefs, hlir.type_parsers, hlir.news.data, hlir.news.meta, ])
def walk_json_from_top(node, fun=p4node_creator): nodes = {} hlir = walk_json(node, fun, nodes) hlir.all_nodes = P4Node({'node_type': 'all_nodes'}, [nodes[idx] for idx in nodes.keys()]) return hlir