当前位置: 首页 > news >正文

【UVM学习笔记】UVM验证平台的运行—Phase以及objection

系列文章目录

【UVM学习笔记】更加灵活的UVM—通信
【UVM学习笔记】UVM基础—一文告诉你UVM的组成部分
【UVM学习笔记】UVM中的“类”


文章目录

  • 系列文章目录
  • 前言
  • 一、phase机制
    • 1.1 task phase与function phase
    • 1.2 代码执行顺序
    • 1.3 super.phase的内容
    • 1.4 phase的跳转
  • 二、objection机制
    • 2.1 在scoreboard中进行控制
    • 2.1 在sequence中进行控制
  • 二、domain机制
  • 总结


前言

该专题用于记录学习UVM芯片验证的过程,主要学习书籍为经典的《UVM实战》,同时也会去进行一些UVM的项目联系。


一、phase机制

1.1 task phase与function phase

UVM中的phase,按照其是否消耗仿真时间的特性,可以分成两大类,一类是function phase,如build_phase、connect_phase等,这些phase都不耗费仿真时间,通过函数来实现;另外一类是task phase,如run_phase等,它们耗费仿真时间,通过任务来实现。
灰色背景所示的是task phase,其他为function phase。

值得注意的是,task phase中,run_phase和pre_reset_phase等12个小的phase并行运行。后者称为动态运行的phase。
分成小的phase是为了实现更加精细化的控制。reset、configure、main、shutdown四个phase是核心,这四个phase通常模拟DUT的正常工作方式,在reset_phase对DUT进行复位、初始化等操作,在configure_phase则进行DUT的配置,DUT的运行主要在main_phase完成,shutdown_phase则是做一些与DUT断电相关的操作。

1.2 代码执行顺序

对于UVM树来说,共有三种顺序可以选择,一是自上而下,二是自下而上,三是随机序。最后一种方式是不受人控制的,在编程当中,这种不受控制的代码越少越好。因此可以选择的无非就是自上而下或者自下而上。
除了build_phase之外,所有不耗费仿真时间的phase(即function phase)都是自下而上执行的。
对于同一层次的、具有兄弟关系的component,其执行顺序是按照字典序的。

1.3 super.phase的内容

对于build_phase来说,uvm_component对其做的最重要的事情就是自动获取通过config_db::set设置的参数。除build_phase外,在写其他phase时,完全可以不必加上super.xxxx_phase语句。

1.4 phase的跳转

phase的跳转是比较高级的功能,假如在验证平台中监测到reset_n信号为低电平,则马上从main_phase跳转到reset_phase。driver的代码如下:

task my_driver::reset_phase(uvm_phase phase);
   phase.raise_objection(this); 
   `uvm_info("driver", "reset phase", UVM_LOW)
   vif.data <= 8'b0;
   vif.valid <= 1'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   phase.drop_objection(this); 
endtask

task my_driver::main_phase(uvm_phase phase);
   `uvm_info("driver", "main phase", UVM_LOW)
   fork
      while(1) begin
         seq_item_port.get_next_item(req);
         drive_one_pkt(req);
         seq_item_port.item_done();
      end
      begin
         @(negedge vif.rst_n);
         phase.jump(uvm_reset_phase::get());
      end
   join
endtask

reset_phase主要做一些清理工作,并等待复位完成。main_phase中一旦监测到reset_n为低电平,则马上跳转到reset_phase。

二、objection机制

objection字面的意思就是反对、异议。在验证平台中,可以通过drop_objection来通知系统可以关闭验证平台。当然,在撤销之前首先要raise_objection
如果UVM发现此phase没有提起任何objection,那么将会直接跳转到下一个phase中。
一般来说,在一个实际的验证平台中,通常会在以下两种objection的控制策略中选择一种:

2.1 在scoreboard中进行控制

如果要在scoreboard中控制objection,则需要通过config_db::set的方式设置收集到的transaction的数量pkt_num,当收集到足够数量的transaction后跳出循环:

task my_scoreboard::main_phase(uvm_phase phase); 
	phase.raise_objection(this); 
	fork 
		while (1) begin 
			exp_port.get(get_expect); 
			expect_queue.push_back(get_expect); 
		end 
		for(int i = 0; i < pkt_num; i++) begin 
			act_port.get(get_actual); 
			...  
		end
	join_any 
	phase.drop_objection(this); 
endtask

上述代码中将原本的fork…join语句改为了fork…join_any。当收集到足够的transaction后,第二个进程终结,从而跳出fork…join_any,执行drop_objection语句。

2.1 在sequence中进行控制

当sequence完成后,再撤销此objection。这里就是之前章节的例子:

task my_case0::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("case0", "main_phase", UVM_LOW)
   #10000;
   phase.drop_objection(this);
endtask

以上两种方式在验证平台中都有应用。其中用得最多的是第二种,这种方式是UVM提倡的方式。UVM的设计哲学就是全部 由sequence来控制激励的生成,因此一般情况下只在sequence中控制objection。
但是有一个问题就是:在sequence中,n时刻发送完毕最后一个transaction,如果此时立刻drop_objection,那么最后在n+p时刻DUT输出的包将无法接收到。因此,在sequence中,最后一个包发送完毕后,要延时p时间才能drop_objection,对应的图如下所示:

