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===独立部署
前言: 短视频账号矩阵是指在不同的短视频平台上,一个个人或企业所拥有的账号数量和分布情况。由于不同的短视频平台受众人群和内容类型等因素不同,因此拥有更多账号可以在更广泛的受众中传播内容,提高曝光度和流量。短视频账号矩阵…...
香港专用服务器拥有良好的国际网络连接
香港服务器在多个领域有着广泛的应用。无论是电子商务、金融交易、游戏娱乐还是社交媒体等,香港服务器都能够提供高效稳定的服务。对于跨境电商来说,搭建香港服务器可以更好地满足亚洲用户的购物需求;对于金融机构来说,香港服务器…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
react菜单,动态绑定点击事件,菜单分离出去单独的js文件,Ant框架
1、菜单文件treeTop.js // 顶部菜单 import { AppstoreOutlined, SettingOutlined } from ant-design/icons; // 定义菜单项数据 const treeTop [{label: Docker管理,key: 1,icon: <AppstoreOutlined />,url:"/docker/index"},{label: 权限管理,key: 2,icon:…...
