UVM入门系列(三)----通过uvm_gen脚本快速搭建一般验证平台(中)

UVM入门系列(三)----通过uvm_gen脚本快速搭建一般验证平台(中)


前言

本篇博文继续之前博文的内容对验证平台进行补全,之前博文内容链接:
UVM入门系列(一)----通过uvm_gen脚本快速搭建一般验证平台(上)

monitor

1 i_monitor

i_monitor承担的功能是监测DUT的输入信号,并传输给reference model进行处理。由上篇博文给出的脚本生成的代码的基本框图可以知道,脚本生成的代码已经将i_monitor和i_agent之间进行了端口连接,所以本博文i_monitor传输包给reference model的数据通路设计如图
在这里插入图片描述11
i_agent的analysis_port到analysis_fifo(在env中定义)到reference model的uvm_blocking_get_port之间的连接在env中进行。
数据包在i_monitor中通过write函数写入fifo,在reference model中通过get函数从fifo中取出。数据包的收发过程均是主动的过程,利于控制。
文章之后的o_monitor和scoreboard之间、reference model和scoreboard之间的连接以此方式进行连接。
下面开始进行代码的补充:
由于已经做了i_monitor到i_agent之间的连接,所以i_monitor代码部分只要增加输入端口的采样和write该函数即可。
i_monitor的采样频率由uvm_event控制,每次seq发送item之后,会触发event,i_monitor等待到event之后开始进行信号采样。
add_seq.sv:

class add_seq extends i_base_seq;
    `uvm_object_utils(add_seq)
    uvm_event seq_begin_ev;
    uvm_event o_seq_begin_ev;
    extern function new(string name="add_seq");
    extern task body();
endclass

function add_seq::new(string name="add_seq");
    super.new(name);
endfunction

task add_seq::body();
    seq_begin_ev=uvm_event_pool::get_global("seq_begin_ev");
    o_seq_begin_ev=uvm_event_pool::get_global("o_seq_begin_ev");
    `uvm_info(get_type_name(),"Default sequence starting",UVM_HIGH)
        o_seq_begin_ev.trigger();
    repeat(100) begin
        seq_begin_ev.trigger();
        `uvm_do(req);
    end
    `uvm_info(get_type_name(),"Default sequence end",UVM_HIGH)
endtask

seq_begin_ev 用于控制i_monitor的采样
o_seq_begin_ev 用于控制o_monitor的采样

i_monitor.sv:

