文章目录
- 前言
- 一、代码
- 二、错误
- 1.地址范围
- 2. 并行执行线程中变量覆盖的情况
- 3.有关incr的beat
前言
- 来源路科验证
- 本节搞定
T3.3
AHB
总线协议的覆盖:AHB_PROTOCOL_COVER
即测试ahb slave
接口和master
接口支持(尽可能)全部的ahb
协议传输场景,主要是支持burst
传输 (并行发送) - 重点在于如何给地址
- 注意该
test
不是测试映射的完整性的;所以不需要关心整个地址是不是更加完备:即不是把所有的地址都测试完 - 关心的是协议的完整性;只需要保证从三个
master
到三个slave
的访问地址之间没有重合;如果重合会给接下来的数据检查的带来问题;如果同一个地址被两个master
的写所覆盖的话;时序上面的延迟会对预测带来障碍 - 可以加一些约束,让波形是自己所期望的;加的约束越少越好,这样的话协议上各种时序出现的可能性更大;前提是设计没问题,要是设计有问题的话,约束一开始不可以放的太开,那么就要从
singl-----burst------wrap
一步一步来
一、代码
- 思路:先搞定其中的一次并行发送:多个
master
到多个slave
,稳点后,外部套一个repeat
,让其多次发送 - 具体代码
--------------------------AHB_PROTOCOL_COVER_seq------------------
virtual task body();
super.body();
`uvm_info("body", "Entered...", UVM_LOW)
cfg.enable_scb = 0;
cfg.enable_cov = 0;
repeat(loop_count) begin
for(int i=0; i< cfg.mst_num; i++) begin
automatic slv_addr_range_t rng = cfg.addrmap.get_addr_range($random_range(0, cfg.slv_num-1));
automatic int mid = i;
fork
mem_check(mid, rng.addr_start + 'h1000*(mid+cfg.mst_num*$random_range(1, 4)));
join_none
end
wait fork; //等第一次传输完以后,在repeat第二次
end
`uvm_info("body", "Exiting...", UVM_LOW)
endtask
automatic int mid = i;
mid
是在循环体内部使用automatic
关键字声明的变量。这种方式会为每次循环迭代创建一个独立的mid
变量副本。所以每次循环迭代中mid
的值都是动态的,不会相互干扰。loop_count
别忘记在挂载sequence
之前随机
seq
中的代码
loop_count
设置多少以功能覆盖率能不能达到为准
-
如何保证三个
master
给同一个slave
写的话,地址不重合?
这里给的地址是rng.addr_start + 'h1000*(mid+cfg.mst_num*$random_range(1, 4)
,可以看作是基地址+偏移地址,目前的burst_size=32bit
,地址需要以4
字节为单位进行递增;只要给master
一个不一样的地址,后面加4
都会不一样,这样就保证了地址的不一样,所以重点在于如何设置偏移地址 -
将一块地址按照
h'1000
(32‘h0200_0000---32‘h0200_FFFF
)分的话,共15个区间;32‘h0200_0000---32‘h0200_1000
是4KB
,burst
传输要求的地址边界不超过1KB
,所以他会完美的去匹配,无论落到哪一个区间,master
哪怕是incr
他也不会越界,这样就保证了地址的不重合 -
mid+cfg.mst_num*$random_range(1, 4)
这块的取值要保证最大值不可以超过14(E)(2+3*4)=14
-
上面的
4
的值与mst_num
变大和mid都有关
二、错误
1.地址范围
- 出现不应该有的地址范围
- 原因:在随机产生数值时,发生了错误,如果随机到5,最大是
2+3*5=17>>14
,将一块地址按照h'1000
(32‘h0200_0000---32‘h0200_FFFF
)分的话,最后一个值是
E=15`,共15个区间;所以将随机值区间最大改为4
mem_check(mid, rng.addr_start + 'h1000*(mid+cfg.mst_num*$random_range(1, 5)));
2. 并行执行线程中变量覆盖的情况
- 这个错误意味着在并行执行多个序列时,存在某些序列提前完成的情况,导致其他序列的项目无法正常处理。
- 原因:当缺少
automatic int mid = i;
时,i
产生的新的数会将原先的覆盖,导致i
只能是3
,原先的依次被覆盖掉了;
--------------------------AHB_PROTOCOL_COVER_seq------------------
virtual task body();
super.body();
`uvm_info("body", "Entered...", UVM_LOW)
cfg.enable_scb = 0;
cfg.enable_cov = 0;
for(int i=0; i< cfg.mst_num; i++) begin
slv_addr_range_t rng = cfg.addrmap.get_addr_range($random_range(0, cfg.slv_num-1));
//automatic int mid = i;
fork
mem_check(mid, rng.addr_start + 'h1000*(mid+cfg.mst_num*$random_range(1, 4)));
join_none
end
`uvm_info("body", "Exiting...", UVM_LOW)
endtask
- 解决之道:添加
automatic int mid = i;
,最好将rng
也添加automatic
3.有关incr的beat
- 这里的错误提示数据对比出了问题,到底哪儿出了问题,看的不是很清楚,所以在做有关动态数组对比时,先比较动态数组的
size
,然后在比较里面的内容,比较每一个数据, - 详细显示的话,会发现是两边的
size
不一样
定位会发现错误的前面是incr
传输,他的地址只要不跨越1KB
边界即可,到底传了多少拍,不大清楚;不像incr4
之类的,他的拍数是固定的在每一次传输的过程中
可以通过该参数记录,在写数据时记录下来,传递给读数据时的约束
如果给的类型是incr
。没有给data.size
的话会出问题;incr
不限定;;;也就是说如果给的burst_type
是incr
的话,要限定burst_type
的长度