当前位置: 首页 > news >正文

带地板翻转的网站怎么做免费网页空间到哪申请

带地板翻转的网站怎么做,免费网页空间到哪申请,建设时时彩网站怎么建设,唐山建设网站网站目录寄存器模型的高级用法*使用reg_predictor*使用UVM_PREDICT_DIRECT功能与mirror操作*寄存器模型的随机化与update扩展位宽寄存器模型的其他常用函数get_root_blocksget_reg_by_offset函数寄存器模型的高级用法 *使用reg_predictor 前面读操作的返回值介绍了左图的方式&…

目录

  • 寄存器模型的高级用法
    • *使用reg_predictor
    • *使用UVM_PREDICT_DIRECT功能与mirror操作
    • *寄存器模型的随机化与update
    • 扩展位宽
  • 寄存器模型的其他常用函数
    • get_root_blocks
    • get_reg_by_offset函数


寄存器模型的高级用法

*使用reg_predictor

前面读操作的返回值介绍了左图的方式,这种方式要依赖于driver。当driver将读取值返回后,寄存器模型会更新寄存器的镜像值和期望值,这是寄存器模型的auto predict功能。在建立寄存器模型时使用如下语句打开此功能:rm.default_map.set_auto_predict(1);

除了左图使用driver的返回值更新寄存器模型外,还存在另一种形式如右图所示。这种形式是由monitor将从总线上收集到的transaction交给寄存器模型,后者更新相应寄存器的值
在这里插入图片描述
要使用这种方式更新数据,需要实例化一个reg_predictor,并为这个reg_predictor实例化一个adapter

class base_test extends uvm_test;…reg_model rm;my_adapter reg_sqr_adapter;my_adapter mon_reg_adapter;uvm_reg_predictor#(bus_transaction) reg_predictor;…
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); //noticeenv.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);rm.default_map.set_auto_predict(1); //noticereg_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和寄存器模型关联在一起

当总线上**只有一个主设备(master)**时,左图和右图完全等价有多个主设备时左图会漏掉某些trasaction

经过上面代码的设置,事实上存在两条更新寄存器模型的路径:一是上面右图虚线所示的自动预测途径,二是经由predictor的途径。如果要彻底关掉虚线的更新路径:rm.default_map.set_auto_predict(0);

*使用UVM_PREDICT_DIRECT功能与mirror操作

UVM提供mirror操作用于读取DUT中寄存器的值并将它们更新到寄存器模型中。它的函数原型为:

task uvm_reg::mirror(output uvm_status_e status,input uvm_check_e check = UVM_NO_CHECK,input uvm_path_e path = UVM_DEFAULT_PATH,);

它常用的参数只有前三个。其中第二个参数指的是如果发现DUT中寄存器的值与寄存器模型中的镜像值不一致,那么在更新寄存器模型之前是否给出错误提示。其可选的值为UVM_CHECK和UVM_NO_CHECK

它有两种应用场景,一是在仿真中不断地调用它,使整个寄存器模型的值与DUT中寄存器的值保持一致,此时check选项是关闭的。二是在仿真即将结束时检查DUT中寄存器的值与寄存器模型中寄存器的镜像值是否一致,这种情况下check选项是打开的。

mirror操作会更新期望值和镜像值。同update操作类似,mirror操作可以在uvm_reg级别和uvm_reg_block级别被调用。当调用一个uvm_reg_block的mirror时,其实质是调用加入其中的所有寄存器的mirror。

前文说过在通信系统中存在大量的计数器。当网络出现异常时借助这些计数器能够快速找出问题所在,所以必须要保证这些计数器的正确性。一般会在仿真即将结束时使用mirror操作检查这些计数器的值是否与预期值一致。

在DUT中的计数器是不断累加的,但寄存器模型中的计数器则保持静止。参考模型会不断统计收到了多少包,那么怎么将这些统计数据传递给寄存器模型呢?

前文中介绍的所有操作都无法完成这个事情,无论是set还是write,或是poke;无论是后门访问还是前门访问。这个问题的实质是想人为地更新镜像值,但同时又不要对DUT进行任何操作

UVM提供predict操作来实现这样的功能

function bit uvm_reg::predict (uvm_reg_data_t value,uvm_reg_byte_en_t be = -1,uvm_predict_e kind = UVM_PREDICT_DIRECT,uvm_path_e path = UVM_FRONTDOOR,);

其中第一个参数表示要预测的值,第二个参数是byte_en,默认-1的意思是全部有效,第三个参数是预测的类型,第四个参数是后门访问或者是前门访问。第三个参数预测类型有如下几种可以选择:

typedef enum {UVM_PREDICT_DIRECT,UVM_PREDICT_READ,UVM_PREDICT_WRITE
} uvm_predict_e;

read/peek和write/poke操作在对DUT完成读写后也会调用此函数,只是给出的参数是UVM_PREDICT_READ和UVM_PREDICT_WRITE

要实现在参考模型中更新寄存器模型而又不影响DUT的值,需要使用UVM_PREDICT_DIRECT,即默认值:

task my_model::main_phase(uvm_phase phase);…p_rm.invert.read(status, value, UVM_FRONTDOOR);while(1) beginport.get(tr);if(value)invert_tr(new_tr);counter = p_rm.counter.get();length = new_tr.pload.size() + 18;counter = counter + length;p_rm.counter.predict(counter); //noticeap.write(new_tr);end
endtask

在my_model中每得到一个新的transaction,就先从寄存器模型中得到counter的期望值(此时与镜像值一致),之后将新的transaction的长度加到counter中,最后使用predict函数将新的counter值更新到寄存器模型中predict操作会更新镜像值和期望值

在测试用例中,仿真完成后可以检查DUT中counter的值是否与寄存器模型中的counter值一致

class case0_vseq extends uvm_sequence;…virtual task body();…dseq = case0_sequence::type_id::create("dseq");dseq.start(p_sequencer.p_my_sqr);#100000;p_sequencer.p_rm.counter.mirror(status, UVM_CHECK, UVM_FRONTDOOR); //注意是check模式…endtask
endclass

*寄存器模型的随机化与update

前文在向uvm_reg中加入uvm_reg_field时,是将加入的uvm_reg_field定义为rand类型:

class reg_invert extends uvm_reg;rand uvm_reg_field reg_data;… 
endclass

在将uvm_reg加入uvm_reg_block中时,同样定义为rand类型:

class reg_model extends uvm_reg_block;rand reg_invert invert;…
endclass

由此可以判断register_model支持randomize操作。可以在uvm_reg_block级别调用randomize函数,也可以在uvm_reg级别,甚至可以在uvm_reg_field级别调用:

assert(rm.randomize());
assert(rm.invert.randomize());
assert(rm.invert.reg_data.randomize());

但要使某个field能够随机化,只是将其定义为rand类型是不够的。在每个reg_field加入uvm_reg时,要调用其configure函数:

// parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset,
// is_rand, individually accessible
reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);

这个函数的第八个参数决定此field是否会在randomize时被随机化。但即使此参数为1,也不一定能够保证此field被随机化。当一个field的类型中没有写操作时,此参数设置是无效的。即此参数只在此field类型为RW、WRC、WRS、WO、W1、WO1时才有效。

因此要避免一个field被随机化,可以在以下三种方式中任选其一:

  1. 当在uvm_reg中定义此field时,不要设置为rand类型
  2. 在调用此field的configure函数时,第八个参数设置为0
  3. 设置此field的类型为RO、RC、RS、WC、WS、W1C、W1S、W1T、W0C、W0S、W0T、W1SRC、W1CRS、W0SRC、W0CRS、WSRC、WCRS、WOC、WOS中的一种(没有写操作)。

其中第一种方式也适用于关闭某个uvm_reg或者某个uvm_reg_block的randomize功能

既然存在randomize,那么也可以为它们定义constraint

class reg_invert extends uvm_reg;rand uvm_reg_field reg_data;constraint cons{reg_data.value == 0;}
…
endclass

在施加约束时,要深入reg_field的value变量。

randomize会更新寄存器模型中的预期值

function void uvm_reg_field::post_randomize();m_desired = value;
endfunction: post_randomize

与set函数类似。因此,可以在randomize完成后调用update任务将随机化后的参数更新到DUT中。这特别适用于在仿真开始时随机化并配置参数

扩展位宽

在reg_invert的new函数中,调用super.new时的第二个参数是16,这个数字一般表示系统总线的宽度,它可以是32、64、128等。

class reg_invert extends uvm_reg;rand uvm_reg_field reg_data;virtual function void build();reg_data = uvm_reg_field::type_id::create("reg_data");// parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, indireg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);endfunction`uvm_object_utils(reg_invert)function new(input string name="reg_invert");//parameter: name, size, has_coveragesuper.new(name, 16, UVM_NO_COVERAGE);endfunction
endclass

但在寄存器模型中,这个数字的默认最大值是64,它是通过一个宏来控制的:

`ifndef UVM_REG_DATA_WIDTH`define UVM_REG_DATA_WIDTH 64
`endif

如果想要扩展系统总线的位宽,可通过重新定义这个宏来扩展

与数据位宽相似的是地址位宽也有默认最大值限制,其默认值也是64:

`ifndef UVM_REG_ADDR_WIDTH`define UVM_REG_ADDR_WIDTH 64
`endif

在默认情况下,字选择信号的位宽等于数据位宽除以8,它通过如下的宏来控制:

