← SVIP demo · 文档与示例快照 · 运行库、历史验收记录及仿真日志未打包 · 阅读范围说明
SVIP AXI4 使用指导

syan · VCS / UVM 1.2 · 2026-11-01

SVIP AXI4 使用指导

Author: syan

版本范围:当前仓库 AXI4 memory-mapped,VCS / UVM 1.2

本指南按接入、激励、控制、扩展和调试组织。首次使用先完成第二章的 smoke,再选择 manager、subordinate 或 passive 的接入方式。架构实现见 架构,全部可执行场景见 testsuite。所有 shell 命令从产品仓库根执行。

1. 产品能力与角色选择

验证任务 使用组件 驱动的信号
验证 DUT slave svip_axi_mgr_agent AW/W/AR,以及 BREADY/RREADY
验证 DUT master svip_axi_sub_agent AWREADY/WREADY/ARREADY,以及 B/R
观察已有连接 任一 agent,cfg.is_active=UVM_PASSIVE 只观察,不能使用主动控制接口

支持 AXI4 FIXED/INCR/WRAP、窄和非对齐 transfer、独立读写 outstanding、跨 ID 响应乱序、可选 R beat interleave、exclusive、五通道 USER、SV memory、随机数据及用户接管响应。完整协议/profile 检查映射见 protocol-checks。ACE、AXI5、多端口一致性与其他模拟器不在当前验收声明中。

业务 sequence -> sequencer -> manager channels -> DUT slave
DUT master -> subordinate channels -> memory / RANDOM / USER response
                 |
              raw pins -> monitor -> transaction/channel AP
                             +----> checker / coverage / tracker

2. 安装检查与首次运行

准备 VCS、UVM1.2 和站点许可证环境。先查看实际测试清单,再运行 smoke:

python3 axi/scripts/regress.py --suite examples --list
python3 axi/scripts/run.py all --width 512 --case smoke --checker /path/to/Axi4PC.sv

Axi4PC.sv 及相邻依赖由项目自行安装,接入要求见 AXI4PC。不传 checker 的 run.py 可用于本地调试;发布回归要求真实 checker。先确认日志、tracker和精确PASS标记,再扩大配置。

项目编译顺序是 interface → 公共coverage package → AXI package → 可选sequence package → 项目testbench:

vcs -full64 -sverilog -ntb_opts uvm-1.2 -timescale=1ns/1ps \
  +incdir+common+common/cov+axi/src+axi/src/coverage+axi/sequence_lib \
  axi/src/svip_axi_bus_if.sv common/cov/svip_fc_pkg.sv \
  axi/src/svip_axi_pkg.sv axi/sequence_lib/svip_axi_seq_pkg.sv your_tb.sv

这条命令编译产品和项目top;不会自动把自测fixture的Arm bind移植到项目top。外部checker在项目中的连接应单独完成。使用独立vlogan分析时,先执行 vlogan -full64 -ntb_opts uvm-1.2,随后按相同顺序和include路径分析。

3. 顶层连接与 agent 创建

顶层按默认容器实例化interface,配置到目标agent的cfg;以下代码分别放在模块和env的相应位置,clk/resetn 由工程提供:

// 顶层模块
import uvm_pkg::*;
import svip_axi_pkg::*;
svip_axi_bus_if axi_if(clk, resetn);
initial begin
  uvm_config_db#(svip_axi_vif_t)::set(null,"uvm_test_top.env.mgr","dut_axi",axi_if);
  run_test();
end
// env 成员
svip_axi_cfg cfg;
svip_axi_mgr_agent mgr;
// env.build_phase 内,在创建agent之前
cfg = svip_axi_cfg::type_id::create("cfg");
cfg.vif_key = "dut_axi";
cfg.data_bytes = 64; // DATA512;DATA1024使用128
cfg.wr_id_width = 8; cfg.rd_id_width = 6;
cfg.wr_addr_width = 64; cfg.rd_addr_width = 64;
cfg.max_wr_outstanding = 32; cfg.max_rd_outstanding = 64;
cfg.tracker_mode = SVIP_AXI_TRACKER_TXN;
uvm_config_db#(svip_axi_cfg)::set(this,"mgr","cfg",cfg);
mgr = svip_axi_mgr_agent::type_id::create("mgr",this);

