由于示例中的代码似乎没有遵循规范,至少在我理解的方式上,我从头开始编写了一个示例。
请注意,以下模型(源代码)在其结构中故意非常冗长和冗余,以便更容易识别其逻辑块并 - 希望 - 理解它。在实践中,人们会使用一些内联函数来处理输入。我也没有使用SIGACT, SIGDEACT
原始模型中出现的 which,因为我无法弄清楚谁应该从原始模型(源代码)和规范中读取这些消息。
#define ALARM_OFF 1
#define ALARM_COUNTDOWN 2
#define ALARM_ARMED 4
#define ALARM_INTRUSION 8
#define ALARM_FIRED 16
#define INPUT_SET_PASSWORD 1
#define INPUT_CHECK_PASSWORD 2
#define INPUT_INTRUDER 4
mtype = { SIGACT, SIGDEACT };
init {
chan alarm_out = [1] of { mtype };
chan alarm_in = [1] of { byte, short };
run alarm(alarm_in, alarm_out);
run user(alarm_in);
run event(alarm_in);
}
proctype alarm(chan input, output)
{
byte count;
byte state = ALARM_OFF;
short passwd = 1234;
short tmp = 0;
off:
if
:: nempty(input) ->
if
:: input?INPUT_SET_PASSWORD(tmp) ->
passwd = tmp;
:: input?INPUT_CHECK_PASSWORD(tmp) ->
if
:: tmp == passwd ->
atomic {
state = ALARM_COUNTDOWN;
count = 0;
goto countdown;
}
:: else ->
skip;
fi;
:: input?INPUT_INTRUDER(tmp) ->
skip;
fi;
:: empty(input) -> skip;
fi;
goto off;
countdown:
if
:: count < 30 ->
if
:: nempty(input) ->
if
:: input?INPUT_SET_PASSWORD(tmp) ->
skip; // error: cannot be done now (?)
:: input?INPUT_CHECK_PASSWORD(tmp) ->
if
:: tmp == passwd ->
atomic {
state = ALARM_OFF;
count = 0;
goto off;
}
:: else ->
skip; // error: incorrect password (?)
fi;
:: input?INPUT_INTRUDER(tmp) ->
skip;
fi;
:: empty(input) ->
skip;
fi;
:: else ->
atomic {
state = ALARM_ARMED;
count = 0;
goto armed;
}
fi;
count++;
goto countdown;
armed:
if
:: nempty(input) ->
if
:: input?INPUT_SET_PASSWORD(tmp) ->
skip; // error: cannot be done now (?)
:: input?INPUT_CHECK_PASSWORD(tmp) ->
if
:: tmp == passwd ->
atomic {
state = ALARM_OFF;
count = 0;
goto off;
}
:: else ->
skip; // error: incorrect password (?)
// maybe it should be handled like
// INPUT_INTRUDER(tmp)
fi;
:: input?INPUT_INTRUDER(tmp) ->
atomic {
state = ALARM_INTRUSION;
count = 0;
goto intruder_detected;
}
fi;
:: empty(input) ->
skip;
fi;
goto armed;
intruder_detected:
if
:: count < 15 ->
if
:: nempty(input) ->
if
:: input?INPUT_SET_PASSWORD(tmp) ->
skip; // error: cannot be done now (?)
:: input?INPUT_CHECK_PASSWORD(tmp);
if
:: tmp == passwd ->
atomic {
state = ALARM_ARMED;
count = 0;
goto armed;
}
:: else ->
skip; // error: incorrect password (?)
fi;
:: input?INPUT_INTRUDER(tmp) ->
skip;
fi;
:: empty(input) ->
skip;
fi;
:: count >= 15 ->
atomic {
state = ALARM_FIRED;
count = 0;
goto alarm_fired;
}
fi;
count++;
goto intruder_detected;
alarm_fired:
if
:: nempty(input) ->
if
:: input?INPUT_SET_PASSWORD(tmp) ->
skip; // error: cannot be done now (?)
:: input?INPUT_CHECK_PASSWORD(tmp);
if
:: tmp == passwd ->
atomic {
state = ALARM_OFF;
count = 0;
goto off;
}
:: else ->
skip; // error: incorrect password (?)
// warn user but keep alarm on
fi;
:: input?INPUT_INTRUDER(tmp) ->
skip;
fi;
:: empty(input) ->
skip;
fi;
goto alarm_fired;
};
proctype user(chan output)
{
output ! INPUT_CHECK_PASSWORD(1234);
};
proctype event(chan output)
{
output ! INPUT_INTRUDER(0);
};
因此,基本上您必须同时检查(如果input
有的话!)和值,count
以便在系统的内部FSM中执行转换。alarm
在示例中,我添加了一个proctype
名称event
,它将随机向系统发送单个INPUT_INTRUDER
输入信号alarm
。这与user
输入他自己的密码相结合,可用于触发会导致警报触发的事件链。