SVIP APB 客户用例与特殊控制
Author: syan
本页面向 APB3/APB4 requester/passive,例子从产品仓库根运行。公开用法仍是 cfg + transaction + UVM sequence + analysis port。完整可执行代码在 control examples 和 原有 examples,清单以 catalog 为准。
先确认信号的控制权
| 目的 | 实际控制方与入口 | 使用边界 |
|---|---|---|
| 指定地址、数据、方向、PPROT、PSTRB | 用户 sequence / svip_apb_txn 或 svip_apb_rw_seq |
requester 驱动;cfg.create_txn() 带有效位宽和对齐约束 |
| 暂停新请求 | cfg.hold |
已呈现的 SETUP/ACCESS 继续完成;不撤回正在等待的请求 |
| 请求间隔、连续传输 | cfg.back_to_back、min_idle_cycles/max_idle_cycles |
不改变当前等待周期,不省略 SETUP |
| 返回等待、反压、PSLVERR、PRDATA | DUT 或外部响应模型 | PREADY 属于响应端;requester 无法强迫 DUT 产生合法反压 |
| 观察实际事务 | agent.mon.ap、reg_ap、abort_ap / driver done_ap |
analysis 快照只读;需要修改时自行 clone;不能据此接管响应 |
| 检查、等待 watchdog | agent.set_checks()、cfg.max_wait_cycles |
watchdog 超限只报告,仍等待完成/reset |
自测 testbench/ 的 ctrl.wait_cycles、manual_response/manual_ready/manual_error/manual_data 是独立 fixture 的控制入口,仅用于例子和验证 VIP。产品当前没有 subordinate、memory backdoor 或“接收请求后由 sequence 回复”的服务接口。
指定内容:直接使用便利 sequence
在 UVM sequence/test 中导入 svip_apb_pkg 和可选的 svip_apb_seq_pkg,cfg 与 agent 已配置:
svip_apb_rw_seq seq = svip_apb_rw_seq::type_id::create("literal");
seq.cfg = cfg;
seq.addr = 'h40; // 当前 profile 要求按 data word 对齐
seq.write = 1;
seq.data = 'h01234567;
seq.strb = '1; // 有效 lane 全部写入
seq.prot = cfg.apb4 ? 3'b101 : 3'b000;
seq.start(agent.sqr);
if (seq.result.status != SVIP_APB_OK)
`uvm_fatal("LITERAL", seq.result.convert2string())
seq.write = 0;
seq.start(agent.sqr);
// seq.data 和 seq.result.data 是实际返回值,按业务模型检查。
finish_item()/seq.start() 同步返回终结结果,无需额外 get_response()。prot 默认0;APB3 必须为0。读请求的 PSTRB 自动为0。示例 example_directed_pattern 发送6组 literal 地址/数据并逐笔读回,同时检查实际引脚的 PPROT,而非只比较配置对象。
python3 apb/scripts/run.py all --case example_directed_pattern --version 4 --coverage
固定部分 bit,其余充分随机
不需要额外 pattern 类型。以下代码位于用户 uvm_sequence #(svip_apb_txn) 的 body,cfg 已提供:
svip_apb_txn t;
svip_apb_strb_t full_strb = 0;
logic [2:0] protection = cfg.apb4 ? 3'b101 : 3'b000;
for (int lane=0; lane<cfg.data_width/8; lane++) full_strb[lane]=1;
t = cfg.create_txn("fixed_nibble_random");
start_item(t);
if (!t.randomize() with {
write == 1;
addr inside {['h40:'h7f]};
data[7:4] == 4'ha;
strb == local::full_strb;
prot == local::protection;
}) `uvm_fatal("PATTERN", "constraints have no solution")
finish_item(t);
if (t.status != SVIP_APB_OK) `uvm_fatal("PATTERN", t.convert2string())
cfg.create_txn() 将有效 ADDR/DATA、协议版本和自然对齐传入 transaction,随机过程不能产生超出有效位宽的地址。业务约束应与这些约束求交;始终检查 randomize 返回值。直接 type_id::create() 则需自行提供 profile。
example_constrained_pattern 连续40次随机写和读回,独立 byte oracle 检数据,实际 monitor 数据检查固定 nibble、地址/低 nibble 的变化;example_random 另覆盖方向、data、prot、strobe 和随机 response wait。覆盖更多 seed 可以发现组合问题,不能代替业务 oracle。
python3 apb/scripts/run.py all --case example_constrained_pattern --version 4 \
--addr-width 20 --data-width 16 --clock-half-ps 250 --coverage
python3 apb/scripts/regress.py --suite examples --seed 7 --coverage
Byte lane 与零 strobe
APB4 对齐 word 的第 lane 个 byte 使用 seq.strb = svip_apb_strb_t'(1) << lane,将数据放在 seq.data[lane*8 +: 8],其他数据位也要在 ACCESS 停等期间保持稳定。PSTRB=0 是合法传输,memory 型 fixture 不更新任何 byte。实际外设的副作用由其寄存器定义决定。
example_byte_lanes 从零初始化,依次写5a/6b/7c/8d;32-bit 读回应为8d7c6b5a。随后发送全1数据、零 strobe,读回保持不变。支持8/16/32-bit,lane 数量从有效 DATA 派生。APB3 没有 byte strobe,该例只适用 APB4。
python3 apb/scripts/run.py all --case example_byte_lanes --version 4 --coverage
本 profile 不提供 unaligned API;修改 word 内某个 byte 使用对齐地址 + PSTRB。便利 sequence 不会把最低 byte 自动搬到指定 lane。
强制反压与复位中止
在自测 fixture 中,ctrl.manual_response=1; ctrl.manual_ready=0; 覆盖实际总线响应,requester 必须保持整个请求。等待不是新的事务;只有 PSEL && PENABLE && PREADY 的采样才是完成候选。
example_backpressure 先预写13579bdf,随后保持一笔2468ace0写连续16个 ACCESS 等待样本,检查 payload 稳定、无提前完成;释放READY后只完成一次,再读回新值。backpressure_reset_write 在同样的停等中 reset,只有一次 RESET_ABORTED,恢复后读回旧值。
python3 apb/scripts/run.py all --case example_backpressure --version 4 --coverage --waves fsdb
python3 apb/scripts/run.py all --case backpressure_reset_write --version 4 \
--clock-half-ps 250 --coverage --waves fsdb
这里的旧值承诺来自 fixture 的“实际总线完成且无错误才提交 memory”策略。VIP 的 RESET_ABORTED 本身不承诺 DUT 回滚写副作用。实际项目请使用 DUT 的响应控制、独立 slave 模型或外部 force,并清楚区分协议违规注入和合法反压。
Hold、idle latency 和 back-to-back
cfg.hold=1 阻止新请求呈现。若已经进入 SETUP/ACCESS,hold 不撤回该请求,完成后停在 idle;cfg.hold=0 允许后续工作。
cfg.back_to_back=0 时,在完成后选择 [min_idle_cycles,max_idle_cycles] 的整数周期延迟;相等时不额外抽随机数。back_to_back=1 不插入额外 idle,但每笔仍有 SETUP。配置在 driver 对应消费点读取;切换业务段时先等待当前段同步完成,再修改。已选定的 idle 间隔不会重新抽样,不能假设 finish_item() 返回后改配置会追溯改变该完成点选出的间隔;example_timing 检查新段内部的后续 gap,不把两段交界处作为新范围的证据。动态 hold 会在 pull 等待之后、呈现之前再确认。
| 配置/开关 | 消费点 |
|---|---|
| vif、active/passive、位宽、APB版本 | build 前确定 |
| tracker/coverage 开关及文件名 | build 前确定;文件名按 agent/run 隔离 |
| hold | 拉取新请求及正式呈现之前检查;对已呈现请求无取消作用 |
| idle 范围、back_to_back | 当前请求终结后选择后续间隔 |
| set_checks() | 同步更新 IF checker 和 monitor watchdog 的运行期开关 |
| max_wait_cycles | monitor 每个等待采样检查;0关闭 |
| fixture.wait_cycles | fixture 在 SETUP 的响应准备点读取 |
| fixture.manual_* | 连续作用于 TB 的响应 mux;本轮例子避开采样沿变更 |
example_hold 也验证已呈现请求继续完成,example_timing 前16笔固定gap=2、后16笔gap=2..5且实际变化、每笔wait=3;example_back_to_back 检查真实零额外 bubble。
错误、观察与波形
example_error 演示真实 PSLVERR 读写响应、允许 error read 数据为X和随后的恢复。check_* 是 checker 资格测试,直接用故障 fixture 驱动非法引脚并检查精确报告预算;它们不是让产品 requester 发送非法流量的公开 API。example_passive 演示独立 requester 下的被动观察。
裸 --waves 与 --waves vcd 保持 VCD。--waves fsdb 使用 VCS/Verdi 的原生 FSDB 支持,要求站点环境已配置;格式进入编译身份及 per-run manifest,缺少所请求格式的文件会失败。
python3 apb/scripts/run.py all --case example_timing --version 4 \
--addr-width 20 --data-width 16 --clock-half-ps 250 --coverage --waves fsdb
波形验收选择 raw pre-edge 与 mon_cb 捕获输入在 edge+1ps 的观测交叉核对。不要用时钟沿后的 raw idle 判定本沿没有完成。FSDB 的 settled 数据无法恢复未记录的 delta/NBA 顺序;reset 与 READY 同 tick 的结果同时依据明确的 reset-priority 契约和原生 SV 检查。实际执行结果见 第二轮验收记录。