- #软件验证 #verification #模型检查 #nuxmv
- 2024-07-11
- 3900+字
背景
NuXMV是软件验证领域常用的开源的模型检查工具,用于验证基于状态机的系统设计是否满足指定规约。最近写作业要用到这东西,因为站里相关资料比较少(搜了一下,主要是LauZyHou的系列阅读比较高,【nuXmv学习笔记】1:交互Shell和建模元素-CSDN博客)
同时,大模型对该语言理解较差,给出的错误太多了!(btw,大模型什么时候在形式化体系上的演绎能力能达到可信的地步啊,能不能 不要很自信地写一堆错误出来啊 爷服了 Orz) 大模型给我的错误有:
- 大模型生成的注释格式是"// comment here",实际应为"-- comment" or “/-- comment --/”;
- 大模型生成的逻辑与是’&&‘,实际应为’&’
- …
- 感觉大模型会错认为smv格式的代码和C语言类似…
所以,为什么不在写作业的过程中,顺便产生一些有点用的笔记呢?感觉自己写的example应该有一定意义。都说中文互联网原创资料少,那就更要多自己写,改变这现状了。
叠甲
虽然有点了解了这个工具,但是学习的时间也不过一两天,了解还很肤浅。写作目的只是为了便于和自己一样的初学者,能够更好、更快掌握这个工具。
如果有表达错误或者不够好的地方,希望读者、评论者能够指出,菜鸡这里提前感谢了🥹🙏
任务需求
作业的要求比较复杂,也没有得到老师和助教的授权,不适合直接写出来,所以做了个简化。
简化后,任务需求是:
- 假设工厂的某个工作站有一个传感器模块和一个处理器模块。传感器模块有 Wait 和 Send 两个状态。
- 当系统的时钟达到一定时间后,传感器收到数据,即它的状态从 Wait 转换到 Send 。
- 在传感器处理完数据以后,会将数据发送给处理器模块。这里我们为简单考虑,只考虑传感器状态从 Send 转换到 Wait。
- 此外,约定每个模块的处理时间都是某一范围内的随机值。
思路、编写smv、run!
思路
- 传感器的要求比较多,可以用一个MODULE来描述它,内部使用一个枚举型变量
state
维护状态;用一个有界变量process_time
表示它处理数据的时间。 - 系统的
main
模块可以用一个变量clock
模拟系统时钟,用system_start
表示系统启动时间。 - 为了方便表达’传感器处理完数据后xxx’的状态变化,我还在传感器里添加了
finish_time
变量,表示任务结束时间,当clock
到达finish_time
时,表示任务处理完。
编写可验证的规约
为了方便验证,我们先写两个LTL规约:
-
LTLSPEC G (call_sensor.state = Wait);
含义:总是有传感器状态为 Wait。(Globally=总是,该命题显然是不成立的,False) -
LTLSPEC F (call_sensor.state = Send);
含义:未来某刻传感器状态为Send( F=in the future,该命题显然成立,True)
对应smv代码
MODULE sensor
VAR
state: {Wait, Send};
process_time: 1..10; -- 假设处理时间都是该范围, bounded
finish_time: integer; -- 处理结束时间; 有这个变量,后面容易处理'完成处理后的逻辑'
ASSIGN
init(state) := Wait;
init(finish_time) := 0;
INIT process_time >= 1 & process_time <= 10; -- 初始化,让process_time 在[1,10]间选个值,对应命令: pick_state/msat_pick_state
MODULE main
VAR
clock: integer;
system_start: integer;
call_sensor: sensor;
ASSIGN
init(clock) := 0;
init(system_start) := 1; -- 假设时刻为1是启动时间
-- 时钟递增
next(clock) := clock +1 ;
-- 通过时钟控制 sensor 的状态变化,定义transition:
next(call_sensor.state) :=
case
clock = system_start : Send; -- 第一个传感器启动
(call_sensor.state = Send) & (clock = call_sensor.finish_time) : Wait;
TRUE : call_sensor.state;
esac;
next(call_sensor.finish_time) :=
case
clock = system_start : system_start + call_sensor.process_time;
TRUE : 0;
esac;
LTLSPEC G (call_sensor.state = Wait);
LTLSPEC F (call_sensor.state = Send);
验证过程
- 配置环境、测试配置成功
从nuxmv官网下载好以后,解压、配置环境变量指向nuxmv的bin目录,并在命令行测试nuxmv
命令:
关键命令(下图来自 nuXmv: Model Checking* (unitn.it),侵删)
- 启动nuxmv
- 启动nuxmv阅读smv文件
nuxmv -int "path-to\test.smv"
- 初始化模型
go_msat
msat_pick_state
命令基本上都可以带 -h 选项查看帮助手册。
这里的常见错误是:错误:不可能建立具有无限精度变量的BDD FSM-腾讯云开发者社区-腾讯云 (tencent.com)
> go
Impossible to build a BDD FSM with infinite precision variables
需要用 go_msat
- 运行:
msat_simulate -v -k 10
- 检验规约是否正确:↓
msat_check_ltlspec_bmc -n 0
msat_check_ltlspec_bmc -n 1
符合预期,
第一个规约(索引为0,LTLSPEC G (call_sensor.state = Wait),找到了counterexample,为False)
第二个规约(索引为1,LTLSPEC F (call_sensor.state = Send), 找不到counterexample,为True)
附录
nuxmv 官网: nuXmv - Home (fbk.eu)
其他nuxmv资料: