[CU]reg model使用篇-uvm_reg常用操作part2(peek(读操作)/poke(写操作))
参考资料:
(1) 《UVM1.1应用指南及源代码分析》
1. peek/poke (path=BACKDOOR)
(1) peek/poke同属于后门访问register/register field方式, 与backdoor read/write类似,但是peek/poke不会模拟寄存器的行为;
(2)如果对一个只读寄存器进行write操作,无论是BACKDOOR还是FRONTDOOR,都不能写进去,而对其进行poke操作(即写操作),能写进去;
(3) 如果对一个读清零的寄存器来说,进行read操作,无论是BACKDOOR还是FRONTDOOR, DUT中此寄存器的值在read操作之后都会变为0,而peek则会得到寄存器的值,但是DUT中寄存器的值依然保持不变;
1 regmodel.register.poke(status,value,.parent(this)); 2 regmodel.register.peek(status,value,.parent(this));
(4) peek/poke操作完成后,寄存器模型会根据操作的结果更新期望值和镜像值(二者相等);
2. peek源码
(1) peek task内部会判断寄存器是否能进行BACKDOOR操作,比如是否设置该寄存器的hdl path;
(2) 主要是调用backdoor_rd task与do_predict(UVM_PREDICT_READ); do_predict用于更新register model中寄存器的相关值;
1 task uvm_reg::peek(output uvm_status_e status, 2 output uvm_reg_data_t value, 3 input string kind = "", 4 input uvm_sequence_base parent = null, 5 input uvm_object extension = null, 6 input string fname = "", 7 input int lineno = 0); 8 9 uvm_reg_backdoor bkdr = get_backdoor(); 10 uvm_reg_item rw; 11 12 m_fname = fname; 13 m_lineno = lineno; 14 15 if (bkdr == null && !has_hdl_path(kind)) begin 16 `uvm_error("RegModel", 17 $sformatf("No backdoor access available to peek register \"%s\"", 18 get_full_name())); 19 status = UVM_NOT_OK; 20 return; 21 end 22 23 if(!m_is_locked_by_field) 24 XatomicX(1); 25 26 // create an abstract transaction for this operation 27 rw = uvm_reg_item::type_id::create("mem_peek_item",,get_full_name()); 28 rw.element = this; 29 rw.path = UVM_BACKDOOR; 30 rw.element_kind = UVM_REG; 31 rw.kind = UVM_READ; 32 rw.bd_kind = kind; 33 rw.parent = parent; 34 rw.extension = extension; 35 rw.fname = fname; 36 rw.lineno = lineno; 37 38 if (bkdr != null) 39 bkdr.read(rw); 40 else 41 backdoor_read(rw); 42 43 status = rw.status; 44 value = rw.value[0]; 45 `uvm_info("RegModel", $sformatf("Peeked register \"%s\": 'h%h", 46 get_full_name(), value),UVM_HIGH); 47 48 do_predict(rw, UVM_PREDICT_READ); 49 50 if (!m_is_locked_by_field) 51 XatomicX(0); 52 endtask: peek
3. poke源码
(1) 主要是调用backdoor_wr task与do_predict(UVM_PREDICT_WRITE);
(2) 本质上采用的是deposit函数;
(3) poke与backdoor write的区别在于后者在调用backdoor_write操作前,先使用backdoor的read读出原来寄存器的值,把读出来的值以及要写入的数值通过调用uvm_reg_field的XpredictX,得到一个新的值,这个值其实就完全模拟了FRONTDOOR行为的一个值,之后再把这个值写入,而前者则是直接写入;
1 task uvm_reg::poke(output uvm_status_e status, 2 input uvm_reg_data_t value, 3 input string kind = "", 4 input uvm_sequence_base parent = null, 5 input uvm_object extension = null, 6 input string fname = "", 7 input int lineno = 0); 8 9 uvm_reg_backdoor bkdr = get_backdoor(); 10 uvm_reg_item rw; 11 12 m_fname = fname; 13 m_lineno = lineno; 14 15 16 if (bkdr == null && !has_hdl_path(kind)) begin 17 `uvm_error("RegModel", 18 {"No backdoor access available to poke register '",get_full_name(),"'"}) 19 status = UVM_NOT_OK; 20 return; 21 end 22 23 if (!m_is_locked_by_field) 24 XatomicX(1); 25 26 // create an abstract transaction for this operation 27 rw = uvm_reg_item::type_id::create("reg_poke_item",,get_full_name()); 28 rw.element = this; 29 rw.path = UVM_BACKDOOR; 30 rw.element_kind = UVM_REG; 31 rw.kind = UVM_WRITE; 32 rw.bd_kind = kind; 33 rw.value[0] = value & ((1 << m_n_bits)-1); 34 rw.parent = parent; 35 rw.extension = extension; 36 rw.fname = fname; 37 rw.lineno = lineno; 38 39 if (bkdr != null) 40 bkdr.write(rw); 41 else 42 backdoor_write(rw); 43 44 status = rw.status; 45 `uvm_info("RegModel", $sformatf("Poked register \"%s\": 'h%h", 46 get_full_name(), value),UVM_HIGH); 47 48 do_predict(rw, UVM_PREDICT_WRITE); 49 50 if (!m_is_locked_by_field) 51 XatomicX(0); 52 endtask: poke
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?