不同agent使用不同cfg和vif key。验证DUT master时替换为subordinate并将cfg交给该实例。纯passive设置 is_active=UVM_PASSIVE 并保留monitor;连接上只能有一方主动驱动每组输出。

编译容器与运行时有效宽度不同:默认容器DATA1024、ADDR64、WR_ID12、RD_ID12、USER68。有效宽度在cfg中设置,窄DUT端口由top显式slice/zero extend。不要仅修改interface实例参数却仍使用默认virtual-interface类型;改变容器时,interface/package/top的 SVIP_AXI_MAX_* 编译定义必须一致。

4. 配置参考与生效时机

配置 用途与约束
data_bytes W/R共同DATA,4..最大容器字节数内的2次幂;AxSIZE表示每beat实际transfer大小
wr_id_width/rd_id_width 方向独立;0表示该方向只用ID0;不能超过各自容器
wr_addr_width/rd_addr_width 方向独立,1..地址容器宽度;完整burst必须落在有效空间
max_wr_outstanding/max_rd_outstanding 独立读写在途上限,均大于0;subordinate也受资源上限约束
max_pending UVM已接纳、尚未取得通道额度的队列上限,大于0
max_per_id_outstanding 0表示只受方向总量限制;非0时两个方向分别按ID计数,共用此配置值
w_before_aw_en 允许W早于AW;关闭后W等待自己的AW握手
reorder_en/r_interleave_en subordinate跨ID乱序 / 可选不同ID的R beat交织;同ID保持顺序
memory_mode/sub_response_mode MEMORY或RANDOM;AUTO或USER,两个维度独立
checks_en/x_checks_en/cov_en 内部协议检查、原始四态检查、覆盖率采样
tracker_mode/tracker_filename OFF/TXN/CHANNEL;文件名按实例隔离

角色、宽度、容量、memory/response模式及组件创建配置在build前确定。Timing和公开运行期控制在各自消费点生效;修改策略不会追溯改写已呈现或已选取的payload/延迟。force READY仍不能越过subordinate实际存储容量。

5. Transaction 与 sequence 的完成契约

随附sequence使用 import svip_axi_seq_pkg::*。将自定义类放在项目sequence package中,先import uvm_pkg/svip_axi_pkg/svip_axi_seq_pkg并include uvm_macros.svh;自定义manager sequence可派生 svip_axi_base_seq:

class literal_seq extends svip_axi_base_seq;
  `uvm_object_utils(literal_seq)
  function new(string name="literal_seq"); super.new(name); endfunction
  task body();
    svip_axi_txn t = new_txn("literal_write");
    if (!t.randomize() with {
          dir==SVIP_AXI_WR; addr=='h1000; id==1;
          len==0; size==2; burst==SVIP_AXI_INCR; lock==0;
        }) `uvm_fatal("PATTERN","randomize failed")
    // 地址对齐到bus word的lane0;size=2为4个有效byte。
    t.data[0]='0; t.data[0][31:0]=32'h12345678;
    t.awuser='h25;
    send(t);
    wait_all();
  endtask
  virtual function void on_done(svip_axi_txn rsp);
    if (rsp.aborted) `uvm_info("RESULT","reset aborted request",UVM_LOW)
    else if (rsp.bresp!=SVIP_AXI_OKAY) `uvm_error("RESULT",rsp.convert2string())
  endfunction
endclass

