I have the following promela code:
chan level = [0] of {int};
proctype Sensor (chan levelChan) {
int x;
do
:: true ->
levelChan ? x;
if
:: (x < 2) -> printf("low %d", x);
:: (x > 8) -> printf("high %d", x);
:: else -> printf("normal %d", x);
fi
od
}
init {
run Sensor(level);
int lvl = 5;
level ! lvl;
lvl = 0;
do
:: true ->
level ! lvl;
lvl++;
(lvl > 9) -> break;
od
}
I am expecting to send level (0-9) information into a channel and have the sensor output low|normal|high depending on this level. Its quite simple. But why SPIN saying its timeout all the time?
0: proc - (:root:) creates proc 0 (:init:)
Starting Sensor with pid 1
1: proc 0 (:init:) creates proc 1 (Sensor)
1: proc 0 (:init:) 1.pml:18 (state 1) [(run Sensor(level))]
2: proc 1 (Sensor) 1.pml:6 (state 11) [(1)]
3: proc 0 (:init:) 1.pml:20 (state 2) [lvl = 5]
4: proc 0 (:init:) 1.pml:20 (state 3) [level!lvl]
4: proc 1 (Sensor) 1.pml:8 (state 2) [levelChan?x]
5: proc 1 (Sensor) 1.pml:9 (state 9) [else]
6: proc 0 (:init:) 1.pml:21 (state 4) [lvl = 0]
normal 5 8: proc 1 (Sensor) 1.pml:12 (state 8) [printf('normal %d',x)]
9: proc 0 (:init:) 1.pml:22 (state 10) [(1)]
12: proc 1 (Sensor) 1.pml:6 (state 11) [(1)]
13: proc 0 (:init:) 1.pml:24 (state 6) [level!lvl]
13: proc 1 (Sensor) 1.pml:8 (state 2) [levelChan?x]
14: proc 1 (Sensor) 1.pml:9 (state 9) [((x<2))]
low 0 15: proc 1 (Sensor) 1.pml:10 (state 4) [printf('low %d',x)]
17: proc 0 (:init:) 1.pml:25 (state 7) [lvl = (lvl+1)]
19: proc 1 (Sensor) 1.pml:6 (state 11) [(1)]
timeout
#processes: 2
19: proc 1 (Sensor) 1.pml:8 (state 2)
19: proc 0 (:init:) 1.pml:26 (state 8)
2 processes created
It seem to only do 1 iteration of the do loop why?
The statements in the init process's do loop are run in sequence.
do
:: true ->
level ! lvl;
lvl++;
(lvl > 9) -> break;
od
The very first time the do loop is run it will send lvl over the level channel, increase the lvl (so it is now 1) and then test (lvl > 9). This is false so will block and causes the timeout.
To have multiple options in a do loop you need :: to define the start of each option:
do
:: true ->
level ! lvl;
lvl++;
:: (lvl > 9) -> break;
od
However this will still not perform as expected. When lvl is greater than 9 both options of the do loop are valid and either one can be chosen, so the loop will not necessarily break when lvl > 9 it could choose to continue to send the lvl over the level channel and increase lvl.
You need to have a condition on the first do option as well as the second:
do
:: (lvl <= 9) ->
level ! lvl;
lvl++;
:: (lvl > 9) -> break;
od
It might be nicer to use the for loop syntax for this example:
init {
run Sensor(level);
int lvl = 5;
level ! lvl;
for (lvl : 0..9){
level ! lvl;
}
}
Note that this example will still have a timeout error caused by Sensor's do loop, when the init process has finished Sensor will still try to read from the level channel and timeout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With