virtual task body(); 
	if(starting_phase != null) 
		starting_phase.raise_objection(this); 
	repeat (10) begin 
		`uvm_do(m_trans) 
	end 
	#100; 
	if(starting_phase != null) 
		starting_phase.drop_objection(this); 
endtask

还有一种方法就是在最顶层运行下面的代码:

phase.phase_done.set_drain_time(this, 200);

这样在你撤销drop_objection后还会等待一段时间,提高了灵活性。

二、domain机制

在默认情况下,验证平台中所有component都位于一个名字为common_domain的domain中,假设有两个driver,那么两者在每一个phase的运行都是同步的。若要体现出独立性,那么两个部分的reset_phase、configure_phae、main_phase等就不应该同步。此时就应该让其中的一部分从common_domain中独立出来,使其位于不同的domain中。
下面是两个在不同的domain的情况:

domain把两块时钟域隔开,之后两个时钟域内的各个动态运行(run_time)的phase就可以不必同步。注意,这里domain只能隔离run-time的phase,对于其他phase,其实还是同步的。
若将某个component置于某个新的domain中,可以使用如下的方式:

class B extends uvm_component;
   uvm_domain new_domain;
   `uvm_component_utils(B)

   function new(string name, uvm_component parent);
      super.new(name, parent);
      new_domain = new("new_domain");
   endfunction

   virtual function void connect_phase(uvm_phase phase);
      set_domain(new_domain);
   endfunction

   extern virtual  task reset_phase(uvm_phase phase);
   extern virtual  task post_reset_phase(uvm_phase phase);
   extern virtual  task main_phase(uvm_phase phase);
   extern virtual  task post_main_phase(uvm_phase phase);
endclass

这样B就是单独一个domain了,然后再运行的话会发现两者的运行时间发生了错位。
刚才的A和B分别位于不同的domain中,在此种情况下,phase的跳转将只局限于某一个domain中。

class B extends uvm_component;
   uvm_domain new_domain;
   bit has_jumped;
   `uvm_component_utils(B)

   function new(string name, uvm_component parent);
      super.new(name, parent);
      new_domain = new("new_domain");
      has_jumped = 0;
   endfunction

   virtual function void connect_phase(uvm_phase phase);
      set_domain(new_domain);
   endfunction

   extern virtual  task reset_phase(uvm_phase phase);
   extern virtual  task main_phase(uvm_phase phase);
endclass

task B::reset_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("B", "enter into reset phase", UVM_LOW)
   #100;
   phase.drop_objection(this);
endtask

task B::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("B", "enter into main phase", UVM_LOW)
   #500;
   if(!has_jumped) begin
      phase.jump(uvm_reset_phase::get());
      has_jumped = 1'b1;
   end
   phase.drop_objection(this);
endtask

运行的结果是B两次进入了reset_phase和main_phase,而A只进入了一次。domain的应用使得phase的跳转可以只局限于验证平台的一部分。

总结

在这一章主要讲述了在UVM中每一个phase的运算顺序,有的是一瞬间运行,一个是需要消耗仿真时间,同时还在跳转、独立性等方面进行了讨论,能够帮助读者更加灵活的进行代码的编写。

相关文章:

  • Redis-11.在Java中操作Redis-Spring Data Redis使用方式-环境搭建
  • spark 集群
  • Gson修仙指南:谷歌大法的佛系JSON渡劫手册
  • C++语言新特性2
  • GraalVM 24 正式发布阿里巴巴贡献重要特性 —— 支持 Java Agent 插桩
  • CExercise_05_1函数_2海伦公式求三角形面积
  • YOLO学习笔记 | 基于YOLO与光流融合的车牌识别方法研究(附Matlab代码)
  • FastAPI依赖注入:从基础概念到应用
  • python+form+opengl显示动态图形数据
  • Nacos 的AP和CP底层是怎么实现的?
  • 多layout 布局适配
  • DHCP之报文格式
  • 记录 | Android getWindow().getDecorView().setSystemUiVisibility(...)设置状态栏属性
  • ubuntu22.04LTS设置中文输入法
  • VBA第三十七期 VBA如何通过事件触发监视所有打开的工作簿或工作表?
  • Linux——Linux系统调用函数练习
  • TCP基础篇(一)
  • 002.指纹浏览器进阶-传参指定操作系统为macOS
  • 【论文推荐|滑坡检测·空间预测·时间预测· 数据驱动的分析】机器学习在滑坡研究中的最新进展与应用(2022)(五)
  • 一周学会Pandas2 Python数据处理与分析-NumPy简介
  • 做空包网站合法吗/热门网站
  • 做杂志的网站有哪些/新闻头条今日要闻军事
  • 镇江外贸网站建设/网站优化推广招聘
  • 周村网站建设/北京搜索优化推广公司
  • 2018年网站建设/免费seo培训
  • vs2008做网站/西安今天出大事