UVM 碎记

6 篇文章 7 订阅

目录

uvm_domain

使用方法:

main phase 跳转到reset phase:

sequencer 的仲裁特性

uvm_event

uvm_barrier

uvm_callback

sequence的通信时序 

域的自动化声明


uvm_domain

控制run_phase对应的细分phase异步执行,适用于DUT含有多个时钟域时,独立的进行细分phase操作,如复位,配置,启动执行。

默认情况下,两个driver类中的复位phase 和main phase必须同时执行。

使用方法:

  1. uvm_domain xxx_domain;//组件里定义
  2. xxx_domain = new(“xxx_domain”);//实例化 function new中
  3. set_domain(xxx_domain);//将当前组件加入xxx_domain中,一般在connect_phase中使用

UVM机制学习之Objection, Domain机制_15的月亮的博客-CSDN博客

UVM:5.3.1 domain 简介_tingtang13的博客-CSDN博客

UVM:5.3.2 多domain 的例子_tingtang13的博客-CSDN博客

UVM:5.3.3 多domain中phase 的跳转_tingtang13的博客-CSDN博客

main phase 跳转到reset phase:

phase.jump(uvm_reset_phase::get());

sequencer 的仲裁特性

可以通过uvm_sequencer::set_arbitration(UVM_SEQ_ARB_TYPE val)函数来设置仲裁模式,这里的仲裁模式UVM_SEQ_ARB_TYPE 有下面几种值可以选择:

  • UVM_SEQ_ARB_FIFO:默认模式,来自于sequences的发送请求,按照FIFO先进先出的方式被依次授权,和优先级没有关系。
  • UVM_SEQ_ARB_WEIGHTED:不同sequeces的发送请求,将按照它们的优先级权重随机授权。
  • UVM_SEQ_ARB_RANDOM:不同的请求会被随机授权,而无视它们的抵达顺序和优先级。
  • UVM_SEQ_ARB_STRICT_FIFO:不同的请求,会按照它们的优先级以及抵达顺序来依次授权,因此与优先级和抵达时间都有关。
  • UVM_SEQ_ARB_STRICT_RANDOM:不同的请求,会按照它们的最高优先级随机授权,与抵达时间无关。
  • UVM_SEQ_ARB_USER:用户可以自定义仲裁方法user_priority_arbitration来裁定哪个sequencer的请求被优先授权。

uvm_event

与event 相比,uvm event类有下面几个重要特性:
 

eventuvm_event

event被->触发之后,触发使用@等待该事件的对象;

再次触发,只需再次用->触发

通过trigger()来触发,触发使用wait trigger()等待该事件的对象。

再次触发,t需要先通过reset()方法重置初始状态,再使用trigger()来触发

无法携带更多的信息可以通过trigger(T data = null)的可选参数,将伴随触发的数据对象都写入到该触发事件中,而等待该事件的对象可以通过方法wait trigger data(output T data)来获取事件触发时写入的数据对象。
t触发时无法直接触发回调函数可以通过add_callback(uvm_event_callback cb,bit append =1)函数来添加回调函数。
无法直接获取等待它的进程数目可以通过 get num waiters()来获取等待它的进程数目。


TLM 传输必须是在组件和组件之间进行的,然而,要在sequence和sequence之间进行同步,或sequence与driver之间进行同步,可以借助uvm_event来实现。

