【转载】【UVM】目前看到的关于uvm regmodel访问方法最详尽的介绍

标签: uvm  访问方法  reg model

注明:本文转自UVM Tutorial for Candy Lovers – 16. Register Access Methods

翻译来自UVM糖果爱好者教程 - 16.寄存器访问方法

 

 

UVM的寄存器抽象层(RAL)提供了几种访问寄存器的方法。 这篇文章将解释寄存器访问方法的工作原理。 在Register Abstraction中,我们介绍了RAL的概述并解释了如何定义寄存器。 在这篇文章中,我们将介绍如何访问寄存器。

uvm_reg_field的属性

在深入了解寄存器访问方法之前,让我们看看如何存储寄存器值。 如寄存器抽象中所示,uvm_reg_field是表示寄存器的位的最低寄存器抽象层。 uvm_reg_field使用多个属性来存储各种寄存器字段值:

  • m_reset [“HARD”]存储硬重置值(hard reset)。 请注意,m_reset是一种带有一种重置键的关联数组。
  • m_mirrored存储我们在待测试设计(DUT)中所认为应该存储的值。
  • m_desired存储我们想要设置给DUT的值。
  • value将要采样的值存储在功能覆盖率中,或者当该字段被随机化时将value约束。

请注意,在这些属性中,只有值属性是公共的。 其他属性是本地的,因此我们无法直接从类外访问它们。 稍后我们将向您介绍如何使用寄存器访问方法访问这些本地属性。

                                                                            uvm_reg_field的属性

configure()

我们在创建uvm_reg_field后执行的第一件事是配置它。在寄存器抽象中,我们如下配置flavor字段。请注意,在Register Abstraction中,我们将flavor字段定义为“WO”(只写),但我们在此将其定义为“RW”(读/写),以使该字段更通用。

 
  1. flavor = uvm_reg_field::type_id::create( "flavor" );

  2. flavor.configure( .parent ( this ),

  3. .size ( 3 ),

  4. .lsb_pos ( 0 ),

  5. .access ( "RW" ),

  6. .volatile ( 0 ),

  7. .reset ( 0 ),

  8. .has_reset ( 1 ),

  9. .is_rand ( 1 ),

  10. .individually_accessible( 0 ) );

如果has_reset参数为1,则复位参数的值将被视为“HARD”复位值。如果has_reset值为0,则复位值将被忽略。复位值应与DUT的复位状态相匹配。如果您想在配置后修改复位值,可以使用set_reset()方法。

flavor.set_reset( .value( 0 ), .kind( "HARD" ) ); // kind == "HARD" by default

                                                    configure()和set_reset()方法如何工作

reset()

如果m_reset [kind]存在,reset()方法将重置寄存器字段的属性。默认类型是“HARD”。如果m_reset [kind]不存在,则reset()方法不执行任何操作。请注意,reset()方法不会复位DUT中的寄存器。它只复位寄存器字段对象的属性。

flavor.reset( .kind( "HARD" ) ); // kind == "HARD" by default

                                                                        reset()方法如何工作

set()

set()方法设置寄存器字段的期望值。 set()方法不会将值设置为DUT中的寄存器的值。它只将值设置为m_desired和寄存器字段对象的值属性。要真正将值设置为DUT中的寄存器,请使用write()或update()方法。这些方法将在稍后解释。

flavor.set( .value( 1 ) );

                                                                        set()方法如何工作

get()

get()方法获取寄存器字段的期望值。 get()方法不会从DUT中的寄存器获取值。它只获取m_desired属性的值。要实际从DUT获取值,请使用read()或mirror()方法。这些方法将在稍后解释。与get()方法类似,还有两个getter访问本地属性。 get_reset()检索m_reset [kind]属性的值,而get_mirrored_value()方法检索m_mirrored属性的值。

 
  1. uvm_reg_data_t desired_value = flavor.get();

  2. uvm_reg_data_t reset_value = flavor.get_reset( .kind( "HARD" ) ); // kind == "HARD" by default

  3. uvm_reg_data_t mirrored_value = flavor.get_mirrored_value();

                                                    get(), get_reset(), and get_mirrored_value()方法如何工作

randomize()

randomize()方法是一个SystemVerilog方法。它随机化一个寄存器字段对象的值属性。随机化后,post_randomize()方法将value属性的值复制到m_desired属性。请注意,如果value属性的rand_mode为OFF,则pre_randomize()方法会将m_desired的值复制到value属性。

assert( flavor.randomize() );

                                                                                         randomize()方法如何工作

write()

write()方法实际上向DUT写入一个值。

 
  1. uvm_status_e status;

  2.  
  3. flavor.write( .status( status ), .value( 1 ) );

