什么导致Promela / SPIN超时?

时间:2013-02-03 09:17:45

标签: verification spin promela

我有以下promela代码:

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
}

我期望将电平(0-9)信息发送到通道,并根据该电平使传感器输出低|正常|高。它很简单。但是为什么SPIN一直在说它的超时?

  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

似乎只做了1次迭代的do循环为什么?

1 个答案:

答案 0 :(得分:3)

init进程的do循环中的语句按顺序运行。

do 
:: true ->
    level ! lvl; 
    lvl++;
    (lvl > 9) -> break;
od

第一次运行do循环时,它会在lvl频道上发送level,增加lvl(现在为1),然后测试{{1} }。这是假的,因此会阻止并导致超时。

要在do循环中有多个选项,您需要(lvl > 9)来定义每个选项的开头:

::

然而,这仍然无法按预期执行。当do :: true -> level ! lvl; lvl++; :: (lvl > 9) -> break; od 大于9时,do循环的两个选项都是有效的,并且可以选择其中一个,因此当lvl可以选择继续发送lvl > 9时,循环不一定会中断在lvl频道上方,增加level

您需要在第一个选项和第二个选项上有条件:

lvl

在此示例中使用for循环语法可能更好:

do 
:: (lvl <= 9) ->
    level ! lvl; 
    lvl++;
:: (lvl > 9) -> break;
od

请注意,此示例仍会因init { run Sensor(level); int lvl = 5; level ! lvl; for (lvl : 0..9){ level ! lvl; } } 的循环导致超时错误,当Sensor进程完成时init仍会尝试从{{1}读取通道和超时。