求助:UVM中peek与poke的问题
正在学习UVM中对register model的backdoor访问。使用peek的时候有点问题,想不出到底为什么,于是上来请教大家。
我在my_test中的run_phase中这样写:
- phase.raise_objection(this);
- begin
- uvm_status_estatus;
- addr=32'h0;
- data=32'h0;
- repeat(1024) begin
- reg_tb0.apb_slave.n_ram.write(status.addr,data);
- addr++;
- data +=2'b10;
- end
- addr=32'h0;
- repeat(1024) begin
- reg_tb0.apb_slave.n_ram.peek(status,addr,data);
- reg_tb0.apb_slave.n_ram.read(status,addr,data1);
- $display("peek @%0h=%0h\t\tread @%0h=%0h",addr,data1,addr,data);
- addr++;
- end
- end
- phase.drop_objection(this);
peek @0=d712read @0=1
peek @1=1read @1=11
peek @2=1read @2=21
peek @3=1read @3=31
peek @4=1read @4=41
peek @5=1read @5=51
peek @6=1read @6=61
peek @7=1read @7=71
. . .. . .
peek @3ff=1read @3ff=3ff1
我有点不大明白,为什么peek出来的所有的数都不对呀?
没人知道么?
自己顶上去。
这个算是backdoor访问么?怎么看着像一般的寄存器访问操作呢?
后来如何解决的,问题出在哪里?
peek使用的hierarchy写错了。就是写register model的时候
也在做memory的backdoor访问操作,不是很清楚uvm_mem.svh源文件中的函数peak/poke和write/read的区别,write/read不支持backdoor访问 ? 另外hdl_path和地址之间是如何绑定的,hdl_path的作用是什么,在函数中视乎不需要指定这个路径?
求小编再给解释一下……
另外是否有backdoor的访问方式的example,能不能给个参考。谢谢
也在做memory的backdoor访问操作,不是很清楚uvm_mem.svh源文件中的函数peak/poke和write/read的区别,write/read不支持backdoor访问 ? 另外hdl_path和地址之间是如何绑定的,hdl_path的作用是什么,在函数中视乎不需要指定这个路径?
求小编再给解释一下……
另外是否有backdoor的访问方式的example,能不能给个参考。谢谢
也在做memory的backdoor访问操作,不是很清楚uvm_mem.svh源文件中的函数peak/poke和write/read的区别,write/read不支持backdoor访问 ? 另外hdl_path和地址之间是如何绑定的,hdl_path的作用是什么,在函数中视乎不需要指定这个路径?
求小编再给解释一下……
另外是否有backdoor的访问方式的example,能不能给个参考。谢谢
backdoor是直接通过hdl_path访问寄存器或者ram,就像平时写的“u_dut.apb_slave.regA=16‘h45"一样。这样访问是不消耗仿真时间的,而read/write是通过总线访问需要消耗仿真时间。hdl_path那个我忘了,应该是没有什么关系吧,如果需要backdoor访问,则需要指定正确的hdl_path,不然就会像我这个问题一样了。我出现这个问题是地址对了,但是hdl_path错了,因此前后门的数值对不上。
在uvm1.1c的库文件中,uvm_mem.svh的1434行起 有下面的这段代码,想请问,这里面的rw.path就是所谓的hdl_path了,是如何传递进来,以及和offset进行绑定的呢?
谢谢
task uvm_mem::write(output uvm_status_estatus,
inputuvm_reg_addr_toffset,
inputuvm_reg_data_tvalue,
inputuvm_path_epath = UVM_DEFAULT_PATH,
inputuvm_reg_mapmap = null,
inputuvm_sequence_base parent = null,
inputintprior = -1,
inputuvm_objectextension = null,
inputstringfname = "",
inputintlineno = 0);
// create an abstract transaction for this operation
uvm_reg_item rw = uvm_reg_item::type_id::create("mem_write",,get_full_name());
rw.element= this;
rw.element_kind = UVM_MEM;
rw.kind= UVM_WRITE;
rw.offset= offset;
rw.value[0]= value;
rw.path= path;
rw.map= map;
rw.parent= parent;
rw.prior= prior;
rw.extension= extension;
rw.fname= fname;
rw.lineno= lineno;
do_write(rw);
status = rw.status;
endtask: write
在uvm1.1c的库文件中,uvm_mem.svh的1434行起 有下面的这段代码,想请问,这里面的rw.path就是所谓的hdl_path了,是如何传递进来,以及和offset进行绑定的呢?
谢谢
task uvm_mem::write(output uvm_status_estatus,
inputuvm_reg_addr_toffset,
inputuvm_reg_data_tvalue,
inputuvm_path_epath = UVM_DEFAULT_PATH,
inputuvm_reg_mapmap = null,
inputuvm_sequence_base parent = null,
inputintprior = -1,
inputuvm_objectextension = null,
inputstringfname = "",
inputintlineno = 0);
// create an abstract transaction for this operation
uvm_reg_item rw = uvm_reg_item::type_id::create("mem_write",,get_full_name());
rw.element= this;
rw.element_kind = UVM_MEM;
rw.kind= UVM_WRITE;
rw.offset= offset;
rw.value[0]= value;
rw.path= path;
rw.map= map;
rw.parent= parent;
rw.prior= prior;
rw.extension= extension;
rw.fname= fname;
rw.lineno= lineno;
do_write(rw);
status = rw.status;
endtask: write
应该就是的。不大明白你说的跟offset进行绑定是什么意思,反正当时我使用register model的时候,需要用configure函数对其指定hdl_path
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- demo_cfg = demo_config::type_id::create("demo_cfg");
- vdo_cfg= config1::type_id::create("vdo_cfg");
- uvm_config_object::set(this,"apb0*","cfg",demo_cfg);
- uvm_config_object::set(this,"apb0.slave[0]*","cfg",demo_cfg.slave_configs[0]);
- uvm_config_object::set(this,"vdo0*","cfg",vdo_cfg);
- uvm_config_object::set(this,"vdo0.slave[0]","cfg",vdo_cfg.slave_configs[0]);
- apb0=apb_env::type_id::create("apb0",this);
- vdo0=vdo_env::type_id::create("vdo0",this);
- regmodel=ral_block_apb_basic_block::type_id::create("regmodel",,get_full_name());
- regmodel.configure(null,"top.u_dut.apb_slave");
- regmodel.build();
- regmodel.lock_model();
- regmodel.reset();
- reg_sqr_adapter=reg_to_apb_adapter::type_id::create("reg_sqr_adapter",,get_full_name());
- mon_sqr_adapter=reg_to_apb_adapter::type_id::create("mon_sqr_adapter",,get_full_name());
- reg_predictor=new("reg_predictor",this);
- endfunction : build_phase
这个regmodel是个ram,而它的地址的指定,是在为其建立模型的时候:
- class ral_mem_MY_RAM extends uvm_mem;
- //function new(string name = "MY_RAM");
- function new(string name = "n_ram");
- super.new(name, `UVM_REG_ADDR_WIDTH'h400, 32, "RW", build_coverage(UVM_NO_COVERAGE));
- endfunction
- virtual function void build();
- endfunction: build
- `uvm_object_utils(ral_mem_MY_RAM)
- endclass : ral_mem_MY_RAM
- class ral_block_apb_basic_block extends uvm_reg_block;
- //rand ral_mem_MY_RAM MY_RAM;
- rand ral_mem_MY_RAM n_ram;
- function new(string name = "apb_slave");
- super.new(name, build_coverage(UVM_NO_COVERAGE));
- endfunction: new
- virtual function void build();
- this.default_map = create_map("", 0, 4, UVM_LITTLE_ENDIAN);
- //this.MY_RAM = ral_mem_MY_RAM::type_id::create("MY_RAM");
- //this.MY_RAM.build();
- //this.MY_RAM.configure(this, "");
- //this.default_map.add_mem(this.MY_RAM, `UVM_REG_ADDR_WIDTH'h0, "RW", 0);
- this.n_ram = ral_mem_MY_RAM::type_id::create("n_ram");
- this.n_ram.build();
- this.n_ram.configure(this,"n_ram.mem");
- this.default_map.add_mem(this.n_ram,`UVM_REG_ADDR_WIDTH'h0,"RW",0);
- //add_hdl_path("dut","apb_slave");
- endfunction : build
- function display();
- $display({"***************now is ",get_full_name()});
- endfunction : display
- `uvm_object_utils(ral_block_apb_basic_block)
- endclass : ral_block_apb_basic_block
小编看了你上面的代码还有一个问题,你在config里指明了 HDL 路径
但是在peek/poke 中有一个地方是判断是否使用backdoor访问的,uvm_mem.svh中的源码 如下
task uvm_mem::peek(output uvm_status_estatus,
inputuvm_reg_addr_toffset,
output uvm_reg_data_tvalue,
inputstringkind = "",
inputuvm_sequence_base parent = null,
inputuvm_objectextension = null,
inputstringfname = "",
inputintlineno = 0);
uvm_reg_backdoor bkdr = get_backdoor();
uvm_reg_item rw;
m_fname = fname;
m_lineno = lineno;
if (bkdr == null && !has_hdl_path(kind)) begin
`uvm_error("RegModel", {"No backdoor access available in memory '",
get_full_name(),"'"})
status = UVM_NOT_OK;
return;
end
这里面的bkdr = get_backdoor 该怎样保证不为 null ?谢谢
小编,看了你的这段代码,有个问题不理解,调用uvm_peek函数时, 下面的这个如何设置get_backdoor
task uvm_mem::peek(output uvm_status_estatus,
inputuvm_reg_addr_toffset,
output uvm_reg_data_tvalue,
inputstringkind = "",
inputuvm_sequence_base parent = null,
inputuvm_objectextension = null,
inputstringfname = "",
inputintlineno = 0);
uvm_reg_backdoor bkdr = get_backdoor();
uvm_reg_item rw;
m_fname = fname;
m_lineno = lineno;
if (bkdr == null && !has_hdl_path(kind)) begin
`uvm_error("RegModel", {"No backdoor access available in memory '",
get_full_name(),"'"})
status = UVM_NOT_OK;
return;
end
怎么设置get_backdoor才能够让bkdr != null ?
谢谢
小编,看了你的这段代码,有个问题不理解,调用uvm_peek函数时, 下面的这个如何设置get_backdoor
task uvm_mem::peek(output uvm_status_estatus,
inputuvm_reg_addr_toffset,
output uvm_reg_data_tvalue,
inputstringkind = "",
inputuvm_sequence_base parent = null,
inputuvm_objectextension = null,
inputstringfname = "",
inputintlineno = 0);
uvm_reg_backdoor bkdr = get_backdoor();
uvm_reg_item rw;
m_fname = fname;
m_lineno = lineno;
if (bkdr == null && !has_hdl_path(kind)) begin
`uvm_error("RegModel", {"No backdoor access available in memory '",
get_full_name(),"'"})
status = UVM_NOT_OK;
return;
end
怎么设置get_backdoor才能够让bkdr != null ?
谢谢
小编,看了你的这段代码,有个问题不理解,调用uvm_peek函数时, 下面的这个如何设置get_backdoor
task uvm_mem::peek(output uvm_status_estatus,
inputuvm_reg_addr_toffset,
output uvm_reg_data_tvalue,
inputstringkind = "",
inputuvm_sequence_base parent = null,
inputuvm_objectextension = null,
inputstringfname = "",
inputintlineno = 0);
uvm_reg_backdoor bkdr = get_backdoor();
uvm_reg_item rw;
m_fname = fname;
m_lineno = lineno;
if (bkdr == null && !has_hdl_path(kind)) begin
`uvm_error("RegModel", {"No backdoor access available in memory '",
get_full_name(),"'"})
status = UVM_NOT_OK;
return;
end
怎么设置get_backdoor才能够让bkdr != null ?
谢谢
我觉得应该是确保你设定的hdl_path是正确的,畅通的。
因为get_backdoor是'get the user-defined backdoor for all registers in this block'
如果你定义的backdoor路径是错误的,或者没有指定backdoor路径,那么,肯定返回的是null值。
我是这样理解的,不知道你有什么想法呢?