ifndef UVM_REG_BYTENABLE_WIDTH`define UVM_REG_BYTENABLE_WIDTH ((`UVM_REG_DATA_WIDTH-1)/8+1) //notice
`endif

如果想要使用其他值,也可以重新定义这个宏。

寄存器模型的其他常用函数

get_root_blocks

在以前例子中,若某处要使用寄存器模型,则必须将寄存器模型的指针传递过去,如在virtual sequence中使用,需要传递给virtual sequencer:

function void base_test::connect_phase(uvm_phase phase);…v_sqr.p_rm = this.rm;
endfunction

UVM还提供其他函数,使得可以在不使用指针传递的情况下得到寄存器模型的指针

function void uvm_reg_block::get_root_blocks(ref uvm_reg_block blks[$]);

get_root_blocks函数得到验证平台上所有的根块(root block——最顶层的reg_block)。其使用示例如下:

class case0_cfg_vseq extends uvm_sequence;…virtual task body();uvm_status_e status;uvm_reg_data_t value;bit[31:0] counter;uvm_reg_block blks[$];reg_model p_rm;…uvm_reg_block::get_root_blocks(blks);if(blks.size() == 0)`uvm_fatal("case0_cfg_vseq", "can't find root blocks")else beginif(!$cast(p_rm, blks[0]))`uvm_fatal("case0_cfg_vseq", "can't cast to reg_model")endp_rm.invert.read(status, value, UVM_FRONTDOOR); //notice…endtask
endclass

在使用get_root_blocks函数得到reg_block的指针后,要使用cast将其转化为目标reg_block形式( 示例中为reg_model)。以后就可以直接使用p_rm来进行寄存器操作,而不必使用p_sequencer.p_rm。

get_reg_by_offset函数

建立寄存器模型后,可直接通过层次引用的方式访问寄存器:rm.invert.read(…);

但出于某些原因依然要使用地址来访问寄存器模型,可使用get_reg_by_offset函数通过寄存器的地址得到一个uvm_reg的指针,再调用此uvm_reg的read或者write就可以进行读写操作

virtual task read_reg(input bit[15:0] addr, output bit[15:0] value);uvm_status_e status;uvm_reg target;uvm_reg_data_t data;uvm_reg_addr_t addrs[];target = p_sequencer.p_rm.default_map.get_reg_by_offset(addr); //noticeif(target == null)`uvm_error("case0_cfg_vseq", $sformatf("can't find reg in register model with address: 'h%target.read(status, data, UVM_FRONTDOOR);void'(target.get_addresses(null,addrs));if(addrs.size() == 1)
39		value = data[15:0];else begin
41		int index;
42		for(int i = 0; i < addrs.size(); i++) begin
43			if(addrs[i] == addr) begin
44				data = data >> (16*(addrs.size() - i));
45				value = data[15:0];
46				break;
47			end
48		endend
endtask

通过调用最顶层的reg_block的get_reg_by_offset可以得到任一寄存器的指针。如果使用层次的寄存器模型,从最顶层的reg_block的get_reg_by_offset也可以得到子reg_block中的寄存器

假如buf_blk的地址偏移是’h1000,其中有偏移为’h3的寄存器(即其物理地址是’h1003),那么可以直接由p_rm.get_reg_by_offset('h1003)得到此寄存器,而不必使用p_rm.buf_blk.get_reg_by_offset('h3)。

如果没有使用多地址寄存器则情况比较简单,上述代码会运行第39行。当存在多个地址时,通过get_addresses函数可以得到这个函数的所有地址,其返回值是一个动态数组addrs。无论是大端还是小端,addrs[0]是LSB对应的地址。第41到48行通过比较addrs中的地址与目标地址,最终得到要访问的数据。

写寄存器与读操作类似。

http://www.lbrq.cn/news/2445157.html

相关文章:

  • 自媒体网站建设要求seo站外优化平台
  • 手机网站建设哪家便宜网站建设策划书范文
  • 下班后做兼职任务网站站长工具流量统计
  • 网站建设wap客户引流的最快方法是什么
  • 昆明优化网站公司seo需要掌握哪些技术
  • 璧山集团网站建设如何注册一个平台
  • 仙桃市住房建设局网站竞价推广是什么意思
  • 想做个赚钱的网站不知道做那种山东seo百度推广
  • 创新的网站建站长沙营销型网站建设
  • 教做发绳的网站谷歌搜索引擎入口2022
  • 结合七牛云 做视频网站怎么做网站关键词优化
  • 网络技术与网站建设友情链接交换要注意哪些问题
  • 晋州网站建设公司网站设计
  • 网站备案服务产品推广策划书
  • 莘庄做网站直播营销
  • 宁德营销型网站建设网络营销的推广方法有哪些
  • 保定网站建设服务平台给我免费的视频在线观看
  • 凡科网站免费注册自己有产品怎么网络销售
  • 做淘宝客需要企业网站吗广告公司接单软件
  • seo整站优化外包公司论坛seo招聘
  • 企业网站建设合同电子版网络推广优化是干啥的
  • 莞城网站制作google引擎免费入口
  • 开发电商网站百度官方下载
  • 网站建设网站定制最佳的搜索引擎
  • 网站空间容量免费发帖推广网站
  • 支付网站招聘费分录怎么做搜狗seo
  • 做随车吊网站要多大长沙seo运营
  • 做集团网站一年多少钱好看的友情链接代码
  • 如何用魔方网表做门户网站网络优化培训
  • wordpress文章自动排版seo是什么职位
  • kafka的消费者负载均衡机制
  • 【Redis】Linux 配置Redis
  • 两个USB-CAN-A收发测试
  • 扒网站工具 HTTrack Website Copier
  • 锁相环技术简介(面向储能变流器应用)
  • Sklearn 机器学习 数值指标 均方误差MSE