苏州城乡建设局网站华为云服务器怎么建设网站
2026/1/1 22:12:39 网站建设 项目流程
苏州城乡建设局网站,华为云服务器怎么建设网站,学校后勤网站建设方案,淘宝建设网站的目的是什么UVM TLM 非阻塞Get端口#xff1a;主动询问取货式通信 你好#xff01;今天我们要学习UVM中非阻塞Get通信。这是一种主动上门取货的通信方式#xff0c;接收方主动去要数据#xff0c;而不是被动等待数据送上门。 #x1f3af; 一句话理解非阻塞G…UVM TLM 非阻塞Get端口主动询问取货式通信你好今天我们要学习UVM中非阻塞Get通信。这是一种主动上门取货的通信方式接收方主动去要数据而不是被动等待数据送上门。 一句话理解非阻塞Get非阻塞Get就像去商店买东西阻塞Get排队等店员服务一直等到轮到你可能等很久非阻塞Get进店先问有货吗有就买没有就离开或等会儿再来⚡ 为什么需要非阻塞Get通信场景对比客户取货想象两种取货方式阻塞方式普通Get客户到仓库等直到货物准备好非阻塞方式非阻塞Get客户打电话问货好了吗没好就挂断等会儿再打非阻塞Get的优势主动控制接收方决定何时取数据避免死等不会无限期阻塞等待灵活调度可以在多个数据源间轮询 Get vs Put 本质区别图解先通过一个流程图理解Get和Put的主动被动关系 核心概念三个关键方法非阻塞Get提供了三种与发送方交互的方式方法类型作用类比try_get()函数尝试获取数据立即返回成功/失败问店员能给我货吗can_get()函数仅查询是否有数据不获取问店员有货吗get()任务阻塞获取等待数据准备好排队等到有货 完整代码深度解析第一步定义数据包类class Packet extends uvm_object;rand bit[7:0]addr;// 地址字段rand bit[7:0]data;// 数据字段uvm_object_utils_begin(Packet)uvm_field_int(addr,UVM_ALL_ON)uvm_field_int(data,UVM_ALL_ON)uvm_object_utils_end functionnew(string namePacket);super.new(name);endfunction endclass注意Get通信是接收方主动所以发送方需要准备好数据等待被取走。第二步发送方实现componentA - 数据提供者角色反转发送方变成被请求方在Get模式中componentA不再是主动发送者而是数据提供者等待被请求。class componentA extends uvm_component;uvm_component_utils(componentA)// 1. 声明非阻塞Get实现端口不是Portuvm_nonblocking_get_imp #(Packet,componentA)m_get_imp;functionnew(string namecomponentA,uvm_component parentnull);super.new(name,parent);endfunction virtual functionvoidbuild_phase(uvm_phase phase);super.build_phase(phase);// 2. 创建实现端口等待被连接m_get_impnew(m_get_imp,this);endfunction// 3. 实现try_get当接收方请求数据时调用virtual function bittry_get(output Packet pkt);// 创建新数据包pktnew();assert(pkt.randomize());uvm_info(COMPA,componentB请求数据包,UVM_LOW)pkt.print();return1;// 总是成功提供数据endfunction// 4. 实现can_get查询是否可提供数据virtual function bitcan_get();// 总是可以提供服务return1;endfunction endclass关键点发送方实现try_get()函数不是任务参数output Packet pkt是输出参数填充数据后返回返回1表示成功提供数据0表示暂时无法提供第三步接收方实现componentB - 数据请求者接收方主动请求数据这是Get模式的核心。版本1基础try_get示例1class componentB extends uvm_component;uvm_component_utils(componentB)// 1. 声明非阻塞Get端口主动请求方uvm_nonblocking_get_port #(Packet)m_get_port;intm_num_tx2;// 请求次数functionnew(string namecomponentB,uvm_component parentnull);super.new(name,parent);endfunction virtual functionvoidbuild_phase(uvm_phase phase);super.build_phase(phase);// 2. 创建Get端口m_get_portnew(m_get_port,this);endfunction virtual taskrun_phase(uvm_phase phase);phase.raise_objection(this);repeat(m_num_tx)begin Packet pkt;bit success;// 3. 关键尝试获取数据非阻塞successm_get_port.try_get(pkt);if(success)begin uvm_info(COMPB,成功获取数据包,UVM_LOW)pkt.print();endelsebegin uvm_info(COMPB,获取数据失败,UVM_LOW)end end phase.drop_objection(this);endtask endclass关键点try_get()立即返回不阻塞输出参数pkt在成功时被填充接收方控制请求时机版本2循环try_get模拟阻塞可选实现virtual taskrun_phase(uvm_phase phase);phase.raise_objection(this);repeat(m_num_tx)begin Packet pkt;bit success;// 循环尝试直到成功获取dobegin successm_get_port.try_get(pkt);if(!success)begin uvm_info(COMPB,componentA暂无数据10ns后重试,UVM_LOW)#10;// 等待后重试end endwhile(!success);uvm_info(COMPB,成功获取数据包,UVM_LOW)pkt.print();end phase.drop_objection(this);endtask版本3使用can_get查询示例2virtual taskrun_phase(uvm_phase phase);phase.raise_objection(this);repeat(m_num_tx)begin Packet pkt;// 先查询发送方是否有数据uvm_info(COMPB,查询componentA是否有数据...,UVM_LOW)while(!m_get_port.can_get())begin #10;// 等待10ns后再次查询uvm_info(COMPB,再次查询...,UVM_LOW)end uvm_info(COMPB,componentA已就绪开始获取数据,UVM_LOW)// 确认有数据后获取这时应该100%成功m_get_port.try_get(pkt);pkt.print();end phase.drop_objection(this);endtaskcan_get的优势纯粹的查询不改变状态可以优化重试策略避免频繁调用try_get的开销第四步发送方的高级实现模拟真实场景版本2随机就绪的发送方class componentA extends uvm_component;// ... 其他代码不变// try_get实现随机决定是否提供数据virtual function bittry_get(output Packet pkt);bit ready;std::randomize(ready);// 随机生成0或1if(ready)begin pktnew();assert(pkt.randomize());uvm_info(COMPA,提供数据包,UVM_LOW)pkt.print();return1;endelsebegin uvm_info(COMPA,暂时无法提供数据,UVM_LOW)return0;end endfunction// can_get实现随机返回就绪状态virtual function bitcan_get();bit ready;std::randomize(ready)with{ready dist{0:/70,1:/30};};// 70%概率返回0未就绪30%概率返回1就绪returnready;endfunction endclass第五步环境连接class my_test extends uvm_test;uvm_component_utils(my_test)componentA compA;// 数据提供者componentB compB;// 数据请求者functionnew(string namemy_test,uvm_component parentnull);super.new(name,parent);endfunction virtual functionvoidbuild_phase(uvm_phase phase);super.build_phase(phase);compAcomponentA::type_id::create(compA,this);compBcomponentB::type_id::create(compB,this);endfunction virtual functionvoidconnect_phase(uvm_phase phase);// 注意连接方向Get端口连接到Get实现compB.m_get_port.connect(compA.m_get_imp);// 意思是compB的请求端口连接到compA的实现端口endfunction endclass重要Get模式连接方向接收方请求者的Port→ 发送方提供者的Imp与Put模式相反 两种模式输出对比分析模式1基础try_get总是成功0: [COMPA] componentB请求数据包 ← 被调用 0: [COMPB] 成功获取数据包 ← 立即返回成功特点请求立即得到满足类似阻塞get但没有等待。模式2can_get查询随机就绪0: [COMPB] 查询componentA是否有数据... 10: [COMPB] 再次查询... ← 等待10ns 20: [COMPB] 再次查询... ← 等待10ns 30: [COMPB] componentA已就绪开始获取数据 30: [COMPA] 提供数据包 ← 最终成功特点模拟真实场景发送方可能暂时无法提供数据。 Get vs Put 对比总结特性Get模式Put模式主动方接收方消费者发送方生产者控制权接收方决定何时取数据发送方决定何时发数据接口get(),try_get(),can_get()put(),try_put(),can_put()数据流向接收方 → 发送方请求数据发送方 → 接收方发送数据典型应用处理器读取存储器驱动器发送事务实现方法发送方实现try_get()接收方实现try_put() 实际应用场景场景1处理器读取指令缓存class instruction_cache extends uvm_component;uvm_nonblocking_get_imp #(instruction,instruction_cache)get_imp;instruction cache[1024];virtual function bittry_get(output instruction instr);if(pc_validcache_hit)begin instrcache[pc];return1;endelsebeginreturn0;// 缓存未命中end endfunction endclass class cpu_fetch_unit extends uvm_component;uvm_nonblocking_get_port #(instruction)get_port;virtual taskrun_phase(uvm_phase phase);forever begin instruction instr;// 尝试从缓存获取指令if(get_port.try_get(instr))beginprocess_instruction(instr);pcpc4;endelsebegin// 缓存未命中处理异常或等待handle_cache_miss();#10;// 等待缓存填充end end endtask endclass场景2DMA控制器读取数据class dma_controller extends uvm_component;uvm_nonblocking_get_port #(data_chunk)get_port;virtual tasktransfer_data(intstart_addr,intsize);for(inti0;isize;i4)begin data_chunk chunk;// 尝试获取数据块while(!get_port.try_get(chunk))begin// 内存忙碌等待并重试#5;end// 处理获取的数据process_data_chunk(chunk);end endtask endclass场景3仲裁器从多个源获取数据class round_robin_arbiter extends uvm_component;uvm_nonblocking_get_port #(packet)port_a,port_b,port_c;virtual taskrun_phase(uvm_phase phase);forever begin packet pkt;// 轮询各个端口if(port_a.try_get(pkt))beginprocess_from_a(pkt);endelseif(port_b.try_get(pkt))beginprocess_from_b(pkt);endelseif(port_c.try_get(pkt))beginprocess_from_c(pkt);endelsebegin// 所有源都无数据等待#10;end end endtask endclass⚠️ 注意事项和最佳实践1. 函数 vs 任务// ❌ 错误非阻塞接口实现任务virtual tasktry_get(output Packet pkt);// 应该是function// ✅ 正确非阻塞接口实现函数virtual function bittry_get(output Packet pkt);2. 输出参数处理// 必须分配新的对象virtual function bittry_get(output Packet pkt);// ❌ 错误不分配对象// pkt.addr 8hFF; // 空指针错误// ✅ 正确创建新对象pktnew();pkt.randomize();return1;endfunction3. 连接方向// ❌ 错误Get模式连接反了compA.m_get_port.connect(compB.m_get_imp);// Put模式才这样// ✅ 正确Get模式连接compB.m_get_port.connect(compA.m_get_imp);// 请求者→提供者4. 竞态条件处理// 多个接收方竞争同一发送方时class shared_data_source extends uvm_component;uvm_nonblocking_get_imp #(Packet,shared_data_source)get_imp;semaphore locknew(1);// 互斥锁virtual function bittry_get(output Packet pkt);if(lock.try_get(1))begin// 获取锁成功pktcreate_packet();lock.put(1);return1;endelsebegin// 获取锁失败其他线程正在使用return0;end endfunction endclass 阻塞 vs 非阻塞Get对比特性阻塞Get非阻塞Get接口类型uvm_blocking_get_portuvm_nonblocking_get_port实现类型uvm_blocking_get_impuvm_nonblocking_get_imp方法类型任务task函数function阻塞性接收方被阻塞接收方立即返回主要方法get()try_get(),can_get()返回值直接返回数据1成功/0失败适用场景简单同步复杂异步、性能敏感典型应用顺序数据读取总线访问、多线程读取 实战练习建议练习1基础非阻塞Get实现基础非阻塞Get示例1观察立即返回的特性对比阻塞Get的时间消耗练习2模拟真实场景让发送方随机忙碌示例2实现接收方的轮询策略添加超时机制练习3多源获取实现一个接收方从两个发送方获取数据使用轮询或优先级策略处理数据源切换练习4性能优化// 比较不同策略的性能virtual taskperformance_test();realtime start_time;intiterations1000;// 策略1频繁try_getstart_time$realtime;for(inti0;iiterations;i)begin Packet pkt;while(!get_port.try_get(pkt))#1;// 忙等待end realtime strategy1_time$realtime-start_time;// 策略2使用can_get减少尝试start_time$realtime;for(inti0;iiterations;i)begin Packet pkt;while(!get_port.can_get())#10;// 等待更长时间get_port.try_get(pkt);end realtime strategy2_time$realtime-start_time;uvm_info(PERF,$sformatf(策略1: %0t ns, 策略2: %0t ns,strategy1_time,strategy2_time),UVM_LOW)endtask 设计模式推荐模式1带超时的获取class timeout_getter extends uvm_component;uvm_nonblocking_get_port #(Packet)get_port;virtual function bitget_with_timeout(output Packet pkt,inttimeout_ns);realtime start_time$realtime;while($realtime-start_timetimeout_ns)beginif(get_port.try_get(pkt))return1;// 成功#5;// 等待5ns后重试end uvm_warning(TIMEOUT,获取数据超时)return0;// 超时失败endfunction endclass模式2批量获取优化class batch_getter extends uvm_component;uvm_nonblocking_get_port #(data_item)get_port;virtual taskget_batch(data_item batch[$],intbatch_size);for(inti0;ibatch_size;i)begin data_item item;// 尝试获取失败则等待while(!get_port.try_get(item))begin// 可以在这里做其他工作#10;end batch.push_back(item);end endtask endclass模式3优先级多源获取class priority_getter extends uvm_component;uvm_nonblocking_get_port #(packet)high_pri_port,low_pri_port;virtual taskrun_phase(uvm_phase phase);forever begin packet pkt;// 优先尝试高优先级源if(high_pri_port.try_get(pkt))beginprocess_high_priority(pkt);endelseif(low_pri_port.try_get(pkt))beginprocess_low_priority(pkt);endelsebegin// 都无数据等待#20;end end endtask endclass 总结非阻塞TLM Get是主动、灵活、高效的拉取数据方式接收方主动控制何时获取数据立即返回不会被无限期阻塞状态感知通过返回值知道获取结果灵活控制可以重试、等待、放弃或切换数据源记住核心特点Get模式接收方主动请求数据不阻塞try_get函数立即返成功失败即刻知can_get查询状态用优化性能减开销连接方向要注意请求端口连实现。掌握了非阻塞Get你就能构建更加主动、高效的验证平台现在尝试在你的测试中用Get模式替换一些被动等待的场景让组件更加智能吧

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询