transaction、句柄与 package
返回 ALU 任务总览。
任务:用一笔对象表示一次操作
最初的 drive_and_check(op,a,b) 逐个传参数;改为 drive_and_check(input alu_transaction tr),由事务保存一次操作的字段。下面是教学用的核心片段;当前类还含随机约束与观测结果字段,见 约束随机。
class alu_transaction;
rand logic [2:0] op;
rand logic [7:0] a, b;
logic [7:0] result;
logic rsp_valid;
function new(logic [2:0] op = 0,
logic [7:0] a = 0, b = 0);
this.op = op;
this.a = a;
this.b = b;
endfunction
endclass
alu_transaction tr; // 句柄,尚未有对象
tr = new(3'd0, 8'd7, 8'd9); // 创建对象
drive_and_check(tr);this.op 是对象成员,右侧 op 是构造参数。一个 tr 句柄可以多次指向新对象;new() 每次产生不同对象。当前测试按顺序调用时反复修改同一对象也可能运行,但将来 monitor、mailbox 等并行组件若仍持有同一对象,修改它会改变尚未处理的事务,所以每笔 new() 更安全。tr 默认可能是 null,使用前做句柄保护。
任务:解决报在 tr 附近的错误
// 错:类型名拼写缺下划线
task automatic drive_and_check(input alutransaction tr);
// 对:与类名一致
task automatic drive_and_check(input alu_transaction tr);“near tr, expecting )”常是解析器读不懂其前面的类型,不一定是 tr 变量名有错。先核对类型拼写、定义可见性与编译日志第一条错误。
任务:让类定义对 top 可见
仅把 alu_transaction.sv 排在 tb_top.sv 前面,不能保证两个独立编译单元共享顶层 class。早期用 -mfcu 临时验证过同编译单元方案;也曾讨论在 top 直接 include。正式方案采用 package:
package alu_pkg;
`include "alu_transaction.sv"
`include "alu_driver.sv"
`include "alu_monitor.sv"
`include "alu_scoreboard.sv"
`include "alu_coverage.sv"
endpackagetop 在用到类名之前写 import alu_pkg::*;。interface 不是 class,不放进此 package;包内被 include 的文件也不要再作为独立源文件重复编译。顺序是先 interface,再 package,最后 top;assertion 模块作为独立模块先于 top 编译。
+incdir+../tb 为这些 include 指定查找目录。如果误写为 +incdir+../rtl/simple_alu.sv,并没有把 RTL 加入编译列表;旧库可能掩盖遗漏。检查日志是否确实编译了 simple_alu。
自检问题
- 声明句柄、调用
new()、复制句柄,分别发生了什么? - 为什么更改编译顺序不足以解决所有“unknown type”?
include与import各处理什么问题?
下一步读 分层平台与 virtual interface。