uvm中transaction的response和id的解读
在公司写代码的时候发现前辈有一段这样的代码:
....//其他transaction
`uvm_create(trans);........
`uvm_send(trans);
tmp_id = trans.get_transaction_id();
get_response(rsp,tmp_id);
如果前面有其他transaction,这段代码里的get_response不带id的话,就会错误地get到前面transaction的response,有点好奇原理,就去看了看源码。
先从driver入手,如果要返回response的话,要先new一个rsp,然后set_id_info,再put_response:
//参考张强白皮书
seq_item_port.get_next_item(req);
drive_one_pkt(req);
rsp = new("rsp");
rsp.set_id_info(req);
seq_item_port.put_response(rsp);
seq_item_port.item_done();
先看set_id_info这个函数,在uvm_sequence_item.svh里面,作用就是将req的两个id set到rsp里,我们主要关注transaction_id,继续往后走。
function void set_id_info(uvm_sequence_item item);if (item == null) beginuvm_report_fatal(get_full_name(), "set_id_info called with null parameter", UVM_NONE);endthis.set_transaction_id(item.get_transaction_id());this.set_sequence_id(item.get_sequence_id());endfunction
get_transaction_id在uvm_transaction.svh里面,返回了m_transaction_id,这个id是uvm_transaction里面的一个local integer变量,默认值为-1。这个id的更改在其他地方,稍后再讲解。
function void uvm_transaction::set_transaction_id(integer id);m_transaction_id = id;
endfunctionfunction integer uvm_transaction::get_transaction_id();return (m_transaction_id);
endfunction
然后看put_response函数,在uvm_sequence.svh里,调用了put_base_response函数。
virtual function void put_response(uvm_sequence_item response_item);RSP response;if (!$cast(response, response_item)) beginuvm_report_fatal("PUTRSP", "Failure to cast response in put_response", UVM_NONE);endput_base_response(response_item);endfunction
put_base_response在uvm_sequence_base.svh里,作用是将response压入队列中,队列默认长度为8,即response_queue_depth=8,当response在队列中的数量为8还继续压入队列后就会报错,一般发生在没有取response的情况下。
virtual function void put_base_response(input uvm_sequence_item response);if ((response_queue_depth == -1) ||(response_queue.size() < response_queue_depth)) beginresponse_queue.push_back(response);return;endif (response_queue_error_report_disabled == 0) beginuvm_report_error(get_full_name(), "Response queue overflow, response was dropped", UVM_NONE);endendfunction
接下来到sequence端,我们看看transaction的id和response是怎么get的。transaction_id,在uvm_transaction.svh里,就是返回m_transaction_id。get_response在uvm_sequence.svh里,调用了get_base_response,这里的参数列表里就有transaction_id了。
virtual task get_response(output RSP response, input int transaction_id = -1);uvm_sequence_item rsp;get_base_response( rsp, transaction_id);$cast(response,rsp);endtask
get_base_response在uvm_sequence_base.svh里,可以看到在没有指定transaction_id(id为默认值)的时候,返回的response是从队列直接pop的,指定了以后就遍历队列找id对应的response,这里就是最前面代码的机制。
virtual task get_base_response(output uvm_sequence_item response, input int transaction_id = -1);int queue_size, i;if (response_queue.size() == 0)wait (response_queue.size() != 0);if (transaction_id == -1) beginresponse = response_queue.pop_front();return;endforever beginqueue_size = response_queue.size();for (i = 0; i < queue_size; i++) beginif (response_queue[i].get_transaction_id() == transaction_id) begin$cast(response,response_queue[i]);response_queue.delete(i);return;endendwait (response_queue.size() != queue_size);endendtask
但是到目前为止,response阶段没有看到id是怎么来的,我们从transaction的create和send阶段找一下。这些宏在uvm_sequence_defines.svh里,可以看到create阶段不涉及id的操作,send里面调了函数,可能会有。因为我们send的是transaction,是uvm_sequence_item类型,uvm_sequence_base是其子类,所以在uvm_send_pri里case不会成功,首先进入start_item里。
`define uvm_create(SEQ_OR_ITEM) \`uvm_create_on(SEQ_OR_ITEM, m_sequencer)`define uvm_create_on(SEQ_OR_ITEM, SEQR) \begin \uvm_object_wrapper w_; \w_ = SEQ_OR_ITEM.get_type(); \$cast(SEQ_OR_ITEM , create_item(w_, SEQR, `"SEQ_OR_ITEM`"));\end`define uvm_send(SEQ_OR_ITEM) \`uvm_send_pri(SEQ_OR_ITEM, -1)`define uvm_send_pri(SEQ_OR_ITEM, PRIORITY) \begin \uvm_sequence_base __seq; \if (!$cast(__seq,SEQ_OR_ITEM)) begin \start_item(SEQ_OR_ITEM, PRIORITY);\finish_item(SEQ_OR_ITEM, PRIORITY);\end \else __seq.start(__seq.get_sequencer(), this, PRIORITY, 0);\end
start_item在uvm_sequence_base.svh里,貌似也不涉及id的操作,再看finish_item,也在vm_sequence_base.svh里。finish_item调用了sequencer的send_request函数,进去看看。
virtual task start_item (uvm_sequence_item item,int set_priority = -1,uvm_sequencer_base sequencer=null);uvm_sequence_base seq;if(item == null) beginuvm_report_fatal("NULLITM",{"attempting to start a null item from sequence '",get_full_name(), "'"}, UVM_NONE);return;endif($cast(seq, item)) beginuvm_report_fatal("SEQNOTITM",{"attempting to start a sequence using start_item() from sequence '",get_full_name(), "'. Use seq.start() instead."}, UVM_NONE);return;endif (sequencer == null)sequencer = item.get_sequencer();if(sequencer == null)sequencer = get_sequencer(); if(sequencer == null) beginuvm_report_fatal("SEQ",{"neither the item's sequencer nor dedicated sequencer has been supplied to start item in ",get_full_name()},UVM_NONE);return;enditem.set_item_context(this, sequencer);if (set_priority < 0)set_priority = get_priority();sequencer.wait_for_grant(this, set_priority);`ifndef UVM_DISABLE_AUTO_ITEM_RECORDINGvoid'(sequencer.begin_child_tr(item, m_tr_handle, item.get_root_sequence_name()));`endifpre_do(1);endtask virtual task finish_item (uvm_sequence_item item,int set_priority = -1);uvm_sequencer_base sequencer;sequencer = item.get_sequencer();if (sequencer == null) beginuvm_report_fatal("STRITM", "sequence_item has null sequencer", UVM_NONE);endmid_do(item);sequencer.send_request(this, item);sequencer.wait_for_item_done(this, -1);`ifndef UVM_DISABLE_AUTO_ITEM_RECORDINGsequencer.end_tr(item);`endifpost_do(item);endtask
send_request在uvm_sequencer_param_base里,可以看到req的transaction_id就是在这里设置的,值为m_next_transaction_id,且每次设置完就自加1,这个值在uvm_sequence_base.svh里,初值为1。
function void uvm_sequencer_param_base::send_request(uvm_sequence_base sequence_ptr,uvm_sequence_item t,bit rerandomize = 0);REQ param_t;if (sequence_ptr == null) beginuvm_report_fatal("SNDREQ", "Send request sequence_ptr is null", UVM_NONE);endif (sequence_ptr.m_wait_for_grant_semaphore < 1) beginuvm_report_fatal("SNDREQ", "Send request called without wait_for_grant", UVM_NONE);endsequence_ptr.m_wait_for_grant_semaphore--;if ($cast(param_t, t)) beginif (rerandomize == 1) beginif (!param_t.randomize()) beginuvm_report_warning("SQRSNDREQ", "Failed to rerandomize sequence item in send_request");endendif (param_t.get_transaction_id() == -1) beginparam_t.set_transaction_id(sequence_ptr.m_next_transaction_id++);endm_last_req_push_front(param_t);end else beginuvm_report_fatal(get_name(),$sformatf("send_request failed to cast sequence item"), UVM_NONE);endparam_t.set_sequence_id(sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1));t.set_sequencer(this);if (m_req_fifo.try_put(param_t) != 1) beginuvm_report_fatal(get_full_name(), "Concurrent calls to get_next_item() not supported. Consider using a semaphore to ensure that concurrent processes take turns in the driver", UVM_NONE);endm_num_reqs_sent++;// Grant any locks as soon as possiblegrant_queued_locks();
endfunction
这下搞清楚了,transaction_id初值为1,且一个sequence里面每个transaction_id的值均不相同,每发一个req,id都会加一,通过这个id可以来区分不同的transaction!
相关文章:
uvm中transaction的response和id的解读
在公司写代码的时候发现前辈有一段这样的代码: ....//其他transaction uvm_create(trans);........ uvm_send(trans); tmp_id trans.get_transaction_id(); get_response(rsp,tmp_id); 如果前面有其他transaction,这段代码里的get_response不带id的话…...
第四节(1):EXCEL中判断一个WORD文件是否被打开
《VBA信息获取与处理》教程(10178984)是我推出第六套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。这部教程给大家讲解的内容有:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互联网…...
java.util.concurrent.locks.Condition详解
Condition翻译成中文是“条件”,一般我们称其为条件变量,每一个Condition对象都通过链表保存了一个队列,我们称之为条件队列。 当然了,这里所说的Condition对象一般指的是Condition接口的实现类ConditionObject,比如我…...
选择适合变更管理的产品开发工具的要点和建议
什么是变更管理? 变更管理是指导组织改进的学科。由于可观察到的行为变化,它会导致永久性变化。它确保您的组织以彻底、有序和可持续的方式学习和改进。成功的改进项目需要个人和团队保持一致,他们有共同的愿景,他们知道如何定义…...
小程序 词云图 echarts-for-weixin-wordcloud
GitHub - clydee-geng/echarts-for-weixin-wordcloud: echarts词云微信小程序版 这个是适配与小程序版的词云图,之前有找到ucharts来代替,但是ucharts的词云图功能有两个缺点:1.无法根据值的大小显示词云图的大小;2.显示的顺序是…...
VScode配置Jupyter
环境 安装步骤 1、插件安装 2、更改pip加速源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 参考:vscode python配置pip源 【Python学习】Day-00 Python安装、VScode安装、pip命令、镜像源配置、虚拟环境 3、建…...
java模拟GPT流式问答
流式请求gpt并且流式推送相关前端页面 1)java流式获取gpt答案 1、读取文件流的方式 使用post请求数据,由于gpt是eventsource的方式返回数据,所以格式是data:,需要手动替换一下值 /** org.apache.http.client.metho…...
【好玩】如何在github主页放一条贪吃蛇
前言 🍊缘由 github放小蛇,就问你烧不烧 起因看到大佬github上有一条贪吃蛇扭来扭去,觉得好玩,遂给大家分享一下本狗的玩蛇历程 🥝成果初展 贪吃蛇 🎯主要目标 实现3大重点 1. github设置主页 2. git…...
顶顶通ASR安装配置说明
联系顶顶通申请Asrproxy授权,勾选asrserver模块。 下载语音识别模型 链接:https://pan.baidu.com/s/1IuDkDeytZOqf7tAbIb6h1Q 提取码:6vg6 安装asrproxy到/ddt/asrproxy,模型解压到 /ddt/asrproxy/model 对接mod_vad asrproxy.json 配置如…...
VMware和别的服务器 ,组建局域网那些事 。
利用VMware ,实现组件局域网、有可能会受限于WiFi(路由器) 。 通常不会,除非做了网关设置 相关知识: 禁用局域网隔离(LAN Isolation): 某些路由器提供了一个选项,允许您禁…...
自监督DINO论文笔记
论文名称:Emerging Properties in Self-Supervised Vision Transformers 发表时间:CVPR2021 作者及组织: Facebook AI Research GitHub:https://github.com/facebookresearch/dino/tree/main 问题与贡献 作者认为self-supervise…...
计算机视觉: 基于隐式BRDF自编码器的文生三维技术
论文链接: MATLABER: Material-Aware Text-to-3D via LAtent BRDF auto-EncodeR 背景 得益扩散模型和大量的text - image 成对的图片, 现在文生2D的模型已经比较成熟的框架和模型,主流的技术比如说stable diffusion 和 midjourney 以及工业领域runway 等…...
分类预测 | MATLAB实现KOA-CNN-BiLSTM开普勒算法优化卷积双向长短期记忆神经网络数据分类预测
分类预测 | MATLAB实现KOA-CNN-BiLSTM开普勒算法优化卷积双向长短期记忆神经网络数据分类预测 目录 分类预测 | MATLAB实现KOA-CNN-BiLSTM开普勒算法优化卷积双向长短期记忆神经网络数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现KOA-CNN-BiLST…...
Java队列相关面试题
ArrayBlockingQueue 1、ArrayBlockingQueue是什么?它与LinkedList和LinkedBlockingQueue有何区别? ArrayBlockingQueue是一个基于数组的有界阻塞队列,可以在队列的两端进行插入和删除操作。 与LinkedList不同,ArrayBlockingQueu…...
水库大坝除险加固安全监测系统解决方案
一、系统背景 为贯彻落实《办公厅关于切实加强水库除险加固和运行管护工作的通知》(〔2021〕8号)要求,完成“十四五”小型病险水库除险加固、雨水情测报和大坝安全监测设施建设任务,规范项目管理,消除安全隐患…...
android native C++编程实现数据库加密sqlcipher
sqlcipher是sqlite的加版本,分为免费版和收费版。 这里研究的是开源的免费版 https://github.com/sqlcipher/sqlcipher Android码源默认提供了sqlite的native,jni和java版本,但没有提供sqlcipher,开发用到需要自己添加。 sqlc…...
第五节 C++ 循环结构(算法)
文章目录 前言介绍1. for 语句1.1 语法结构1.2 语法流程的执行过程1.2.1 案例 1:循环的正序输入和倒序输入1.2.2 案例2 : 求1~n的平方数1.2.3 案例 3: 求输入a和b,求a~b区间数. 1.3 for 循环案例练习1.3.1 求最大值与最小值1.3.2 计算奇数和和偶数和1.3.3 计算平均气温与最高气…...
接口与抽象类的区别
a、抽象类不能被实例化只能被继承;b、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;c、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;d、一个子类继承一个抽象类,则子类…...
短视频账号矩阵系统源码saas===独立部署
前言: 短视频账号矩阵是指在不同的短视频平台上,一个个人或企业所拥有的账号数量和分布情况。由于不同的短视频平台受众人群和内容类型等因素不同,因此拥有更多账号可以在更广泛的受众中传播内容,提高曝光度和流量。短视频账号矩阵…...
香港专用服务器拥有良好的国际网络连接
香港服务器在多个领域有着广泛的应用。无论是电子商务、金融交易、游戏娱乐还是社交媒体等,香港服务器都能够提供高效稳定的服务。对于跨境电商来说,搭建香港服务器可以更好地满足亚洲用户的购物需求;对于金融机构来说,香港服务器…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
