[UVM源代码研究] sequence、 sequencer与driver的通信(uvm-1.2版)_sequence访问driver变量-程序员宅基地

技术标签: UVM源代码研究  经验分享  源代码管理  

[UVM源代码研究] sequence、 sequencer与driver的通信(uvm-1.2版)

driver与sequencer间的基本连接与通信

driver与sequencer之间的通信,我们最常用的最基本的方法就是

  1. driver中的seq_item_port在agent中connect到了sequencer中的seq_item_export
  2. driver中的seq_item_port通过调用get_next_item任务来从sequencer上获取transaction

于是我们产生如下几个问题:

  • sequencer上的transaction从何处而来?
  • get_next_item这个任务如何实现数据的传递?
  • seq_item_port和seq_item_export分别是什么样的端口类型?

带着以上几个疑问我们看看uvm源代码中都是如何实现的。

get_next_item

src/seq/uvm_sequencer.svh中的源代码

在这里插入图片描述

src/comps/uvm_driver.svh中的源代码

在这里插入图片描述

经过TLM的学习我们知道在TLM通信中存在以下几个概念:

  1. initiator(调用通信方法)和target(实现通信方法)
  2. producer(产生数据)和consumer(使用数据)

由此我们得出如下结论:

  1. driver这里充当的是一个initiator和consumer的作用,发起get_next_item()的通信方法并获取数据,因而我们知道get_next_item()一定是在充当target的sequencer中实现的,并且数据也是在sequencer中产生。
  2. driver中seq_item_port是一个port类型,而sequencer中的seq_item_export是一个imp类型
    自定义的driver和sequencer中构造函数new中调用super.new()可以分别完成seq_item_port好seq_item_export的创建。

get_next_item_called

src/seq/uvm_sequencer.svh中的源代码

在这里插入图片描述

get_next_item这个的task里使用了get_next_item_called这个变量,212-214行显示调用get_next_item的时候get_next_item_called一定为0,否则会报错。调用完get_next_item后需要将get_next_item_called赋值为1。

我们再看看uvm_sequencer里还有哪些地方对get_next_item_called进行了赋值。

分别在item_done和stop_sequences这两个函数中对get_next_item_called做了赋0的操作,由此我们不难得出如下结论:driver执行get_next_item获取数据的时候,如果前一次get_next_item获取数据后driver中没有执行item_done或者sequencer没有调用stop_sequences来强制kill掉上面运行的所有transaction/sequence,那么sequencer中会报错。即通过get_next_item_called这样一个变量实现了driver一次只能从sequencer获取一个数据进行处理。

sequence_item_requeated

src/seq/uvm_sequencer_base.svh中的源代码

在这里插入图片描述

与get_next_item_called同时出现的另一个变量sequence_item_requeated起到一个等待sequencer授权sequence的作用。

sequence_item_requeated清零的位置与get_next_item_called一样,也是在item_done和stop_sequences中完成的,也就是正常情况下执行到get_next_item里的216行判断语句的时候sequence_item_requeated通常为0,会调用m_select_sequence,这个task是在uvm_sequencer的父类uvm_sequencer_base中实现的。

716-722行代码实现了等待被仲裁授权的sequence。

724-728授权上面等到的sequence(通过sequence对应的id标识arb_completed数组来实现授权)。
等待sequence授权的过程是get_next_item阻塞的原因所在。

get_next_item第221-222行实现了对get_next_item_called、sequence_item_requeated赋值为1,表明此时sequencer中有一个数据正在发送给driver处理,如果在item_done或者stop_sequences之前driver又通过get_next_item发起一个获取数据的请求,212和216行的判断会执行报错和不进行sequence的仲裁选择行为。

get_next_item第223行从m_req_fifo中用peek获取一个数据输出给driver。(注意这里用到的是peek而不是pop,也就是fifo中的数据仍然保留并没有彻底取出,后面会介绍原因。)

item_done

src/seq/uvm_sequencer.svh中的源代码

在这里插入图片描述

src/seq/uvm_sequencer_base.svh中的源代码
在这里插入图片描述

关于item_done,首先需要说明的就是这是一个函数,并不会消耗时间,driver中调用item_done表明通过get_next_item获取的transaction已经drive到interface完成了协议转换,可以接收下一笔数据了。

所以这里281-282行将前面介绍的这两个变量清零了。

284行就解答了我们前面关于get_next_item里为什么调用try_peek来从fifo中获取数据的问题:get_next_item只是表示driver获取了数据,但是数据什么时候被消耗完成是由item_done决定的,所以fifo中的数据只有在item_done的时候才能pop出来。

使用try_get函数同时增加了判断,如果此时取不出数据则报错。

288-289行这两个变量作用就是当sequence调用sequencer中的wait_for_item_done的时候,能够将item_done匹配到对应的sequene的某个特定transaction,正如我们在driver中如果使用rsp,需要调用rsp.set_id_info来将req和rsp通过id关联起来一样。

292-294行作用就是当item_done参数不为空时,就执行put_response()将item_done的参数作为rsp发出。

297行的作用就是授权给那些在等待授权队列里靠前位置调用了lock或者grab的sequence。

sequence与sequencer之间的通信

src/seq/uvm_sequencer_param_base.svh中的源代码

在这里插入图片描述

src/seq/uvm_sequence_base.svh中的源代码

在这里插入图片描述

sequencer中获取的数据存放在m_req_fifo这样一个uvm_tlm_fifo中。

关于这个fifo定义以及添加数据是在uvm_sequencer_param_base类中实现的,它派生自uvm_sequencer_base,而uvm_sequencer又是从它派生而来的。该类中还定义了另一个我们常用到的函数put_response(),后面我们会讲。

这里的send_request函数是在uvm_sequence_base(uvm_sequence的父类)调用的,这样就实现了在uvm_sequence的派生类中调finish_item(通常用uvm_do宏包裹)将数据发送到sequencer并存放在m_req_fifo中。

使用try_put()函数是为了进行判断fifo是否溢出,溢出则报错。

如此我们便清楚了sequence与sequencer之间数据传输的通路实现。

start_item

src/seq/uvm_sequence_base.svh中的源代码

在这里插入图片描述

finish_item实现将sequence中的数据发送到sequencer,而与之通常配对的start_item里都做了什么呢?它又是与sequencer做了哪些交互?

默认是用的是m_sequencer,即sequence启动时指定的sequencer。

这里主要执行操作就是994行等待sequencer的授权。

put_response

src/seq/uvm_sequencer_param_base.svh中的源代码

在这里插入图片描述

src/seq/uvm_sequence_base.svh中的源代码

在这里插入图片描述

从uvm_sequencer_param_base中put_response的实现我们发现,328行获取了通过rsp调用get_sequence_id获取了在该sequencer运行的对应的sequence的句柄,337行调用了对应sequence中的put_response函数并将该rsp压入了该sequence实例中的队列response_queue中,队列的默认允许深度是8。
进而在sequence中调用get_response才能获取到之前被压入的rsp数据。

这就是rsp从driver到sequencer再到sequence的数据通路,其实不难看出sequencer在这里只是起到了个调用函数的中介作用,甚至没有将rsp临时存放起来。

sequence、sequencer与driver数据通信图示

实现通过以上分析,我们对sequence、sequencer与driver数据的传递相关函数调用等总结为如下图示:
在这里插入图片描述

总结

本文通过分析UVM源代码中uvm_sequence、uvm_sequencer、uvm_driver中的相关代码实现,讲述了sequence中发包经sequencer、driver再到发包完整整个包的传递流程,相应经过本文的分析解释读者对UVM中transaction的传递会有更深的认识。

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

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签