【转载】【UVM】目前看到的关于uvm regmodel访问方法最详尽的介绍
注明:本文转自UVM Tutorial for Candy Lovers – 16. Register Access Methods
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”(读/写),以使该字段更通用。
-
flavor = uvm_reg_field::type_id::create( "flavor" ); -
flavor.configure( .parent ( this ), -
.size ( 3 ), -
.lsb_pos ( 0 ), -
.access ( "RW" ), -
.volatile ( 0 ), -
.reset ( 0 ), -
.has_reset ( 1 ), -
.is_rand ( 1 ), -
.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属性的值。
-
uvm_reg_data_t desired_value = flavor.get(); -
uvm_reg_data_t reset_value = flavor.get_reset( .kind( "HARD" ) ); // kind == "HARD" by default -
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写入一个值。
-
uvm_status_e status; -
flavor.write( .status( status ), .value( 1 ) );
write()方法涉及多个步骤。
- 创建与写入操作对应的uvm_reg_item对象。
- uvm_reg_adapter将写入操作转换为相应的总线事务。
- uvm_driver执行到DUT的总线事务。
- uvm_monitor捕获总线事务。
- uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。
- 寄存器操作转换为uvm_reg_item。
- uvm_reg_item用于更新值,m_mirrored和m_desired属性。
请注意,如果在配置寄存器字段时个别可访问参数为0,则包含该字段的整个寄存器会被写入,因为该字段不可单独访问。在这种情况下,m_mirrored值将用作其他字段的写入值。
write()方法如何工作
read()
read()方法实际上从DUT中读取一个寄存器值。
-
uvm_status_e status; -
uvm_reg_data_t value; -
flavor.read( .status( status ), .value( value ) );
与write()方法类似,read()方法涉及多个步骤。
- 创建与读操作对应的uvm_reg_item对象。
- uvm_reg_adapter将读取操作转换为相应的总线事务。
- uvm_driver执行到DUT的总线事务。
- uvm_reg_apapter将读取数据的总线事务转换为寄存器操作。
- read()方法将读取值返回给调用者。
- 同时,uvm_monitor捕获总线事务。
- uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。
- 寄存器操作转换为uvm_reg_item。
- uvm_reg_item用于更新值,m_mirrored和m_desired属性。
请注意,如果在配置寄存器字段时individually_accessible 参数为0,则会读取包含字段的整个寄存器。在这种情况下,也会为其他字段更新m_mirrored值。
read()方法如何工作
update()
update()方法实际上是向DUT写入一个寄存器值。 update()方法属于uvm_reg类。 uvm_reg_field类没有update()方法。
-
uvm_status_e status; -
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读取一个寄存器。
-
uvm_status_e status; -
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 |
value |
m_desired |
m_mirrored |
DUT |
|---|---|---|---|---|---|
configure |
set the value of val |
||||
set_reset(val) |
set the value of val |
||||
reset() |
copy the value of m_reset |
copy the value of m_reset |
copy the value of m_reset |
||
set(val) |
set the value of val |
set the value of val |
|||
get_reset() |
return the value of m_reset |
||||
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 |
set the value of val |
set the value of val |
set the value of val |
在这篇文章中,我们只介绍了所谓的前门访问。我们将在单独的帖子中介绍后门访问。我希望本教程能帮助您理解寄存器的访问方法。
原文中有一些QA可以加深理解。
智能推荐
嵌入式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,按照我得写,如...
