智能网站建设软件有哪些,品牌网站建设小蝌蚪c,小程序开发厂家,wordpress优惠券插件文章目录 前言一、寄存器模型对DUT的模拟1.1 期望值和镜像值1.2 常见操作对期望值和镜像值的影响 二、prediction分类2.1 自动预测2.2 显式预测 三、访问寄存器方式四、mem和reg的联系和差别五、内建built_in sequence5.1 寄存器模型内建序列5.2 存储器模型内建序列5.3 禁止域名… 文章目录 前言一、寄存器模型对DUT的模拟1.1 期望值和镜像值1.2 常见操作对期望值和镜像值的影响 二、prediction分类2.1 自动预测2.2 显式预测 三、访问寄存器方式四、mem和reg的联系和差别五、内建built_in sequence5.1 寄存器模型内建序列5.2 存储器模型内建序列5.3 禁止域名 六、寄存器模型的应用场景七、检查寄存器的方式八、覆盖率收集 前言
2023.4.24 寄存器模型学起来感觉好难没太理解主要是还没有实际使用理论知识学起来枯燥 一、寄存器模型对DUT的模拟
1.1 期望值和镜像值 镜像值mirrored value表示当前硬件状态的已知值。镜像值往往由模型预测给出即在前门访问时通过观察总线或在后门访问时通过自动预测等方式来给出镜像值。镜像值有可能与硬件实际值actual value不一致无法保持同步更新。 期望值desired value先利用寄存器模型修改软件对象值而后利用该值更新硬件值。 mirrored value与desired value是寄存器模型的属性而actual value对应硬件的真实数值。 对于存储器并不存在期望值和镜像值。
class case0_cfg_vseq extends uvm_sequence;virtual task body();p_sequencer.p_rm.invert.set(16h1); //设置期望值value p_sequencer.p_rm.invert.get(); //get函数去获得期望值value p_sequencer.p_rm.invert.get_mirrored_value(); //得到镜像值p_sequencer.p_rm.invert.update(status, UVM_FRONTDOOR); //update函数会去检查两者是否一致不一样会把期望值写入DUT同时更新镜像值...
endclass1.2 常见操作对期望值和镜像值的影响
read/write/peek/poke读写会使得寄存器模型去更新值使得两者是相等的 set只改变期望值不改变镜像值 update检查是否一致不一致会去更新镜像值使其和期望值相同 randomize随机化后期望值会改变镜像值不改变。但不是所有寄存器模型都支持此函数此外可以在configure函数的第八个参数关闭随机化功能。
一般randomize和update配合使用上电复位后先随机化再update去配置DUT。
二、prediction分类
左边是自动预测右边是显示预测
2.1 自动预测
auto prediction没有predictor和monitor的情况下利用寄存器的操作来自动记录每次寄存器的读写数值并在后台自动调用predict()方法。
后门访问的时候只能自动预测uvm_reg_map::set_auto_predict()。如果出现其它一些sequence直接在总线层面上对寄存器进行操作(跳过寄存器级别的write()/read()操作)或通过其它总线访问寄存器等额外情况都无法自动得到寄存器的镜像值和预期值。
2.2 显式预测
explicit更加可靠的方式是在物理总线上通过monitor捕捉总线事务并将捕捉到的事务传递给外部例化的predictor再利用adapter的桥接方法实现事务信息转换并将转化后的寄存器模型有关信息更新到map中。
显式预测对寄存器数值预测更为准确
class base_test extends uvm_test;reg_model rm; //寄存器模型my_adapter reg_sqr_adapter;my_adapter mon_reg_adapter; //adapter是object类uvm_reg_predictor #(bus_transaction) reg_predictor; //predictor是组件类参数类声明要传递的transaction类型...
endclassfunction void base_test::build_phase (uvm_phase phase) ;rm reg_model::type_id::create ( rm, this) ;rm.configure ( null, );rm.build ( ) ;rm.lock_model ( );rm.reset ( ) ;reg_sqr_adapter new ( reg_sqr_adapter ) ;mon_reg_adapter new ( mon_reg_adapter ) ;reg_predictor new ( reg_predictor, this) ;env.p_rm this.rm;
endfunctionfunction void base_test::connect_phase (uvm_phase phase) ;rm.default_map.set_sequencer (env.bus_agt.sqr,reg_sqr_adapter); //连接sequencer和adapterrm.default_map.set_auto_predict (0); //此处设置为0的话就会关闭右图虚线更新寄存器模型的路径 reg_predictor.map rm.default_map; reg_predictor.adapter mon_reg_adapter;env.bus_agt.ap.connect (reg_predictor.bus_in) ;
endfunction在connect_phase中需要将reg_predictor和bus_agt的ap口连接在一起并设置reg_predictor的adapter和map。只有设置了map后才能将predictor和寄存器模型关联在一起。 在集成的过程中需要将adapter与map的句柄也一并传递给predictor同时将monitor采集的事务通过analysis port接入到predictor一侧。
三、访问寄存器方式
1、uvm_reg_block、uvm_reg、uvm_reg_field三个类提供用于访问寄存器的方法
mirror()读取actual value去更新mirrored value前门后门都可以还可以检查update()先set修改软件的值然后再去修改硬件actual value最后总线获得数据去更新mirrored value。最后三个数据都是一样的。这个两个函数前门后门访问都可以使用但是不能对寄存器域进行操作set()set的是desired value是软件的值不是硬件实际值。set之后的操作是update因为两侧的值不相同了。get()get的是desired value是软件的值不是硬件实际值reset()复位block/reg/field的期望值和镜像值get_reset()得到reg/field的复位值
mirror和read对比
相同都可以进行前门或后门访问不同mirror不会返回读取的值但是会把镜像值进行修改mirror前门访问可以进行block级别操作
randomize、set和update配合使用模拟场景 先随机化寄存器的值再去设置某些特定的值最后再根据这些值去配置寄存器相比较于write和read来说这样做可以模拟更多的场景。
void(rgm.chnl0_ctrl_reg.randomize());
rgm.chnl0_ctrl_reg.pkt_len.set(h3);
rgm.chnl0_ctrl_reg.update(status, UVM_FRONTDOOR, .parent(this));void(rgm.chnl1_ctrl_reg.randomize());
rgm.chnl1_ctrl_reg.set(h22);
rgm.update(status, UVM_FRONTDOOR, .parent(this));2、uvm_reg_sequence的访问方式针对寄存器对象reg的不是寄存器块或寄存器域
对于前门访问的read()和write()在总线事务完成时镜像值和期望值才会更新为与总线上相同的值这种预测方式是显式预测对peek()和poke()及后门访问模式下的read()和write()由于不通过总线默认采取自动预测的方式故在零时刻方法调用返回后镜像值和期望值也相应修改复位操作捕捉到硬件进行复位时需要把验证平台的寄存器模型进行复位。 复位后可以读取复位值并与后门访问获得的寄存器复位值进行比较来判断复位是否成功。
(negedge p_sequencer.vif.rstn);
rgm.reset();
rgm.chnl0_ctrl_reg.reset();
rgm.chnl0_ctrl_reg.pkt_len.reset(); //检查复位是否成功
rstval rgm.chnl0_ctrl_reg.get_reset(); //得到复位值只能在reg/field层次
rgm.chnl0_ctrl_reg.read(status, data, UVM_BACKDOOR, .parent(this));
if(rstval ! data)uvm_error(RSTERR, reset value read is not the desired reset value)四、mem和reg的联系和差别
UVM寄存器模型也可以对存储建模。可以模拟RW、RO、WO类型的存储而且可以配置存储模型的数据宽度和地址范围。
一旦映射会带来很大的资源消耗因此就不支持预测和影子存储功能shadow storage没有镜像值和期望值。利用自带的方法去访问硬件存储。利用模型的地址范围去测试硬件的地址范围是否全部覆盖。提供前门和后门访问可以先后门写前门读以前是系统函数或者仿真器除了有read/write/peek/poke之外还有burst_read和burst_write函数连续传输传进去的是数组形式传递多个数据。如果需要实现更多的协议配置要去建议在总线UVC层面去驱动
五、内建built_in sequence
UVM自带的一些sequence可以在项目初期对寄存器模型进行验证为后期各个功能点验证打下基础
5.1 寄存器模型内建序列 5.2 存储器模型内建序列 5.3 禁止域名
对一些寄存器如果想将其排除在某些内建序列测试范围之外可额外添加上面列表中提到的“禁止域名”。由于uvm_reg_block和uvm_reg都是uvm_object类而不是uvm_component类所以可以使用uvm_resource_db来配置“禁止域名”。
class mcdf_rgm extends uvm_reg_block;...virtual function build();...//disable build-in seq attributesuvm_resourcr_db #(bit)::set({REG::, this.chnl0_stat_reg.get_full_name()}, NO_REG_ACCESS_TEST, 1);uvm_resourcr_db #(bit)::set({REG::, this.chnl1_stat_reg.get_full_name()}, NO_REG_ACCESS_TEST, 1);uvm_resourcr_db #(bit)::set({REG::, this.chnl2_stat_reg.get_full_name()}, NO_REG_ACCESS_TEST, 1);endfunction
endclass六、寄存器模型的应用场景
检查寄存器以及协助检查硬件设计逻辑和比对数据在对硬件数据通路做数据比对时需及时知道当时的硬件配置状况而利用寄存器模型的镜像值可实现实时读取不需要从前门访问。寄存器模型不但可以用来检查硬件寄存器也可用来配合scoreboard实时检查DUT的功能。
七、检查寄存器的方式
从前门写并且从前门读。这种方式最为常见但是无法检查地址是否正确映射。而前门与后门混合操作的方式可以保证地址的映射检查。从前门写再从后门读。利用write()实现前门写再用read()或peek()从后门读。从后门写再从前门读。利用write()或poke()实现后门写再用read()从前门读。对一些状态寄存器(硬件自身信号会驱动更新其实际值)先用peek()获取(并且会调用predict()方法更新镜像值)再调用mirror()方法从前门访问并且与之前更新的镜像值比较。
八、覆盖率收集
在验证前期可以不例化covergroup保证更好的资源利用在验证后期需采集功能覆盖率时再考虑例化、使能采样。
read/write函数会自动调用回调函数sample进行自动采样数据。sample又会调用sample_values函数再去调用covergroupsample_values函数是供外部调用的函数在发生特定事件的触发时如中断、复位等可以在外部通过监听具体事件来调用该方法采样的时候会采集所有的域的值但有些是没用的。希望可以采用自定义的形式限定感兴趣的域和采样事件。
class ctrl_reg extends uvm_reg;uvm_object_utils(ctrl_reg)uvm_reg_field reserved;rand uvm_reg_field pkt_len;rand uvm_reg_field prio_level;rand uvm_reg_field chnl_en;covergroup value_cg;option.per_instance 1;reserved: coverpoint reserved.value[25:0];pkt_len: coverpoint pkt_len.value[2:0];prio_level: coverpoint prio_level.value[1:0];chnl_en: coverpoint chnl_en.value[0:0];endgroupfunction new(string namectrl_reg);super.new(name, 32, UVM_CVR_ALL); //包含所有的覆盖率类型set_coverage(UVM_CVR_FIELD_VALS);if(has_coverage(UVM_CVR_FIELD_VALS)) begin //是否具备对应的covergroup有就例化groupvalue_cg new();endendfunctionvirtual function build();reserved uvm_reg_field::type_id::create(reserved);pkt_len uvm_reg_field::type_id::create(pkt_len);prio_level uvm_reg_field::type_id::create(prio_level);chnl_en uvm_reg_field::type_id::create(chnl_en);reserved.configure(this, 26, 6, RO, 0, 26h0, 1, 0, 0);pkt_len.configure(this, 3, 3, RW, 0, 3h0, 1, 1, 0);prio_level.configure(this, 2, 1, RW, 0, 2h3, 1, 1, 0);chnl_en.configure(this, 1, 0, RW, 0, 1h0, 1, 1, 0);endfunctionfunction void sample(uvm_reg_data_t data,uvm_reg_data_t byte_en,bit is_read,uvm_reg_map map);super.sample(data, byte_en, is_read, map);sample_values();endfunctionfunction void sample_values();super.sample_values();if(get_coverage(UVM_CVR_FIELD_VALS)) begin //是否允许使用对应的covergroup进行采样value_cg.sample();endendfunction
endclass