在test的objection保护下调用 seq.start(mgr.sqr)。这里 len=AxLEN=beats-1,size=log2(bytes per beat),不是DATA总位宽。new_txn()从sequencer cfg复制有效profile;直接factory创建时在randomize前调用 cfg.configure_txn(t)。

AXI的send只表示接纳。 driver保留私有clone,完成通过UVM response进入 on_done();wait_all()等待已发送项的终结。不要把原请求对象当成响应,也不要在send之后立即读取它判断完成。普通读检查 rsp.data[]/rresp[];reset中止先检查 aborted,此时响应字段无效。

6. 指定 pattern、随机与 byte lane

随机约束涵盖burst、size、4KB边界、有效ID/地址、cache及exclusive规则。post_randomize()为写请求分配并随机填充 data[]/strb[],默认有效lane全选;DATA数组不是rand字段。需要固定内容时在randomize之后覆盖。切换strobe调用 fill_wdata(SVIP_AXI_STRB_FULL/RANDOM/MIXED),该方法也重新填充数据,因此固定数据要在其后设置。

数据按bus lane表示:data[beat][8*lane+:8];不能把每个窄beat都无条件放在lane0。用 lane_mask(beat) 和地址映射了解表示,数据正确性仍由独立模型判断。USER默认0,awuser/aruser/buser为标量,wuser[]/ruser[]按beat提供;写USER数组长度与W beat一致。

svip_axi_rand_seq 提供 num_txns/num_slots/addr_lo/addr_hi/wr_pct/max_id/max_len/strb_mode 等旋钮。每笔在飞事务独占4KB slot,slot数也限制实际并行度;提高outstanding时需提供足够地址空间和slot。它适用于避免重叠歧义的随机流量;特定地址依赖、重叠访问和小于一页的空间应使用自定义transaction sequence。小transfer分布详见该sequence源码与 examples。

7. Latency、反压和 runtime 控制

控制位置 配置/方法 单位与含义
Manager请求 timing.aw_valid/w_valid/ar_valid 呈现请求前的周期延迟,W按beat
Manager响应反压 timing.b_ready/r_ready 上一次握手后READY保持低的周期数
Subordinate接收 timing.aw_ready/w_ready/ar_ready 接收握手后的READY间隔
Subordinate回复 timing.b_lat/r_lat/r_beat AW/W收齐到B、AR到首R、R beat间隔
强制反压 mgr.force_ready(B/R,enable,value) manager只拥有BREADY/RREADY
请求反压 sub.force_ready(AW/W/AR,enable,value) subordinate只拥有这三组READY
暂停回复 sub.hold_responses(b,r) 阻止启动新响应/新beat,已呈现VALID继续保持
cfg.timing.apply(SVIP_AXI_TIMING_RANDOM);
cfg.timing.r_ready.set_bursty(0,1,20,8,16);
cfg.timing.b_ready.set_fixed(3);
// 运行期,持续若干项目时钟后释放;调用者负责安排等待。
mgr.force_ready(SVIP_AXI_R,1,0);
// ... wait for the desired clock events ...
mgr.force_ready(SVIP_AXI_R,0,0);

set_zero/set_fixed/set_range/set_bursty均按cycle计。0不消除AXI请求/响应依赖;“零延迟”也必须遵守合法握手。已呈现VALID不能因控制开关撤回,payload在VALID&&!READY期间保持。参考 example_timing 和control相关compliance的实际等待/稳定性断言。

8. Subordinate:memory、RANDOM 与 USER

默认 MEMORY+AUTO 自动使用稀疏SV byte memory;未写字节由seed/address hash生成,同地址重复读一致。写尊重WSTRB,memory error region支持SLVERR/DECERR;reset保留字节、清exclusive reservation。

外挂模型派生 svip_axi_mem,覆盖虚 read_byte/write_byte/byte_resp,build前赋给 cfg.mem。直接外部写入需调用 invalidate_range(),避免exclusive reservation失效遗漏;枚举/copy操作另见 架构memory契约。