write()方法涉及多个步骤。

  1. 创建与写入操作对应的uvm_reg_item对象。
  2. uvm_reg_adapter将写入操作转换为相应的总线事务。
  3. uvm_driver执行到DUT的总线事务。
  4. uvm_monitor捕获总线事务。
  5. uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。
  6. 寄存器操作转换为uvm_reg_item。
  7. uvm_reg_item用于更新值,m_mirrored和m_desired属性。

请注意,如果在配置寄存器字段时个别可访问参数为0,则包含该字段的整个寄存器会被写入,因为该字段不可单独访问。在这种情况下,m_mirrored值将用作其他字段的写入值。

                                                                                 write()方法如何工作

read()

read()方法实际上从DUT中读取一个寄存器值。

 
  1. uvm_status_e status;

  2. uvm_reg_data_t value;

  3.  
  4. flavor.read( .status( status ), .value( value ) );

与write()方法类似,read()方法涉及多个步骤。

  1. 创建与读操作对应的uvm_reg_item对象。
  2. uvm_reg_adapter将读取操作转换为相应的总线事务。
  3. uvm_driver执行到DUT的总线事务。
  4. uvm_reg_apapter将读取数据的总线事务转换为寄存器操作。
  5. read()方法将读取值返回给调用者。
  6. 同时,uvm_monitor捕获总线事务。
  7. uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。
  8. 寄存器操作转换为uvm_reg_item。
  9. uvm_reg_item用于更新值,m_mirrored和m_desired属性。

请注意,如果在配置寄存器字段时individually_accessible 参数为0,则会读取包含字段的整个寄存器。在这种情况下,也会为其他字段更新m_mirrored值。

                                                                                        read()方法如何工作

update()

update()方法实际上是向DUT写入一个寄存器值。 update()方法属于uvm_reg类。 uvm_reg_field类没有update()方法。

 
  1. uvm_status_e status;

  2.  
  3. jb_recipe_reg.update( .status( status ) );

write()方法和update()方法之间的区别是:

  • write()方法将一个值作为其参数,而update()方法使用m_desired属性的值作为要写入的值。
  • 只有当m_mirrored和m_desired不相等时,update()方法才写入该值。

                                                                                        update()方法执行前

update()方法在内部调用write(.value(m_desired))。因此,更新后,m_mirrored的值也会更新。

                                                                                        update()方法执行后

mirror()

mirror()方法实际上是从DUT读取一个寄存器。

 
  1. uvm_status_e status;

  2.  
  3. flavor.mirror( .status( status ), .check( UVM_CHECK ) );

read()方法和mirror()方法之间的区别是:

  • read()方法返回寄存器值给调用者,而mirror()方法不返回寄存器值。 mirror()方法只更新m_mirrored属性的值。
  • 如果check参数的值为UVM_CHECK,则mirror()方法将读取值与m_desired进行比较。请注意,UVM类库文档指出,它将读取值与镜像值进行比较,但如果您查看uvm-1.1c代码库的uvm_reg.svh的第2,944行,它实际上会与所需的值进行比较,而不是针对镜像值。

2014年4月11日:uvm-1.1d代码库已纠正此问题。mirror()将读取值与镜像值进行比较。如果您对此修复感兴趣,请参阅uvm_reg.svh的第2,951行。)

关于检查的另一个警告是,如果在配置寄存器字段时将volatile参数设置为1,则即使将check参数设置为UVM_CHECK,也不会检查寄存器字段。这是因为我们无法确定性地预测寄存器字段的值,因为它可能在DUT中被更改(易失性)。

mirror()方法在内部调用do_read()方法。这是与read()方法内部调用的相同方法。因此,除m_mirrored属性外,mirror()方法还会更新值和m_desired属性。

                                                                                        mirror()如何工作

predict()

predict()方法更新镜像值。

flavor.predict( .value( 1 ) );

predict()方法也会更新值和m_desired属性。

                                                                                            predict()方法如何工作

Summary

下表总结了每种方法如何更新寄存器字段对象的属性。

Method m_reset
["HARD"]
value m_desired m_mirrored DUT
configure
(.reset(val),
.has_reset(1))
set the value of val        
set_reset(val) set the value of val        
reset()   copy the value of m_reset
["HARD"]
copy the value of m_reset
["HARD"]
copy the value of m_reset
["HARD"]
 
set(val)   set the value of val set the value of val    
get_reset() return the value of m_reset
["HARD"]
       
get()     return the value of m_desired    
get_mirrored_value()       return the value of m_mirrored  
randomize()   randomize copy the value of value    
write(.value(val))   set the value of val set the value of val set the value of val write the value of val
read(.value(val))   set the read value set the read value set the read value read the register
update()   set the value of m_desired set the value of m_desired set the value of m_desired write the value of m_desired
mirror()   set the read value set the read value set the read value read the register
predict
(.value(val))
  set the value of val set the value of val set the value of val
 

 

在这篇文章中,我们只介绍了所谓的前门访问。我们将在单独的帖子中介绍后门访问。我希望本教程能帮助您理解寄存器的访问方法。

