包含指令生成,verilog编译的可自定义的自动化测试流程脚本

提示:这篇文章即将在作者的博客上发布,敬请期待。

FyVoid

CO_tester

repo: https://github.com/FyVoid/BUAA_CO_tester 北航云盘提供的下载存在严重的bug,且难以随后续开发更新,现只提供github repo地址

本项目包括

  • python实现的MIPS汇编程序生成程序
  • 一套利用mars命令行和iverilog对随机生成的程序进行汇编、仿真并输出结果的流程
  • 可自定义的汇编指令生成、有一定扩展性
  • 通过魔改版MARS进行正确性验证

环境配置

完整运行此测试流程,你需要至少有

  • iverilog
  • java(支持mars)
  • shell脚本支持(windows可以尝试使用git bash)

如果要通过gtkwave查看波形,则需要安装gtkwave并支持控制台命令gtkwave

太长不看

clone或从北航云盘下载后,将CO_tester和你的verilog源代码置于同一个目录,将verilog源码(应该包含一个能正常运行的testbench)置于src文件夹下,此时目录应该类似于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.
├── CO_tester
│   ├── CO_test.sh
│   ├── README.md
│   ├── analyse.py
│   ├── assemble.asm
│   ├── assemble.sh
│   ├── compile.sh
│   ├── generate.py
│   ├── mars.jar
│   ├── pytester
│   │   ├── analyser.py
│   │   ├── hex2binary.py
│   │   ├── instruction.py
│   │   └── tester.py
├── src
│   ├── ... 你的verilog cpu源代码
│   ├── mips.v
│   ├── mips_tb.v 你的testbench(不需要同名)

在终端运行

1
sh CO_test.sh

程序会自动生成一个mips程序assemble.asm

mars命令行会将该程序转化为code.txt,随后iverilog会编译verilog源码,并生成波形和cpu输出(存于cpu_output.txt),python程序会对比verilog输出和魔改版MARS产生的标准输出,输出对应关系于log.txt,gtkwave会自动启动并显示波形

log.txt应该类似这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@00003000: $18 <= 29a30000        <=>    @00003000: $18 <= 29a30000
@00003004: $ 3 <= 0000a435 <=> @00003004: $ 3 <= 0000a435
@00003008: $ 8 <= 0000009c <=> @00003008: $ 8 <= 0000009c
@0000300c: *00000dd0 <= 0000a435 <=> @0000300c: *00000dd0 <= 0000a435
@00003010: $ 6 <= 54b80000 <=> @00003010: $ 6 <= 54b80000
@00003014: $ 2 <= 0000d7a6 <=> @00003014: $ 2 <= 0000d7a6
@00003018: $ 3 <= 00000000 <=> @00003018: $ 3 <= 00000000
@00003020: $22 <= b16e0000 <=> @00003020: $22 <= b16e0000
@00003028: $31 <= 0000302c <=> @00003028: $31 <= 0000302c
@000030d8: $20 <= 0000a3a3 <=> @000030d8: $20 <= 0000a3a3
@000030dc: $ 4 <= ffff285a <=> @000030dc: $ 4 <= ffff285a
@000030e0: $23 <= 00000000 <=> @000030e0: $23 <= 00000000
@000030e4: $ 6 <= 00000000 <=> @000030e4: $ 6 <= 00000000
@000030e8: $ 7 <= 00000000 <=> @000030e8: $ 7 <= 00000000
@000030ec: $ 8 <= 00000dd0 <=> @000030ec: $ 8 <= 00000dd0
@000030f0: *00000dd0 <= 00000000 <=> @000030f0: *00000dd0 <= 00000000
@000030f4: $20 <= 00000000 <=> @000030f4: $20 <= 00000000
@000030f8: $19 <= 0000b631 <=> @000030f8: $19 <= 0000b631
@000030fc: $11 <= ffff2d7f <=> @000030fc: $11 <= ffff2d7f
@00003100: $ 8 <= 00000898 <=> @00003100: $ 8 <= 00000898
@00003104: *000008e8 <= 00000000 <=> @00003104: *000008e8 <= 00000000
@00003108: $ 8 <= 00000394 <=> @00003108: $ 8 <= 00000394
@0000310c: $23 <= 00000000 <=> @0000310c: $23 <= 00000000
@00003110: $31 <= 00003114 <=> @00003110: $31 <= 00003114
@000031c8: *000007f4 <= 29a30000 <=> @000031c8: *000007f4 <= 29a30000
@000031cc: $ 2 <= 0000142a <=> @000031cc: $ 2 <= 0000142a
@000031d0: $20 <= 0000b631 <=> @000031d0: $20 <= 0000b631
END
All Correct Nya!

整个测试逻辑图如下,各个组件可以分开使用

tester.drawio

批量测试

愿意折腾的学生能学到更多

如果你去github上获取最新版,可以通过

1
sh batch_test.sh <batch_count>

进行批量测试,如果不指定batch_count,则会进行50次测试
测试的结果会被汇总到batch_log.txt文件下

高级功能

事实上,你可以通过一定的修改来自定义汇编程序的生成,可以自定义的部分包括

  • 自定义新指令
  • 自定义每个指令生成概率
  • 自定义某些行为的概率(如跳转和内存存取)
  • 自定义生成程序的指令条数

自定义新指令

通过调整tester_config.txt的内容,你可以减少/添加已有的指令,控制每个指令生成的概率,甚至自定义新的指令

指令的格式为

