예제 #1
0
 def __copy__(self):
     cls = self.__class__
     result = cls.__new__(cls)
     result.__dict__.update(self.__dict__)
     result.type_params = copy.copy(self.type_params)
     result.params = []
     for param in self.params:
         result.params.append(copy.copy(param))
     return result
예제 #2
0
    def eval(self, p4_state):
        val = p4_state.resolve_expr(self.val)
        if self.instance_type is None:
            # no type defined, return just the value
            return val
        else:
            instance = gen_instance("None", self.instance_type)

        if isinstance(val, P4ComplexInstance):
            # copy the reference if we initialize with another complex type
            return copy.copy(val)
        if isinstance(instance, P4ComplexInstance):
            if isinstance(val, dict):
                instance.setValid()
                for name, val in val.items():
                    val_expr = p4_state.resolve_expr(val)
                    instance.set_or_add_var(name, val_expr)
            elif isinstance(val, list):
                instance.set_list(val)
            else:
                raise RuntimeError(
                    f"P4StructInitializer members {val} not supported!")
            return instance
        else:
            # cast the value we assign to the instance we create
            # TODO: I do not like this, there must be a better way to do this
            if isinstance(val, int) and isinstance(
                    instance, (z3.BitVecSortRef, z3.BitVecRef)):
                val = z3_cast(val, instance.sort())
            return val
예제 #3
0
 def init_type_params(self, ctx, *args, **kwargs):
     # TODO Figure out what to actually do here
     init_ctrl = copy.copy(self)
     # the type params sometimes include the return type also
     # it is typically the first value, but is bound somewhere else
     for idx, t_param in enumerate(init_ctrl.type_params):
         init_ctrl.type_ctx[t_param] = args[idx]
     return init_ctrl
예제 #4
0
 def __copy__(self):
     cls = self.__class__
     result = cls.__new__(cls)
     result.__dict__.update(self.__dict__)
     result.params = copy.deepcopy(result.params)
     for idx, val in enumerate(result.params):
         result.params[idx] = copy.copy(val)
     return result
예제 #5
0
 def eval(self, p4_state):
     log.debug("Assigning %s to %s ", self.rval, self.lval)
     rval_expr = p4_state.resolve_expr(self.rval)
     # in assignments all complex types values are copied
     if isinstance(rval_expr, StructInstance):
         rval_expr = copy.copy(rval_expr)
     if isinstance(rval_expr, int):
         lval = p4_state.resolve_expr(self.lval)
         rval_expr = z3_cast(rval_expr, lval.sort())
     p4_state.set_or_add_var(self.lval, rval_expr)
예제 #6
0
 def initialize(self, context, *args, **kwargs):
     ctrl_copy = copy.copy(self)
     ctrl_copy.merged_consts = merge_parameters(ctrl_copy.const_params,
                                                *args, **kwargs)
     # also bind types, because for reasons you can bind types everywhere...
     for idx, const_param in enumerate(ctrl_copy.const_params):
         # this means the type is generic
         p4_type = resolve_type(context, const_param.p4_type)
         if p4_type is None:
             # grab the type of the input arguments
             ctrl_copy.type_context[const_param.p4_type] = args[idx].sort()
     return ctrl_copy
예제 #7
0
    def copy_in(self, ctx, merged_args):
        param_buffer = OrderedDict()
        var_buffer = OrderedDict()
        for param_name, arg in merged_args.items():
            # We need to resolve array indices appropriately
            arg_expr, _ = resolve_index(ctx, arg.p4_val)
            try:
                param_val = ctx.resolve_reference(param_name)
                var_buffer[param_name] = (arg.mode, arg_expr, param_val)
            except RuntimeError:
                # if the variable name does not exist, set the value to None
                var_buffer[param_name] = (arg.mode, arg_expr, None)
            # Sometimes expressions are passed, resolve those first
            arg_expr = ctx.resolve_expr(arg_expr)
            # it can happen that we receive a list
            # infer the type, generate, and set
            try:
                p4_type = ctx.resolve_type(arg.p4_type)
            except KeyError:
                # this is a generic type, we need to bind for this scope
                # FIXME: Clean this up
                p4_type = arg_expr.sort()
                ctx.add_type(arg.p4_type, p4_type)
            if isinstance(arg_expr, list):
                # if the type is undefined, do nothing
                if isinstance(p4_type, P4ComplexType):
                    arg_instance = ctx.gen_instance(UNDEF_LABEL, p4_type)
                    arg_instance.set_list(arg_expr)
                    arg_expr = arg_instance
            # it is possible to pass an int as value, we need to cast it
            elif isinstance(arg_expr, int):
                arg_expr = z3_cast(arg_expr, p4_type)
            # need to work with an independent copy
            # the purpose is to handle indirect assignments in an action
            if arg.mode in ("in", "inout") and isinstance(
                    arg_expr, StructInstance):
                arg_expr = copy.copy(arg_expr)
            if arg.mode == "out":
                # outs are left-values so the arg must be a string
                # infer the type value at runtime, param does not work yet
                # outs reset the input
                # In the case that the instance is a complex type make sure
                # to propagate the variable through all its members
                log.debug("Resetting %s to %s", arg_expr, param_name)
                arg_expr = ctx.gen_instance(UNDEF_LABEL, p4_type)

            log.debug("Copy-in: %s to %s", arg_expr, param_name)
            # buffer the value, do NOT set it yet
            param_buffer[param_name] = arg_expr
        return param_buffer, var_buffer
예제 #8
0
 def bind_to_ctrl_type(self, ctx, ctrl_type):
     # TODO Figure out what to actually do here
     # FIXME: A hack to deal with lack of input params
     if len(ctrl_type.params) < len(self.type_params):
         return self
     init_ctrl = copy.copy(self)
     # the type params sometimes include the return type also
     # it is typically the first value, but is bound somewhere else
     for idx, t_param in enumerate(init_ctrl.type_params):
         sub_type = ctx.resolve_type(ctrl_type.params[idx].p4_type)
         init_ctrl.type_ctx[t_param] = sub_type
         for param_idx, param in enumerate(init_ctrl.params):
             if isinstance(param.p4_type, str) and param.p4_type == t_param:
                 init_ctrl.params[param_idx] = ctrl_type.params[idx]
     return init_ctrl
예제 #9
0
 def eval(self, ctx):
     # An assignment, written with the = sign, first evaluates its left
     # sub-expression to an l-value, then evaluates its right sub-expression
     # to a value, and finally copies the value into the l-value. Derived
     # types (e.g. structs) are copied recursively, and all components of
     # headers are copied, including “validity” bits. Assignment is not
     # defined for extern values.
     log.debug("Assigning %s to %s ", self.rval, self.lval)
     lval, _ = resolve_index(ctx, self.lval)
     rval_expr = ctx.resolve_expr(self.rval)
     # in assignments all complex types values are copied
     if isinstance(rval_expr, StructInstance):
         rval_expr = copy.copy(rval_expr)
     if isinstance(rval_expr, int):
         rval_expr = z3_cast(rval_expr, ctx.resolve_expr(self.lval).sort())
     ctx.set_or_add_var(lval, rval_expr)
예제 #10
0
 def initialize(self, *args, **kwargs):
     # TODO Figure out what to actually do here
     init_method = copy.copy(self)
     # deepcopy is important to ensure independent type inference
     # the type params sometimes include the return type also
     # it is typically the first value, but is bound somewhere else
     if len(args) < len(init_method.type_params):
         type_list = init_method.type_params[1:]
     else:
         type_list = init_method.type_params
     for idx, t_param in enumerate(type_list):
         if init_method.return_type == t_param:
             init_method.return_type = args[idx]
         for method_param in init_method.params:
             if method_param.p4_type == t_param:
                 method_param.p4_type = args[idx]
     return init_method
예제 #11
0
    def eval(self, p4_state):
        log.debug("Assigning %s to %s ", self.rval, self.lval)
        rval_expr = p4_state.resolve_expr(self.rval)
        # in assignments all complex types values are copied
        if isinstance(rval_expr, P4ComplexInstance):
            rval_expr = copy.copy(rval_expr)
        # make sure the assignment is aligned appropriately
        # this can happen because we also evaluate before the
        # BindTypeVariables pass
        # we can only align if tmp_val is a bitvector
        # example test: instance_overwrite.p4
        lval = p4_state.resolve_expr(self.lval)
        if isinstance(rval_expr, int) and isinstance(
                lval, (z3.BitVecSortRef, z3.BitVecRef)):
            rval_expr = z3_cast(rval_expr, lval.sort())
        p4_state.set_or_add_var(self.lval, rval_expr)

        p4z3_expr = p4_state.pop_next_expr()
        return p4z3_expr.eval(p4_state)