原文中有一些QA可以加深理解。

版权声明:本文为ytzlln原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ytzlln/article/details/82596997

智能推荐

嵌入式Linux——应用调试:用户态打印段错误信息

简介:     很多时候我们会遇到段错误:segmentation fault,而段错误有时是由内核引起的,有时是由应用程序引起的。在内核态时,发生段错误时会打印oops信息,但是在用户态时,发生段错误却只会打印segmentation fault而并不会打印其他的信息。所以本文主要介绍在用户态时,通过修改内核设置和添加启动参数来打印引发segmentati...

springboot1.4.1整合logback 遇到的问题

springboot1.4.1整合logback 遇到的问题 项目使用了springboot1.4.1整合logback,然而设置的过期时间15 并没有生效, 2GB达到2G自动删除也没有生效,仅仅实现了按大小分割。 经过查看pom 父工程内的源码发现是默认的logback版本是1.1.7,而过期时间配置是在logback 1.1.8以后才支持的。 不得不说这是springboot1.4.1 的b...

记一次C/S架构的渗透测试

概述 目标站点是http://www.example.com,官网提供了api使用文档,但是对其测试后没有发现漏洞,目录、端口扫描等都未发现可利用的点。后发现官网提供了客户端下载,遂对其进行一番测试。 信息收集 先抓了下客户端的包,使用Fiddler和BurpSuite都抓不到,怀疑走的不是HTTP协议,用WireShark查看其确实用的是HTTP协议,但是数据包不好重放,这里最后使用了WSExp...

Linux:结合Securecrt进行文件上传(lrzsz)P2

1、安装rzsz软件   2、点击Scurecrt的option——X/Y/Z配置上传和下载目录   3、首先在Linux里切换到一个目录,然后用rz命令,文件就会上传到钙Linux的目录下   只要敲rz即可,然后在弹出的对话框里选择需要上传的文件即可 4、下载文件用sz   下载单个文件:在当前目录下有该文件     sz filename   下载...

SQL 提示作为 布局 生存工具指南

下面是一些展示AdventureWorks中表现最好的销售人员并列出他们的经理的结构化查询语言代码。 它产生以下结果。 所以,代码是有效的,但它是丑陋的。 如果我需要理解和改进代码,我首先需要把它变成可读的形式。 我有结构化查询语言提示,所以我可以按下计算机的ctrl按键键 踢你自己),它会应用默认的内置代码样式,并对此进行修复。 不,不是,因为我相信你仍然不喜欢它的格式。 没有两个开发人员能够就...

猜你喜欢

Vue+Springboot解决数据传输时参数格式不匹配问题

前端:使用的是ant design vue ,端口号为8000 后端:使用的是springboot框架开发,端口号为8080 需求:已经解决跨域问题,前端发送登录的信息给后台,后台接收不到 样例: 前端: 后台: 请求的数据格式为json格式,后台参数类型不匹配 解决方案 第一种: 修改后端,参数类型: 第二种方式: 在前端vue框架中加入qs插件,qs 是一个增加了一些安全性的查询字符串解析和序...

Flex布局做出自适应页面--语法和案例

本文发布在: github项目地址:https://github.com/tenadolanter/flex-layout-demo SegmentFault地址:https://segmentfault.com/a/1190000012916949/ CSDN地址:http://blog.csdn.net/qq_34648000/article/details/79115294 博客园地址:ht...

Java - 基于 Apache POI 创建 Excel 文件

基于 Apache POI 创建 Excel 文件 准备 新建 Maven Project,引入依赖: 创建行和列 设置列宽 设置列宽(第 19 行): 注意:其他行的首列的宽度是受第一行、第一列的影响而变宽,并非我们设置的。 设置字体颜色 设置字体颜色(第 25 ~ 31 行): 设置网页超链接 设置网页超链接(第 18、27 ~ 29 行): 参考 java操作excel常用的两种方式...

python基础-质数判断及优化

文章目录 一、问题描述 二、代码 三、问题2优化 四、数学补充 一、问题描述 质数判断条件: 质数是只能被1和它自身整除的数,1不是质数也不是合数。 二、代码 问题1代码 问题2代码 三、问题2优化 优化方案: 模块,通过模块可以对Python进行扩展 引入一个time模块,来统计程序执行的时间 time()函数可以用来获取当前的时间,返回的单位是秒 获取程序开始的时间,以运行时间来衡量优化结果。...

部署jenkins+svn持续集成

部署环境:CentOS7+jdk8 svn版本是windows,jenkins是linux 然后下载jenkins的yum源文件,获取jenkins的下载** 输入本机ip+端口,然后在这个web界面显示的路径里把**复制出来,下一步后选择推荐插件安装,后面需要用的插件可以再安装,等待安装完成后,第一次登陆不需要密码,可以设置登陆用户。 然后配置全局设置 如果你是yum安装得git,按照我得写,如...