6.MCDF寄存器设计代码
(1)示意图
(2)代码
-
verilog中数组操作:regs[`SLV0_RW_REG][0:5]指的是32bit数据下的0:5位。
7.adapter
(1)adapter的位置
(2)adapter实现
(3)示例代码
[1]继承与uvm_reg_adapter;
[2]在new()中将provides_responses置1;
[3]将uvm_reg_bus_op类型转换成mcdf_bus_trans类型,但是函数返回的是uvm_sequence_item类型。return t;是隐式的转换。
[4]从函数的参数中看出将uvm_sequence_item类型的bus_item转化为uvm_reg_bus_op类型;但父类句柄但指向的是子类对象;定义了子类型mcdf_bus_trans t,需要将父类转换为子类,毕竟指向的是子类对象。
[5]
(4)示例分析
(5)adapter的集成
[1]一般rgm(reg model)在test层,env通过rgm句柄引用,所以先看顶层有没通过config_db配置,没有的话则在env中创建。
[2]rgm.build():可参考9-1-3(2)。
[3]
rgm.map.set_sequencer(agent.sequencer,reg2mcdf);
句柄关联:rgm_map先与adapter关联,adapter又与agent.sequencer关联。
[4]
rgm.map.set_auto_predict();
auto_predictor不依赖于predictor和monitor。
(6)示例分析
8.寄存器的访问方式
(1)概述
-
DPI访问很快,0时刻就可以访问到。
(2)前门访问简介
-
read()、write()是reg的方法;read_reg()、write_reg()是uvm_reg_sequence的方法。
extern virtual task read(output uvm_status_e status,
output uvm_reg_data_t value,
input uvm_door_e path = UVM_DEFAULT_DOOR,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
status: 表示操作状态,OK or NOT OK
value: 表示读出的值
path: 表示是前门访问还是后门访问
map: 表示 如果是前门访问时用哪个map。
parent:表示哪个sequence来发送RAL item读操作请求
prior:表示item的优先级
extension:表示一些扩展信息
fname和lineno没有什么用,暂时不用去care
(3)前门访问示例
(4)后门访问:HDL路径映射
-
reg_backdoor_access是db.config的名字;路径映射后:reg_backdoor_access.dut.regs[]。
(5)后门访问:add_hdl_path()、add_hdl_path_slice()、peek、poke
(6)后门访问示例
(7)前门和后门比较
-
因为有些寄存器配置有先后关系,不受时序的话,会出问题。
(8)混合应用
-
通过随机化寄存器使得各个域处于随机值,再通过前门访问配置我们关注的域的值,这样的好处是不再通过设置复位之后的寄存器,这种更具有确定性的场景,而是一开始就随机化模拟无法预期的硬件配置,在设置了必要的寄存器之后,再看看有没有意想不到的边界情况。
rgm.reg.randomize();
rgm.reg.reg_field.set(值);//设置某个域
rgm.reg.update(status,UVM_FRONTDOOR,.parent(this));
-
通过前门写后门读/后门写前门读,来检查地址映射到错误寄存器的问题。
rgm.reg.write(status,data,UVM_FRONTDOOR);
rgm.reg.mirror(status,UVM_CHECK,UVM_BACKDOOR,.parent(this));
-
对于状态寄存器,这种不方便随机以及不方便和硬件值做比较的,往往先使用peek获取(后门访问会用自动预测更新mirror value),然后再调用mirror的方法从前门访问,和更新的镜像值作比较。
rgm.reg.peek(status,data);
rgm.reg.mirror(status,UVM_CHECK,UVM_FRONTDOOR,.parent(this));//要选择UVM_CHECK
-
比较复位值是不是与硬件一侧的寄存器描述一致,先用get_rest得到软件一侧的复位值,再用后门从硬件里读回硬件复位值(硬件在外部先复位),再比较
@(negedge p_sequencer.vif.rstn);
@(posedge p_sequencer.vif.rstn);
rgm.reg.reset();
value=rgm.reg.get_reset();
value2=rgm.reg.read(status,data,UVM_BACKDOOR);
if(value!=value2) `uvm_error
1.mirror、desired和actual value
(1)
-
每个filed都有两个值。
(2)
2.prediction分类
(1)跟踪寄存器值的两种方式
(2)自动预测
(3)显式预测:explicit
(4)显式预测示例
-
uvm_reg_predictor是参数类,并是component,为了保证monitor的ap口和predictor的imp口类型一致,所以参数是必须的。
-
mcdf2reg_predictor.map = rgm.map; mcdf2reg_predictor.adapter = reg2macdf; 是将map和adapter的句柄接到predictor里面,之所以要传递他们的句柄,是将利用两个函数将预测值返给到reg里。
3.uvm_reg的访问方法
(1)uvm_reg_block、uvm_reg、uvm_reg_field三个类提供访问寄存器的方法表格
[1]read/write/peek/poke
uvm_reg而言,四者都是针对硬件的真实值,后门访问都有这四种方法,而对于前门访问没有peek、poke。
[2]由于前门访问时bytes操作的,所以不能按位修改,所以前门访问中field是“否”。
[3]get与set都是软件值。
(2)再将uvm_reg_sequence提供的方法(均是针对寄存器对象的,而不是寄存器块或者寄存器域)整理如下:
(3)reset() 、get_reset()
(4)mirror()
(5)set()、updata()