New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
State and repeated invocations #926
Comments
Local variables should behave exactly as in functions. The only way to preserve the value is for them to be uninitialized on the second entry. This is undefined behavior. If the spec is not clear about this we have a bug. |
It is perfectly legal to call the same instance twice. |
What if we replace the local variable with a register of size 1? That is, the body of register<bit<8>>(1) r;
apply {
bit<8> x;
r.read(x,0);
r.write(0,x+1);
} |
constructor invocation = state allocation. |
There's a section on the evaluation of P4 programs: https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-p4-abstract-mach |
Indeed. We understand this, and Petr4 does the right thing. It does seem to be slightly confusing that local variables declared in a control do not persist across invocations, but other stateful elements do. One could imagine adding a restriction (though this would not be backward compatible) to require all local variables to be declared in the |
As I said, for you to take advantage of the variable persistence they need to have a path of execution in which the variables are read before they are written (so they must be uninitialized in the first execution). You could conceive a legal program that carries state between control invocations to make this safe. |
So, the initialization of local variables happens on each invocation. But the uninitialized variables are persistent, right? If I write
in @hackedy's example, the result will be 3? |
My understand of the P4_16 language spec is that all local variables (not externs, but variables) that are uninitialized, begin every execution of the enclosing scope with an unspecified initial value, that might depend upon the target, and the target is free to initialize it with the value that you least wish it had, as far as your program's safety/correctness is concerned. Your example program could assign any unspecified value to h.f.val during the copy-out of the second call to c_inst.apply(). |
Let's say that the meaning of this program is undefined. Your interpretation is possible, but not the only one. |
Yes, @jafingerhut is right. |
I see. The spec says
It is a bit confusing the scope of an invocation of a control block include the whole control declaration or only the apply block. |
Whether it is the entire control declaration, or only the apply block, calling apply() on a control two times is exiting the entire scope of the entire control, including its apply block, but also everything else defined within the control. |
Except for any stateful objects, including externs and other control instances, which were instantiated within the control. That instantiation happens once, I think. |
Note: If you want some value preserved from one apply() call to an instance of a control to the next, you can make it an |
Agreed, instantiation of extern objects and tables happens once. They are explicitly defined by the language to be objects that contain their own state, though, even from processing one packet to the next. |
Does anyone in this discussion want to create a PR to make the spec crisper? |
I would be happy to write a PR that might help reduce confusion, if I knew the source of the confusion. I might be too close to the spec's details and the way things already are to see it clearly. Is the basic idea that it is currently confusing that local variables within a parser or control are either: (a) if they have no initialization expression, e.g. they look something like (b) if they have an initialization expression, e.g. they look something like If statements like those would clear things up for some readers, where in the spec would such statements best go? |
The confusion comes perhaps from the fact that instantiations that happen outside the apply block of a control preserve state across invocations, while variables do not. One could think that there is a difference between variables declared outside and inside the apply block. Perhaps the section on evaluation? Or someplace where the structure of controls is described? |
Thanks everyone for your comments, this was helpful. I'll write a pull request with a clarification. |
If you do it before Monday we'll discuss it at the next design group meeting. |
This PR subsumed by #1243. |
Hi, I apologize if this has already been addressed in issues here. I'm trying to determine what's supposed to happen if a control instance
apply()
is called twice. Is the state of local variables persisted between the two calls, or is it like creating two separate instances and applying them one after the other? Is it even legal P4 to call a control (or parser) twice?Here is an example: https://github.com/cornell-netlab/petr4/blob/36862d54cd037fa964e951db6883236c37485342/stf-test/custom-stf-tests/multiple-calls.p4
...and an STF test describing what I'd expect it to do if local variables persist: https://github.com/cornell-netlab/petr4/blob/36862d54cd037fa964e951db6883236c37485342/stf-test/custom-stf-tests/multiple-calls.stf
The text was updated successfully, but these errors were encountered: