天天看点

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

UVM学习之路(6)— QuestaSim的调试方法

一、前言

在使用仿真器的过程中会涉及到库窗口、仿真窗口和过程窗口,他们将与硬件、模型 和在线运行的进程一一对应。

二、库窗口

所有编译成功的硬件(module、interface、program)和软件(class、package)都可以被放入库中,如果不指定放入的位置,他们会被放入默认的work库中。如下所示,是QuestaSim的库窗口;

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

三、仿真窗口

仿真窗口(sim window)代表目前正在进行的仿真结构,一般在验证环境中,应该包含硬件测试的结构组件和待测设计(DUT)。如下所示,是QuestaSim的仿真(sim)窗口,我们可以看到除了有我们自己编写后被编译出来的库,还有被默认引入的标准库;

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

不过需要注意的是,仿真窗口只能提供静态的 层次结构,即由module、program、interface和package的内容,但是对于class的例化实例这种在验证环境中十分重要的动态软件内容,则需要在类窗口(class window)和对象窗口(object window)中查看。

四、过程窗口

过程窗口(process window)代表着整个仿真在某一个时间点上所有过程语句块(initial、always、assign)的状态。如下所示,是QuestaSim的过程窗口;

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

如果状态为

active

,代表该进程块正在执行,如果是

ready

状态,代表该进程块是非活跃状态。

五、查看信号和波形

我们在启动仿真后仿真器会自动打开波形(Wave)窗口,如下所示

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

然后我们就可以在仿真窗口或者信号窗口(objects window)中选中需要的信号添加到波形窗口处,如下所示,选中要添加的波形,右键点击【Add Wave】即可

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

这样我们点击运行后即可在Wave窗口中看到波形了

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

另外,在命令窗口(transcript window)使用命令

log -r/*

在开始仿真前调用,可以确保TB层次下所有信号都可以保存到数据库以供查看任何信号的波形。

六、测量时钟

在Wave窗口中点击绿色+号的【Insert cursor】图标,添加一个时间轴

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

然后我们移动时间轴,可以看到两个时间轴之间的时间间隔

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

接着格式设置图标,

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

将【Show frequency in cursor delta】勾选上

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

我们就可以看到,之前的时间间隔变成了频率格式

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

七、设置断点

设置断点可以便于查看软件程序(function、task、object)中局部变量的数值。因为软件部分的变量(即动态变量dynamic variable)是无法添加到波形窗口的,所以软件部分的变量我们需要通过设置断点的方法来查看。编写代码如下所示

module breakpoint1;

	int val1;
	int val2;

	int result;
	function int incr_static(input int a);
		result = a + 1;
		return result;
	endfunction

	function automatic int incr_dynamic(input int a);
		int result;
		result = a + 1;
		return result;
	endfunction

	initial begin
		val1 = 0;
		val1 = incr_static(val1);
		val1 = incr_static(val1);  // breakpoint line8 result == ?
	end

	initial begin
		val2 = 0;
		val2 = incr_dynamic(val2);
		val2 = incr_dynamic(val2); // breakpoint line14 result == ? 
	end

endmodule
           

编译仿真运行,然后在仿真窗口双击模块名称

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

我们就可以看到代码窗口打开了,并在模块声明行出现了 一个小旗子

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

接着在代码窗口左边的行号上点击一下即可设置一个断点了

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

然后我们点击【Run -All】图标,或者输入

run -all

命令,让代码运行到14行断点处

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

然后我们可以在【Locals】窗口中看到动态变量的值

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

八、强制修改信号

编写代码如下所示,

module simstart1;

	logic a1=0; 
	logic a2, a3, a4, a5;
	bit rstn, clk;

	assign a2 = a1; 		// assign

	initial begin 			// initial
	  a3 = a1;
	end

	always @(posedge clk, negedge rstn) begin // sequential logic
		if(rstn === 'b0) a4 <= 0;
		else a4 <= a1;
	end

	always @(a1) begin // combination logic
		a5 <= a1;
	end

	initial begin
		#10ns rstn <= 0;
		#20ns rstn <= 1;
	end

	initial forever #5ns clk <= !clk;

endmodule
           

在第19行设置断点,仿真运行100ns,会发现我们无法运行到断点处,这是因为仿真过程中a1的值一直没有改变

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

我们在【Objects】窗口中选中

a1

,右键选择【Modify】->【Force…】以强行修改a1的值

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

编辑如下所示,将要修改为的值输入

1'h1

,延时等待时间输入

10ns

,点击OK保存

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

然后输入命令

run 20ns

运行20ns,可以看到,在10ns时运行到断点处停下来了

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

但是此时

a5

并没有变化

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

我们在输入

run 0

命令让仿真再运行一个时间片,可以看到,a5的值 已经变成

1'h1

了,然后运行箭头也离开了19行

UVM学习之路(6)— QuestaSim的调试方法UVM学习之路(6)— QuestaSim的调试方法

继续阅读