1
[指令名] [参数1], (参数2), (参数3) | (output), (prob:生成概率)

指令名可以是任何合理的名字

参数可选的值如下

参数 效果
$reg 随机产生\$t, \$s, \$a, \$v中的寄存器
$t 随机产生\$t0-\$t9
$s 随机产生\$s0-\$s7
$a 随机产生\$a0-\$a3
$v 随机产生\$v0 or \$v1
$im 随机产生范围为0-0xffff的立即数
$lb 随机产生跳转标签、标签可能是已经存在的标签,也可能是新的标签,这个概率由generate.py中的参数决定
$rega 随机产生一个形如offset(\$t0)的地址,地址的值(即offset+\$t0)可能是先前使用过的地址,也可能是新的地址,如果是已经产生过的地址,则一定为0(\$t0)

$rega一定会在存取指令前产生一条ori指令,保证地址对齐

指令结尾的|是必须的,如果其后有output,表示该条指令会导致verilog仿真产生输出(根据CO课程规则),如果有prob,表示该指令的概率人为制定,格式为prob:(0-1的数)f结尾的f是必须的

如果所有指令概率和>1或所有指令概率和<=1且每条指令均被指定概率,则每条指令概率为该条指令概率/总概率

否则,未指定概率指令概率为(1-已指定指令概率和)/(未指定概率指令数)

自定义生成概率和生成数量

generate.py文件中

1
2
3
gen_label_prob = 0.2		# 产生新标签的概率
former_addr_prob = 0.5 # 产生新地址的概率
total_instruct = 114 # 总的指令数量,由于$rega会产生ori,不是确定数量(可能+1)

shell脚本命令行参数

  • nw: 不自动开启gtkwave
  • nl: log中不保存所有指令对应关系
  • ns: 命令行不输出log
  • dir <dirname>: 保存临时文件和log的目录

最后

该自动化程序会继续更新适用新的课程要求


CookedBear(助教) 回复 FyVoid
助教认证

同学你好,感谢你将自己的在测试方面的成果开源分享供大家学习。目前的程序已经基本具有了在 verilog cpu 中进行自动化测试的能力了。下面是一些小小的改进意见,希望能够帮助同学进一步完善自动化测试的流程。

  • 首先,在测试代码生成部分,预先设置 tester_config 文件将待测指令的格式进行统计是一种很巧妙的方法,直观地将程序的代码量进行了缩减。但在后续 project 中,我们构建的 cpu 需要支持更多的指令类和具体指令,只用文本的方式对指令的特征进行说明、区分可能会略显吃力。可以尝试对指令类、单条指令进行建类、继承,对指令进行更详细的区分,也能更好地控制指令所用寄存器、立即数的选用策略。
  • 其次,不知你是否注意到了,在同学提供的 log.txt 中,3条 add、sub 指令,其中有 2 条实际上进行了对两个内容为 0 寄存器的运算,如果同学后续有继续改进的想法,在测试强度上可以从这一点入手进行改进。
  • 最后,对于进行仿真的工具链,可以尝试使用 ise 的命令行工具进行仿真,我们的教程中也有相关的章节。不过可能会多增加一些用户使用时的配置步骤,但同样在教程中有提示:

最终仿真的结果依旧以 ISE 为准,Icarus Verilog 在某些情况下会与 ISE 产生不同结果

希望完善后的测试工具能够帮助更多的同学 All Correct Nya!


FyVoid 回复 CookedBear(助教)

感谢助教的指正
其实采取配置文件定义指令的设计模式是出于以下考虑

  • tester只负责指令的文本生成
  • mars负责所有的指令实际译码和执行

也就是希望通过隔离指令文本的生成和解释两个部分提供更加便捷、可扩展性更高的测试过程,例如如果我想加入qaq指令,只需要在config中加入

1
qaq $reg, $reg, $reg |  

而qaq指令具体的执行依赖于mars相关的修改,例如采用学长开发的魔改版mars添加class文件扩展
当然,未来如果已有的指令格式不足以表达需求,也会增加新的指令格式
另外感谢提出出现重复无用测试的情况,会想办法改进!


fickle

学长有写过一个魔改版mars,可以拿来当std用https://github.com/Toby-Shi-cloud/Mars-with-BUAA-CO-extension


FyVoid 回复 fickle

很好的建议,现在已经支持


fickle

如果有人在.v文件中写了`include,需要在compile.sh中将

1
find ../src -name "*.v" | xargs iverilog -o wave

改为

1
find ../src -name "*.v" | xargs iverilog -o wave -I <include files path>

以支持.v文件中的`include。

例如include都在同一层文件夹下,include files path就为../src


fickle

gen似乎是有一点问题,可能在存取数据的时候没判范围之类的,跑mars的时候有个报错

1
line 17: Runtime exception at 0x00003038: address out of range 0xffffff44

FyVoid 回复 fickle

如果用的是早上发布的版本会有这个问题,下午发布的版本应该已经修复了这个问题 如果用的已经是新版本,能不能提供一下报错的指令内容


fickle 回复 FyVoid

给你github上发issue了


fickle

vvp运行的时候似乎不能停止?我跑的时候有这个问题,所以给前面加上了一个timeout 1。不知道楼主有没有这个问题。


FyVoid 回复 fickle

这个跟你的testbench有关系,例如我的testbench在1000多延时后会停止 你可以用$finish;让verilog停止仿真


fickle 回复 FyVoid

哦,合理

0%