RANDOM模式不访问memory,cfg.mem可为null;写不保存,读为新的随机active-lane数据且停等稳定。它适用于不检查读写关联的响应场景。

USER模式在build前设置 cfg.sub_response_mode=SVIP_AXI_SUB_USER,上层task取得请求后自行安排响应:

svip_axi_txn req, rsp;
sub.get_request(req);
rsp = sub.default_response(req); // 显式执行默认模型/回调副作用
rsp.buser='h25;
if (!sub.send_response(req,rsp))
  `uvm_error("RESPONSE","request invalidated or already submitted")

写请求在AW与完整W收齐后交付,读请求在AR后交付。保留交付的确切req句柄关联响应;用clone构造rsp,不能用req clone替代关联凭据。helper同请求只执行默认副作用一次,后续返回缓存副本;完全自定义响应可以不调用helper。

Read rsp必须提供完整 data[]/rresp[];ruser[]/rloop[]可全空补零,非空则必须完整。send_response立即保存快照,调用后修改rsp不改变排队内容;重复或reset后的旧句柄被拒绝。同timestamp的Active/NBA提交在严格晚于提交时间的driver时钟消费,然后应用latency。示例和错误修正/重提交场景见 example_slave_model 与 reactive_*。

9. Callback、analysis port、tracker 与覆盖率

add_callback(cb)注册派生 svip_axi_callbacks;request/read_response/write_response是非阻塞function,适合呈现前整形。需要等待事件或由sequence决定回复时使用USER模式。不要在analysis subscriber里修改共享发布对象;需要修改时clone。

观察入口 用途
agent.ap monitor重建的完整transaction
agent.channel_ap 逐握手四态channel快照
sequence on_done manager提交项的响应/中止结果
tracker_mode=TXN 事务摘要;CHANNEL另加逐通道DATA/STRB/USER
cov_en native covergroup与共享coverage service采样

Tracker默认OFF;不同agent应隔离输出文件名。Tracker帮助定位握手,数据正确性由scoreboard/oracle判断。--coverage同时启用VCS数据库与校验后的 fc.json;手工工程用 +svip_fc_json=<path> 在final_phase导出。跨run合并使用 common工具,不兼容profile不能混成一个百分比。

10. Reset、checker 与故障定位

总线reset使用raw epoch guard和NBA后idle处理,终止旧请求/USER上下文并回收资源。Manager中止响应带aborted;旧USER句柄不能重用。Reset不承诺回滚已发生的DUT写副作用。软件停止/abort与共同bus reset语义不同,已经呈现的工作仍遵守握手稳定性。

内部monitor检查未知值、VALID停等稳定、请求/响应依赖、ID顺序、beat/LAST、burst/profile和非法EXOKAY;外部Arm checker独立工作。故意违规用精确rule/scope/count预算,不能全局屏蔽错误。遇到挂起先查看READY控制、USER未提交请求、outstanding/slot及reset状态;遇到数据错先对照lane、WSTRB、RRESP和模型副作用。

波形按接收方采样值判握手,区分raw pins与clocking block输入;时钟沿后的raw idle不等于本沿没有完成。保留seed、容器定义、完整命令与同次run的tracker/FSDB/manifest。

11. Examples、回归与支持边界

python3 axi/scripts/run.py all --width 1024 --case reactive_model \
  --case random_traffic --coverage --checker /path/to/Axi4PC.sv
python3 axi/scripts/regress.py --suite full --coverage --waves --jobs 4 \
  --checker /path/to/Axi4PC.sv

当前具名case及适用组合以 catalog 为准。示例按接入/时序/扩展学习,compliance用于参数、协议、reset与故障回归。512/1024 DATA是主验收矩阵;小DATA/不同容器只运行适用的定向case,不把含大transfer和高地址的整个矩阵机械搬过去。

准确运行结果与限制见 当前验收记录,配置细节见 配置审计,升级旧工程见 迁移指南。