目录
uvm_reg_access_seq
if (model == null) begin
`uvm_error("uvm_reg_access_seq", "No register model specified to run sequence on")
return;
end
uvm_reg_block model;
reg_seq = uvm_reg_single_access_seq::type_id::create("single_reg_access_seq");
this.reset_blk(model);
model.reset();
do_block(model);
需要指定进行寄存器测试的model,随后例化uvm_reg_single_access_seq。
reset_blk是一个空函数,具体不清楚
随后进行model的reset,依次调用下层reg或是blk的reset
reset函数链接
reset函数链接:
function void uvm_reg_block::reset(string kind = "HARD");
foreach (regs[rg_]) begin
uvm_reg rg = rg_;
rg.reset(kind);
end
foreach (blks[blk_]) begin
uvm_reg_block blk = blk_;
blk.reset(kind);
end
endfunction
reg又依次调用field的reset函数
function void uvm_reg::reset(string kind = "HARD");
foreach (m_fields[i])
m_fields[i].reset(kind);
// Put back a key in the semaphore if it is checked out
// in case a thread was killed during an operation
void'(m_atomic.try_get(1));
m_atomic.put(1);
m_process = null;
Xset_busyX(0);
endfunction: reset
接下来看一些do_block内容
如果在seq中使用了uvm_resource_db来禁用了该blk那么会直接退出该函数
blk.get_registers(regs, UVM_NO_HIER);
顺便看一下uvm_resource_db,链接如下
调用get_registers来获取该blk例化的所有寄存器,但不会获取子blk中例化的寄存器,因为是UVM_NO_HIER
foreach (regs[i]) begin
// Registers with some attributes are not to be tested
if (uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
"NO_REG_TESTS", 0) != null ||
uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},
"NO_REG_ACCESS_TEST", 0) != null )
continue;
// Can only deal with registers with backdoor access
if (regs[i].get_backdoor() == null && !regs[i].has_hdl_path()) begin
`uvm_warning("uvm_reg_access_seq", {"Register '",regs[i].get_full_name(),
"' does not have a backdoor mechanism available"})
continue;
end
reg_seq.rg = regs[i];
reg_seq.start(null,this);
end
遍历得到的寄存器队列,首先还是检查是否设置了屏蔽寄存器
检查寄存器是否设置后门路径
将uvm_reg_single_access_seq的rg变量指向实例化的寄存器,start seq。
uvm_reg_single_access_seq
uvm_resource_db不再多说,没有为rg设置后门路径直接return,无法执行该test,因为该test后续需要对寄存器进行后门读操作
if (rg.get_backdoor() == null && !rg.has_hdl_path()) begin
`uvm_error("uvm_reg_access_seq", {"Register '",rg.get_full_name(),
"' does not have a backdoor mechanism available"})
return;
end
得到该rg所在的map数,一个寄存器可以被包含在多个map中,对应多个物理接口
rg.get_maps(maps);
获取寄存器域,遍历包含的所有map
遍历寄存器域,get_access后去域属性,对RO属性进行计数
如果寄存器属性是未知的return
begin
uvm_reg_field fields[$];
rg.get_fields(fields);
foreach (maps[k]) begin
int ro;
ro=0;
foreach (fields[j]) begin
if (fields[j].get_access(maps[k]) == "RO") begin
ro++;
end
if (!fields[j].is_known_access(maps[k])) begin
`uvm_warning("uvm_reg_access_seq", {"Register '",rg.get_full_name(),
"' has field with unknown access type '",
fields[j].get_access(maps[k]),"', skipping"})
return;
end
end
if(ro==fields.size()) begin
`uvm_warning("uvm_reg_access_seq", {"Register '",
rg.get_full_name(),"' has only RO fields in map ",maps[k].get_full_name(),", skipping"})
return;
end
end
end
如果ro变量等于寄存器域数量,也就是该寄存器是RO属性return
test部分
get获取寄存器的期望值(寄存器复位后期望值就是默认值)
前门给寄存器写入按位取反的期望值
mirror函数将寄存器的镜像值与后门读到的值进行相比,保证前门写入的值从后门能够正确读出来
后门给寄存器写入期望值,随后前门mirror
foreach (maps[j]) begin
uvm_status_e status;
uvm_reg_data_t v, exp;
`uvm_info("uvm_reg_access_seq", {"Verifying access of register '",
rg.get_full_name(),"' in map '", maps[j].get_full_name(),
"' ..."}, UVM_LOW)
v = rg.get();
rg.write(status, ~v, UVM_FRONTDOOR, maps[j], this);
if (status != UVM_IS_OK) begin
`uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
"' when writing '",rg.get_full_name(),
"' through map '",maps[j].get_full_name(),"'"})
end
#1;
rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, uvm_reg_map::backdoor(), this);
if (status != UVM_IS_OK) begin
`uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
"' when reading reset value of register '",
rg.get_full_name(), "' through backdoor"})
end
rg.write(status, v, UVM_BACKDOOR, maps[j], this);
if (status != UVM_IS_OK) begin
`uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
"' when writing '",rg.get_full_name(),
"' through backdoor"})
end
rg.mirror(status, UVM_CHECK, UVM_FRONTDOOR, maps[j], this);
if (status != UVM_IS_OK) begin
`uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
"' when reading reset value of register '",
rg.get_full_name(), "' through map '",
maps[j].get_full_name(),"'"})
end
end
endtask:
但是在测试的时候RO域怎么办呢?
对于RO寄存器来说,期望值是0吗?