예제 #12
0
 def set_context(self, p4_state, merged_args, ref_criteria):
     param_buffer = OrderedDict()
     for param_name, arg in merged_args.items():
         # Sometimes expressions are passed, resolve those first
         arg_expr = p4_state.resolve_expr(arg.p4_val)
         # for now use the param name, not the arg_name constructed here
         # FIXME: there are some passes that rename causing issues
         arg_name = f"{self.name}_{param_name}"
         # it can happen that we receive a list
         # infer the type, generate, and set
         if isinstance(arg_expr, list):
             # if the type is undefined, do nothing
             if isinstance(arg.p4_type, P4ComplexType):
                 arg_instance = gen_instance(arg_name, arg.p4_type)
                 arg_instance.set_list(arg_expr)
                 arg_expr = arg_instance
         if arg.is_ref == "inout":
             if isinstance(arg_expr, P4ComplexInstance):
                 arg_expr = copy.copy(arg_expr)
         if arg.is_ref == "out":
             # outs are left-values so the arg must be a string
             # infer the type value at runtime, param does not work yet
             # outs reset the input
             # In the case that the instance is a complex type make sure
             # to propagate the variable through all its members
             log.debug("Resetting %s to %s", arg_expr, param_name)
             if isinstance(arg_expr, P4ComplexInstance):
                 arg_expr = arg_expr.p4z3_type.instantiate(param_name)
                 # FIXME: This should not be needed
                 arg_expr.deactivate()
             else:
                 arg_expr = z3.Const(f"undefined", arg_expr.sort())
         log.debug("Copy-in: %s to %s", arg_expr, param_name)
         # it is possible to pass an int as value, we need to cast it
         if isinstance(arg_expr, int) and isinstance(
                 arg.p4_type, (z3.BitVecSortRef, z3.BitVecRef)):
             arg_expr = z3_cast(arg_expr, arg.p4_type)
         # buffer the value, do NOT set it yet
         param_buffer[param_name] = arg_expr
     # now we can set the arguments without influencing subsequent variables
     for param_name, param_val in param_buffer.items():
         p4_state.set_or_add_var(param_name, param_val)
예제 #13
0
    def copy_in(self, p4_state, merged_args):
        param_buffer = OrderedDict()
        for param_name, arg in merged_args.items():
            # Sometimes expressions are passed, resolve those first
            arg_expr = p4_state.resolve_expr(arg.p4_val)
            # for now use the param name, not the arg_name constructed here
            # FIXME: there are some passes that rename causing issues
            arg_name = "undefined"  # f"{self.name}_{param_name}"
            # it can happen that we receive a list
            # infer the type, generate, and set
            p4_type = resolve_type(p4_state, arg.p4_type)
            if isinstance(arg_expr, list):
                # if the type is undefined, do nothing
                if isinstance(p4_type, P4ComplexType):
                    arg_instance = gen_instance(p4_state, arg_name, p4_type)
                    arg_instance.set_list(arg_expr)
                    arg_expr = arg_instance
            # it is possible to pass an int as value, we need to cast it
            elif isinstance(arg_expr, int):
                arg_expr = z3_cast(arg_expr, p4_type)
            # need to work with an independent copy
            # the purpose is to handle indirect assignments in an action
            if arg.mode in ("in", "inout") and isinstance(
                    arg_expr, StructInstance):
                arg_expr = copy.copy(arg_expr)
            if arg.mode == "out":
                # outs are left-values so the arg must be a string
                # infer the type value at runtime, param does not work yet
                # outs reset the input
                # In the case that the instance is a complex type make sure
                # to propagate the variable through all its members
                log.debug("Resetting %s to %s", arg_expr, param_name)
                arg_expr = gen_instance(p4_state, arg_name, p4_type)

            log.debug("Copy-in: %s to %s", arg_expr, param_name)
            # buffer the value, do NOT set it yet
            param_buffer[param_name] = arg_expr
        return param_buffer
예제 #14
0
 def init_type_params(self, ctx, *args, **kwargs):
     init_method = copy.copy(self)
     for idx, t_param in enumerate(init_method.type_params):
         arg = ctx.resolve_type(args[idx])
         init_method.type_ctx[t_param] = arg
     return init_method
예제 #15
0
 def init_type_params(self, context, *args, **kwargs):
     init_method = copy.copy(self)
     for idx, t_param in enumerate(init_method.type_params):
         arg = resolve_type(context, args[idx])
         init_method.type_context[t_param] = arg
     return init_method
예제 #16
0
 def init_type_params(self, _ctx, *args, **kwargs):
     init_package = copy.copy(self)
     for idx, t_param in enumerate(init_package.type_params):
         init_package.type_ctx[t_param] = args[idx]
     return init_package