memory模型的前门操作
memory模型的前门访问包括passive模式和active 模式,在passive模式,根据monitor监控到的接口上的读写事务进行更新内存;在active模式下则由slave sequence更新内存。
// axi_slave_mem_response_sequence
if(req_resp.xact_type == svt_axi_slave_transaction::WRITE) begin
put_write_transaction_data_to_mem(req_resp);
end
else begin
get_read_data_from_mem_to_transaction(req_resp);
end
在base_test中需要使用config_db机制将该slave_resp_seq设置为对应slave_agent中sequencer的default sequene
uvm_config_db#(uvm_object_wrapper)::set(this,"*sub_env.axi_sys_env.slave[0].sequencer.run_phase","default_sequence",axi_slave_mem_response_sequence::type_id::get());
memory模型的后门操作
鉴于uvm_root.find可以用来查找UVM树形结构中的例化的component句柄,可以用此方法获取验证环境中例化的svt_mem,然后调用svt_mem自带的write()和read()方式进行后门操作。
获取memory类型
function automatic svt_mem find_svt_mem(string name)
static svt_axi_slave_agent axi_salve_agent0;
static svt_axi_slave_agent axi_salve_agent1;
svt_mem memory;
case(name)
"axi_salve0":begin
if(axi_salve_agent0 == null) begin
uvm_pkg::uvm_root root = uvm_pkg::uvm_root::get();
uvm_pkg::uvm_component comp = root.find("*sub_env.axi_sys_env.slave[0]");
assert($cast(axi_salve_agent0,comp));
end
memory = axi_salve_agent0.axi_slave_mem;
end
... ...
endcase
return memory;
endfunction
获取到axi slave中的memory后,便可以调用其自带的read()和write()方法通过后门的方式访问该内存。需要注意的是,对该内存的访问需要保证地址对齐(地址需要与配置的该slave agent的data_width对齐)。
自定义函数的封装
假设axi_slave agent的配置参数 addr_width 为 48-bit,data_width 为256-bit,可以按照以下方式进行封装。
function logic [7:0] axi_write_mem8(string name, bit [47:0] address, logic [7:0] data)
bit [47:0] mem_address;
logic [255:0] mem_data;
logic [31:0] mem_strb;
svt_mem axi_mem;
axi_mem = find_svt_mem(name);
mem_address = address;
mem_data = 'h0;
mem_data[mem_address[4:0]*8 +: 8] = data;
mem_strb = 'h0;
mem_strb[mem_address[4:0]] = 1'b1;
void'(axi_mem.write({mem_address[47:5],5'b00000},mem_data,mem_strb));
endfunction
其他方法介绍
另外,axi slave vip还提供write_byte()和read_byte(),可以按字节对memory进行后门访问,其原型如下:
task svt_axi_slave_agent::write_byte(input bit[`SVT_AXI_MAX_ADDR_WIDTH-1:0] addr, bit[7:0] data);
task svt_axi_slave_agent::read_byte(input bit[`SVT_AXI_MAX_ADDR_WIDTH-1:0] addr, output bit[7:0] data);
set_meminit() 方法 可以配置mem模型对未写过的地址返回一些特定值,以此实现mem的随机初始化,原型如下:
task svt_mem::set_meminit (svt_mem::meminit_enum meminit = UNKNOWNS,
bit [SVT_MEM_MAX_DATA_WIDTH-1:0] meminit_value = 0,
bit [SVT_MEM_MAX_ADDR_WIDTH-1:0] meminit_address_offset = 0)
meminit_enum 中定义的类型如下:
UNKNOWNS
ZEROES
ONES
ADDRESS
VALUE
INCR
DECR
USER_PATTERN
RANDOM
可以通过如下方式为svt_mem赋值:
axi_mem = find_svt_mem("axi_slave");
axi_mem.set_meminit(svt_mem::VALUE,'h123456789,'h0);
补充知识
uvm_root中的find()和find_all()方法
详见UVM_Class_Reference_Manual的uvm_root章节.
- function uvm_component find (string comp_match)
该方法调用了uvm_root::find_all
- function void find_all (string comp_match, ref uvm_component comps[S], input uvm_component comp=null)
find/find_all可以根据传入的字符串(string comp_match)来查找uvm树形结构中例化的 component句柄(find)或者component句柄列表(find all)。
例如,sequence中使用 uvm_top.find(“uvm_test_top”)就可以获得testcase的句柄。
同时,find/find_all调用了DPI,对字符串支持使用通配符*和?
uvm_root.find源码如下