module uvm_event_sync;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

  class edata extends uvm_object;
    int data;
    `uvm_object_utils(edata)
    function new(string name = "edata");
      super.new(name);
    endfunction
  endclass

  class ecb extends uvm_event_callback;
    `uvm_object_utils(ecb)
    function new(string name = "ecb");
      super.new(name);
    endfunction
    function bit pre_trigger(uvm_event e, uvm_object data = null);
      `uvm_info("EPRETRIG", $sformatf("before trigger event %s", e.get_name()), UVM_LOW)
      return 0;
    endfunction
    function void post_trigger(uvm_event e, uvm_object data = null);
      `uvm_info("EPOSTRIG", $sformatf("after trigger event %s", e.get_name()), UVM_LOW)
    endfunction
  endclass 


  class comp1 extends uvm_component;
    uvm_event e1;
    `uvm_component_utils(comp1)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      e1 = uvm_event_pool::get_global("e1");
    endfunction
    task run_phase(uvm_phase phase);
      edata d = new();
      ecb cb = new();
      d.data = 100;
      #10ns;
      e1.add_callback(cb);
      e1.trigger(d);
      `uvm_info("ETRIG", $sformatf("trigger sync event at %t ps", $time), UVM_LOW)
    endtask
  endclass

  class comp2 extends uvm_component;
    uvm_event e1;
    `uvm_component_utils(comp2)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      e1 = uvm_event_pool::get_global("e1");
    endfunction
    task run_phase(uvm_phase phase);
      uvm_object tmp;
      edata d;
      `uvm_info("ESYNC", $sformatf("wait sync event at %t ps", $time), UVM_LOW)
      e1.wait_trigger_data(tmp);
      void'($cast(d, tmp));
      `uvm_info("ESYNC", $sformatf("get data %0d after sync at %t ps", d.data, $time), UVM_LOW)
    endtask
  endclass

  class env1 extends uvm_env;
    comp1 c1;
    comp2 c2;
    `uvm_component_utils(env1)

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

    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      c1 = comp1::type_id::create("c1", this);
      c2 = comp2::type_id::create("c2", this);
    endfunction: build_phase
  endclass

  class test1 extends uvm_test;
    `uvm_component_utils(test1)
    env1 env;
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      env = env1::type_id::create("env", this);
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      phase.raise_objection(phase);
      #1us;
      phase.drop_objection(phase);
    endtask
  endclass

  initial begin
    run_test("test1");
  end
endmodule




// UVM_INFO @ 0: reporter [RNTST] Running test test1...
// UVM_INFO @ 0: uvm_test_top.env.c2 [ESYNC] wait sync event at                    0 ps
// UVM_INFO @ 10000: reporter [EPRETRIG] before trigger event e1
// UVM_INFO @ 10000: reporter [EPOSTRIG] after trigger event e1
// UVM_INFO @ 10000: uvm_test_top.env.c1 [ETRIG] trigger sync event at                10000 ps
// UVM_INFO @ 10000: uvm_test_top.env.c2 [ESYNC] get data 100 after sync at                10000 ps

uvm_barrier

多个组件的同步。barrier.wait_for   顶层设置 barrier.set_threshold()触发

module uvm_barrier_sync;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

  class comp1 extends uvm_component;
    uvm_barrier b1;
    `uvm_component_utils(comp1)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      b1 = uvm_barrier_pool::get_global("b1");
    endfunction
    task run_phase(uvm_phase phase);
      #10ns;
      `uvm_info("BSYNC", $sformatf("c1 wait for b1 at %0t ps", $time), UVM_LOW)
      b1.wait_for();
      `uvm_info("BSYNC", $sformatf("c1 is activated at %0t ps", $time), UVM_LOW)
    endtask
  endclass

  class comp2 extends uvm_component;
    uvm_barrier b1;
    `uvm_component_utils(comp2)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      b1 = uvm_barrier_pool::get_global("b1");
    endfunction
    task run_phase(uvm_phase phase);
      #20ns;
      `uvm_info("BSYNC", $sformatf("c2 wait for b1 at %0t ps", $time), UVM_LOW)
      b1.wait_for();
      `uvm_info("BSYNC", $sformatf("c2 is activated at %0t ps", $time), UVM_LOW)
    endtask
  endclass

  class env1 extends uvm_env;
    comp1 c1;
    comp2 c2;
    uvm_barrier b1;
    `uvm_component_utils(env1)

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

    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      c1 = comp1::type_id::create("c1", this);
      c2 = comp2::type_id::create("c2", this);
      b1 = uvm_barrier_pool::get_global("b1");
    endfunction: build_phase

    task run_phase(uvm_phase phase);
      b1.set_threshold(3);
      `uvm_info("BSYNC", $sformatf("env set b1 threshold %d at %0t ps", b1.get_threshold(), $time), UVM_LOW)
      #50ns;
      b1.set_threshold(2);
      `uvm_info("BSYNC", $sformatf("env set b1 threshold %d at %0t ps", b1.get_threshold(), $time), UVM_LOW)
    endtask

  endclass

  class test1 extends uvm_test;
    `uvm_component_utils(test1)
    env1 env;
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      env = env1::type_id::create("env", this);
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      phase.raise_objection(phase);
      #1us;
      phase.drop_objection(phase);
    endtask
  endclass

  initial begin
    run_test("test1");
  end
endmodule




// UVM_INFO @ 0: reporter [RNTST] Running test test1...
// UVM_INFO @ 0: uvm_test_top.env [BSYNC] env set b1 threshold 3 at 0 ps
// UVM_INFO @ 10000: uvm_test_top.env.c1 [BSYNC] c1 wait for b1 at 10000 ps
// UVM_INFO @ 20000: uvm_test_top.env.c2 [BSYNC] c2 wait for b1 at 20000 ps
// UVM_INFO @ 50000: uvm_test_top.env [BSYNC] env set b1 threshold 2 at 50000 ps
// UVM_INFO @ 50000: uvm_test_top.env.c1 [BSYNC] c1 is activated at 50000 ps
// UVM_INFO @ 50000: uvm_test_top.env.c2 [BSYNC] c2 is activated at 50000 ps

uvm_callback

  1. 定义callback空壳函数,extends uvm_callback;
  2. 在使用cb 的 component中注册绑定`uvm_register_cb(comp,cb)
  3. 预留函数入口:`uvm_do_callbacks(comp,cb,function) ,cb中的function
  4. 在顶层例化cb,comp,在build_phase中关联绑定,uvm_callbacks #(comp) ::add(compxx,cbxx)。
module uvm_callback_sync;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

  class edata extends uvm_object;
    int data;
    `uvm_object_utils(edata)
    function new(string name = "edata");
      super.new(name);
    endfunction
  endclass

  class cb1 extends uvm_callback;
    `uvm_object_utils(cb1)
    function new(string name = "cb1");
      super.new(name);
    endfunction
    virtual function void do_trans(edata d);
      d.data = 200;
      `uvm_info("CB", $sformatf("cb1 executed with data %0d", d.data), UVM_LOW)
    endfunction
  endclass

  class cb2 extends cb1;
    `uvm_object_utils(cb2)
    function new(string name = "cb2");
      super.new(name);
    endfunction
    function void do_trans(edata d);
      d.data = 300;
      `uvm_info("CB", $sformatf("cb2 executed with data %0d", d.data), UVM_LOW)
    endfunction
  endclass


  class comp1 extends uvm_component;
    `uvm_component_utils(comp1)
    `uvm_register_cb(comp1, cb1)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
    endfunction
    task run_phase(uvm_phase phase);
      edata d = new();
      d.data = 100;
      `uvm_info("RUN", $sformatf("proceeding data %0d", d.data), UVM_LOW)
      `uvm_do_callbacks(comp1, cb1, do_trans(d))
    endtask
  endclass

  class env1 extends uvm_env;
    comp1 c1;
    cb1 m_cb1;
    cb2 m_cb2;
    `uvm_component_utils(env1)

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

    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      c1 = comp1::type_id::create("c1", this);
      uvm_callbacks #(comp1)::add(c1, m_cb1);
      uvm_callbacks #(comp1)::add(c1, m_cb2);
    endfunction: build_phase
  endclass

  class test1 extends uvm_test;
    `uvm_component_utils(test1)
    env1 env;
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      env = env1::type_id::create("env", this);
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      phase.raise_objection(phase);
      #1us;
      phase.drop_objection(phase);
    endtask
  endclass

  initial begin
    run_test("test1");
  end
endmodule


// UVM_INFO @ 0: reporter [RNTST] Running test test1...
// UVM_INFO @ 0: uvm_test_top.env.c1 [RUN] proceeding data 100
// UVM_INFO @ 0: reporter [CB] cb1 executed with data 200
// UVM_INFO @ 0: reporter [CB] cb2 executed with data 300

sequence的通信时序 

         

域的自动化声明

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值