IC验证 APB 项目(二)——框架结构(总)
目录
- VIP 框架结构
- config
- interface
- sequence
- sequence item
- seq_lib
- agent
- sequencer
- driver
- monitor
- slave 部分与 master 的区别
- driver
- TB 框架结构
- environment
- base_test
- single_transaction_test
- testbench
VIP 框架结构
config
config 存放配置信息,比如 is_active 可以决定 sequencer、driver 组件是否要被创建和连接,以决定激励是否被激活。
interface
- 定义控制变量和 APB 信号
- 定义时钟块
- 定义了三个 covergroup,并完成相应的例化
- cg_apb_command:记录 PSEL 和 PWRITE 的交叉覆盖率,分为写有效、读有效和无效控制三个 bins
- cg_apb_trans_timing_group:psel 通过 PSEL 维持在高电平的拍数来记录单次或 burst(2/4/816/32) 传输;penable 通过 PENABLE 维持在低电平的拍数来记录单次传输后变回 IDLE 和背靠背两种状态
- cg_apb_write_read_order_group:通过 PWRITE 的四种翻转状态来记录四种读写切换过程
- 定义断言检查和断言覆盖率,具体内容实现由下一篇具体简述
sequence
sequence item
apb_transfer 是 APB 项目的 sequence item,代码包含以下内容:
- 随机变量的定义与约束(addr、data、trans_kind、idle_cycles),其中 trans_kind 是枚举类型,有 IDLE、WRITE、READ;idle_cycles 表示每次 IDLE 状态的保持拍数
- 域的自动化
seq_lib
seq_lib 即 sequence library,集中所有的 sequence,包括 base_sequence、single_write_sequence、single_read_sequence、write_read_sequence、burst_write_sequence、burst_read_sequence。代码包含以下内容:
- 随机变量的定义与约束(addr、data、idle_cycles)
- body 函数:可以利用发送序列宏,对 sequence item 进行对象创建与约束,并调用 start_item() 和 finish_item() 发送给 sequencer 或 driver,有需要时还可以将其挂载到 sequencer。发送后,可使用 get_response,阻塞等待 driver 返回响应,并完成后续处理
- 针对 write_sequence,直接约束其 trans_kind = WRITE,addr、data 为本地生成的随机变量,这部分后续会在 test 层被覆盖
- read_sequence 与 write_sequence 类似,不同的是 trans_kind = READ,同时 data 应为 get_response 获取响应后的数据
agent
agent 可以理解为包含 monitor、sequencer、driver 的壳子,代码包含以下内容:
- build:利用 config 机制获取从 tb 中发送的 apb_config 和 apb_if,并将 apb_config 传递至 monitor、sequencer、driver 对应的 config
- connect
- monitor、sequencer、driver 的 interface 连接
- driver 和 sequencer 的 TLM 端口连接
sequencer
sequencer 的实现较为简单,除了类的创建代码外,声明 apb_config 和 apb_if 句柄即可。
driver
driver 的 run 任务要并行地触发 get_and_drive 和 reset_listener 方法:
- get_and_drive 是 driver 的主控循环,持续从 sequencer 获取 req 事务,调用 drive_transfer 完成激励后反馈响应
- seq_item_port 是 driver 与 sequencer 交互的专用 TLM 端口,常用方法包含以下两种
- get_next_item(output REQ t):阻塞方式等待从 sequencer 获取下一个 item
- item_done(input RSP rsp = null):通知 sequencer 当前 item 已处理完毕,可选择性地传递 RSP 参数
- 补充一点:req 和 rsp 是 UVM 预定义的,类型由当前类的 REQ 和 RSP 决定
- 建立响应 rsp
- req.clone() 返回的是父类句柄,所以利用 $cast 先将其转换为 RSP 类型再进行复制操作
- 复制过程不包含 ID 复制,因此需要补充 set_sequence_id 和 set_transaction_id
- drive_transfer 首先根据 trans_kind 调用不同的方法,do_idle、do_write、do_read
- do_idle:将 PSEL、PENABLE、PWDATA 清零
- do_write:包含两个状态,SETUP 和 ENABLE,根据 APB 时序图完成信号激励即可
- do_read:与 do_write 类似,注意读操作中的 PRDATA 存在delay
- seq_item_port 是 driver 与 sequencer 交互的专用 TLM 端口,常用方法包含以下两种
- reset_listener 负责监听复位信号,复位触发后,恢复 APB 总线的信号为默认值
monitor
monitor 的代码包含以下内容:
- new 包含 uvm_analysis_port 和 apb_transfer 类对象创建,其中例化的 apb_transfer 类就是要被广播的事务
- uvm_analysis_port 是 TLM 的通信管道之一,是一种广播型端口,调用 analysis_port.write(t),即可将事务 t 广播给所有连接到该端口的订阅者(uvm_analysis_imp),可作为 monitor 与 scoreboard 等组件的通信渠道
- run 任务触发 monitor_transactions 方法,代码包含以下内容:
- 调用 collect_transfer 任务,捕捉 APB 总线上的 SETUP 状态,并在下一拍对 PADDR 和 PWDATA(PRDATA)进行采样
- 对捕捉的事务进行广播
slave 部分与 master 的区别
driver
- slave driver 需要关联数组 mem 存放接收的数据
- slave driver 的 run 任务要并行地触发 get_and_drive、reset_listener 和 drive_response 三个方法
- get_and_drive 与 master 中的代码不同的是缺少 drive_transfer 过程,也就是只记录 sequencer 的事务,但不产生激励
- reset_listener 复位触发时将 PRDATA 清零,并将 mem 清空
- drive_response 在捕捉 APB 总线上的 SETUP 状态,并根据 PWRITE 调用 do_write 和 do_read 方法
- do_write:更新 slave driver 的 mem
- do_read:读取地址,判断 mem 的对应位置是否有数据,更新 PRDATA
TB 框架结构
environment
environment 包含 master agent 和 slave agent,代码包含两个 agent 句柄的声明和对象创建。
base_test
base_test 是 environment 的上一层,代码包含 environment 句柄的声明和对象创建。
- apb_base_test_sequence 是跟 test 有关的基类 sequence,代码包含以下内容:
- 定义关联数组 mem,用于数据比对。写操作时数据会同时写入 slave 中的 mem 和 test 中的 mem,后续读操作时,通过比对这两个 mem 对应位置的数据是否一致来验证读写有效性
- check_mem_data 数据比对函数
- 其他基本方法
- wait_reset_release 等待复位信号释放,即先等待 rstn 的下降沿,再等待 rstn 的上升沿
- wait_cycles 等待 n 个时钟周期
- get_rand_addr 随机生成地址,高 20 位设为零,是为了减小随机性,避免连续读阶段时的读出数据一直为空,此外,为了保证访问对齐,通常地址低两位为零
single_transaction_test
single_transaction_test 继承自 base_test,测试任务是产生四个阶段的激励任务,连续写、连续读、读写交替、无间隔地读写交替。
-
apb_single_transaction_sequence 继承自 apb_base_test_sequence,代码包含以下内容:
- seq_lib 中 single_write_sequence、single_read_sequence、write_read_sequence 句柄的声明
- 随机变量的定义与约束,比如 test_num,用以决定每个激励阶段的数据产生次数
- body 函数:先等待复位信号释放,再依次完成四阶段激励任务,每个任务通过利用发送序列宏,对 sequence item 进行对象创建与约束,并调用 start_item() 和 finish_item() 发送给 sequencer 或 driver
-
apb_single_transaction_test 的 run_phase 代码包含以下内容:
- apb_single_transaction_sequence 的句柄声明与对象创建
- raise_objection 挂起 objection 以防止跳出 run_phase
- 调用父类的 run_phase
- 将 apb_single_transaction_sequence 挂载在 environment -> master agent -> master sequencer 上
- drop_objection 落下 objection,跳出 run_phase
testbench
tb 文件的代码包含以下内容:
- 产生时钟和复位信号的激励
- interface 句柄声明
- 利用 config 机制发送 apb_if,后续传递至 master agent 和 slave agent
- run_test 指定运行的 test 名称