class i_monitor extends uvm_monitor;

  `uvm_component_utils(i_monitor)
  virtual interface i_agent_if vif;
  virtual interface cr_if cvif;
  uvm_analysis_port #(i_seq_item) analysis_port;
  i_seq_item m_trans;
  uvm_event seq_begin_ev;

  extern function new(string name, uvm_component parent);
  extern virtual function void build_phase (uvm_phase phase);
  extern virtual function void connect_phase(uvm_phase phase);
  extern task main_phase(uvm_phase phase);
  extern task do_mon();

endclass : i_monitor 

function i_monitor::new(string name, uvm_component parent);
  super.new(name, parent);
  analysis_port = new("analysis_port", this);
endfunction : new

function void i_monitor::build_phase(uvm_phase phase);
    seq_begin_ev=uvm_event_pool::get_global("seq_begin_ev");
endfunction : build_phase

function void i_monitor::connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  if (!uvm_config_db #(virtual i_agent_if)::get(this, "", "vif", vif))
    `uvm_error("NOVIF", {"virtual interface must be set for: ",get_full_name(),".vif"})
  if (!uvm_config_db #(virtual cr_if)::get(this, "", "cvif", cvif))
    `uvm_error("NOVIF", {"virtual interface must be set for: ",get_full_name(),".cvif"})
endfunction : connect_phase

task i_monitor::main_phase(uvm_phase phase);
    `uvm_info(get_type_name(), "main phase", UVM_HIGH)
    fork 
        forever begin
            seq_begin_ev.wait_trigger();
            seq_begin_ev.reset();
            @(posedge cvif.sysclock);
            m_trans = i_seq_item::type_id::create("m_trans");
            do_mon();
            analysis_port.write(m_trans);
            `uvm_info("I_MON",m_trans.sprint,UVM_LOW)
        end
    join_none
endtask : main_phase

task i_monitor::do_mon();
    m_trans.a=vif.a;
    m_trans.b=vif.b;
    m_trans.cin=vif.cin;
endtask : do_mon

2 o_monitor

o_monitor与i_monitor类似,用于DUT输出端口信号的采样。
首先补全o_seq_item.sv

class o_seq_item extends uvm_sequence_item;
     rand bit cout;
     rand bit [8:0] sum;
    `uvm_object_utils_begin(o_seq_item)
        `uvm_field_int(cout,UVM_DEFAULT)
        `uvm_field_int(sum,UVM_DEFAULT)
    `uvm_object_utils_end

  extern function new(string name = "o_seq_item");
endclass : o_seq_item 


function o_seq_item::new(string name = "o_seq_item");
  super.new(name);
endfunction : new

o_monitor会采样o_seq_item,并发送给scoreboard。

class o_monitor extends uvm_monitor;
  `uvm_component_utils(o_monitor)
  virtual interface o_agent_if vif;
  virtual interface cr_if cvif;
  uvm_analysis_port #(o_seq_item) analysis_port;
  uvm_event o_seq_begin_ev;
  o_seq_item m_trans;
  extern function new(string name, uvm_component parent);
  extern virtual function void build_phase (uvm_phase phase);
  extern virtual function void connect_phase(uvm_phase phase);
  extern task main_phase(uvm_phase phase);
  extern task do_mon();
endclass : o_monitor 

function o_monitor::new(string name, uvm_component parent);
  super.new(name, parent);
  analysis_port = new("analysis_port", this);
endfunction : new

function void o_monitor::build_phase(uvm_phase phase);
    o_seq_begin_ev=uvm_event_pool::get_global("o_seq_begin_ev");
endfunction : build_phase

function void o_monitor::connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  if (!uvm_config_db #(virtual o_agent_if)::get(this, "", "vif", vif))
    `uvm_error("NOVIF", {"virtual interface must be set for: ",get_full_name(),".vif"})
  if (!uvm_config_db #(virtual cr_if)::get(this, "", "cvif", cvif))
    `uvm_error("NOVIF", {"virtual interface must be set for: ",get_full_name(),".cvif"})
endfunction : connect_phase

task o_monitor::main_phase(uvm_phase phase);
  `uvm_info(get_type_name(), "main phase", UVM_HIGH)
  fork
    begin
        o_seq_begin_ev.wait_trigger();
        @(posedge cvif.sysclock);
        @(posedge cvif.sysclock);
        forever begin
            m_trans = o_seq_item::type_id::create("m_trans");
            do_mon();
            analysis_port.write(m_trans);
            `uvm_info("O_MON",m_trans.sprint,UVM_LOW)
        end
    end
  join_none
endtask : main_phase

task o_monitor::do_mon();
    m_trans.sum=vif.sum;
    m_trans.cout=vif.cout;
    @(posedge cvif.sysclock);
endtask : do_mon

3 在env中进行port的连接:

声明fifo

  uvm_tlm_analysis_fifo#(i_seq_item) i_ref_fifo;
  uvm_tlm_analysis_fifo#(o_seq_item) o_scb_fifo;
  i_ref_fifo=new("i_ref_fifo",this);
  o_scb_fifo=new("o_scb_fifo",this);

连接port:

  m_o_agent.analysis_port.connect(o_scb_fifo.analysis_export);
  m_scb.get_o_port.connect(o_scb_fifo.blocking_get_export);
  m_refm.analysis_port.connect(ref_scb_fifo.analysis_export);
  m_scb.get_ref_port.connect(ref_scb_fifo.blocking_get_export);

总结

本篇博文完成了dut输入输出信号的采样工作,并将采样的接口信号打包发送给reference model和scoreboard进行处理,后续博文会继续进行reference model 和scoreboard部分代码的完善。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值