电力电子转战数字IC20220816day61——uvm入门实验3

目录

实验目标

实验任务

1.1将monitor中用来与checker中的mailbox通信的mon_mb句柄换成对应的uvm_blocking_put_port类型

1.2在checker中声明和monitor通信的imp端口,与refmod通信的imp端口

1.3对上面声明的imp实现对应的方法

1.4在mcdf_refmod中声明与checker连接的imp端口,例化

1.5在mcdf_env的connect_phase()完成monitor的port连接到mcdf_checker imp

1.6在mcdf_checker中完成mcdf_refmod的port连接到mcdf_checker的imp

2.1将mcdf_refmod中的out_mb替换成uvm_tlm_fifo

2.2同样的,mcdf_checker中的exp_mb[3]替换成uvm_blocking_get_port类型句柄数组。将mcdf_checker中的port连接到mcdf_refmod中uvm_tlm_fifo自带的blocking_get_export

3.1利用回调函数完成类的复用,先预定义几个虚方法

3.2关联回调类型和对应的test

3.3回调指定,也就是连接

3.4定义继承于base test的两个test的两个回调函数cb_*********,这两个回调函数都继承于base test的回调函数

4在mcdf_base_test中添加新的end_of_elaboration_phase函数;利用uvm_root类设置信息冗余度为UVM_high;利用uvm_root::set_report_max_quit_count()函数设置仿真退出的最大数值;利用uvm_root::set_timeout()设置仿真的最大时间长度


实验目标

实验任务

1.1将monitor中用来与checker中的mailbox通信的mon_mb句柄换成对应的uvm_blocking_put_port类型

首先在monitor中(这里以chnl_monitor为例),声明端口

    uvm_blocking_put_port #(mon_data_t) mon_bp_port;

然后在new函数中例化这个PORT

    function new(string name="chnl_monitor", uvm_component parent);
      super.new(name, parent);
      //TODO-1.1 instantiate the TLM port
      mon_bp_port = new("mon_bp_port", this);
    endfunction

将原来存放句柄的方式由mailbox改为端口

        mon_mb.put(m);

        mon_bp_port.put(m);

1.2在checker中声明和monitor通信的imp端口,与refmod通信的imp端口

checker对多个agent中的monitor,是一对多的多方向通信类型,需要使用宏声明

//在mcdf_checker前进行宏声明
  `uvm_blocking_put_imp_decl(_chnl0)
  `uvm_blocking_put_imp_decl(_chnl1)
  `uvm_blocking_put_imp_decl(_chnl2)
  `uvm_blocking_put_imp_decl(_fmt)
  `uvm_blocking_put_imp_decl(_reg)

  `uvm_blocking_get_peek_imp_decl(_chnl0)
  `uvm_blocking_get_peek_imp_decl(_chnl1)
  `uvm_blocking_get_peek_imp_decl(_chnl2)

  `uvm_blocking_get_imp_decl(_reg)

//在mcdf_checker中进行端口声明
    uvm_blocking_put_imp_chnl0 #(mon_data_t, mcdf_checker)   chnl0_bp_imp;
    uvm_blocking_put_imp_chnl1 #(mon_data_t, mcdf_checker)   chnl1_bp_imp;
    uvm_blocking_put_imp_chnl2 #(mon_data_t, mcdf_checker)   chnl2_bp_imp;
    uvm_blocking_put_imp_fmt   #(fmt_trans , mcdf_checker)   fmt_bp_imp  ;
    uvm_blocking_put_imp_reg   #(reg_trans , mcdf_checker)   reg_bp_imp  ;
    //
    uvm_blocking_get_peek_imp_chnl0 #(mon_data_t, mcdf_checker)  chnl0_bgpk_imp;
    uvm_blocking_get_peek_imp_chnl1 #(mon_data_t, mcdf_checker)  chnl1_bgpk_imp;
    uvm_blocking_get_peek_imp_chnl2 #(mon_data_t, mcdf_checker)  chnl2_bgpk_imp;

    uvm_blocking_get_imp_reg    #(reg_trans , mcdf_checker)  reg_bg_imp  ;

//在new函数中例化
      chnl0_bp_imp = new("chnl0_bp_imp", this);
      chnl1_bp_imp = new("chnl1_bp_imp", this);
      chnl2_bp_imp = new("chnl2_bp_imp", this);
      fmt_bp_imp   = new("fmt_bp_imp", this);  
      reg_bp_imp   = new("reg_bp_imp", this);  

      chnl0_bgpk_imp = new("chnl0_bgpk_imp", this);
      chnl1_bgpk_imp = new("chnl1_bgpk_imp", this);
      chnl2_bgpk_imp = new("chnl2_bgpk_imp", this);

      reg_bg_imp    = new("reg_bg_imp", this);  

1.3对上面声明的imp实现对应的方法

    task put_chnl0(mon_data_t t);
      chnl_mbs[0].put(t);
    endtask
    task put_chnl1(mon_data_t t);
      chnl_mbs[1].put(t);
    endtask
    task put_chnl2(mon_data_t t);
      chnl_mbs[2].put(t);
    endtask
    task put_fmt(fmt_trans t);
      fmt_mb.put(t);
    endtask
    task put_reg(reg_trans t);
      reg_mb.put(t);
    endtask

    task peek_chnl0(output mon_data_t t);
      chnl_mbs[0].peek(t);
    endtask
    task peek_chnl1(output mon_data_t t);
      chnl_mbs[1].peek(t);
    endtask
    task peek_chnl2(output mon_data_t t);
      chnl_mbs[2].peek(t);
    endtask
    task get_chnl0(output mon_data_t t);
      chnl_mbs[0].get(t);
    endtask
    task get_chnl1(output mon_data_t t);
      chnl_mbs[1].get(t);
    endtask
    task get_chnl2(output mon_data_t t);
      chnl_mbs[2].get(t);
    endtask
    task get_reg(output reg_trans t);
      reg_mb.get(t);
    endtask

1.4在mcdf_refmod中声明与checker连接的imp端口,例化

//在mcdf_refmod类中声明
    uvm_blocking_get_port #(reg_trans) reg_bg_port;
    uvm_blocking_get_peek_port #(mon_data_t) in_bgpk_ports[3];

//在new函数中例化
      reg_bg_port = new("reg_bg_port", this);
      foreach(in_bgpk_ports[i]) in_bgpk_ports[i] = new($sformatf("in_bgpk_ports[%0d]", i), this);

//将mailbox换成PORT
        this.reg_mb.get(t);

        this.reg_bg_port.get(t);
        this.in_mbs[id].peek(it);

          this.in_bgpk_ports[id].get(it);

          this.in_mbs[id].get(it);

          this.in_bgpk_ports[id].get(it);

1.5在mcdf_env的connect_phase()完成monitor的port连接到mcdf_checker imp

    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      //TODO-1.5 connect TLM ports between monitors and the checker
      chnl_agts[0].monitor.mon_bp_port.connect(chker.chnl0_bp_imp);
      chnl_agts[1].monitor.mon_bp_port.connect(chker.chnl1_bp_imp);
      chnl_agts[2].monitor.mon_bp_port.connect(chker.chnl2_bp_imp);
      reg_agt.monitor.mon_bp_port.connect(chker.reg_bp_imp);
      fmt_agt.monitor.mon_bp_port.connect(chker.fmt_bp_imp);
    endfunction

1.6在mcdf_checker中完成mcdf_refmod的port连接到mcdf_checker的imp

    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      //TODO-1.6 connect checker TLM ports with the ones of reference model
      refmod.in_bgpk_ports[0].connect(chnl0_bgpk_imp);
      refmod.in_bgpk_ports[1].connect(chnl1_bgpk_imp);
      refmod.in_bgpk_ports[2].connect(chnl2_bgpk_imp);

      refmod.reg_bg_port.connect(reg_bg_imp);

2.1将mcdf_refmod中的out_mb替换成uvm_tlm_fifo

//先声明
    uvm_tlm_fifo #(fmt_trans) out_tlm_fifos[3];
//new函数中例化
      foreach(out_tlm_fifos[i]) out_tlm_fifos[i] = new($sformatf("out_tlm_fifos[%0d]", i), this);
//替代原来的mailbox
        this.out_mbs[id].put(ot);

        this.out_tlm_fifos[id].put(ot);

2.2同样的,mcdf_checker中的exp_mb[3]替换成uvm_blocking_get_port类型句柄数组。将mcdf_checker中的port连接到mcdf_refmod中uvm_tlm_fifo自带的blocking_get_export

    uvm_blocking_get_port #(fmt_trans) exp_bg_ports[3];

      foreach(exp_bg_ports[i]) exp_bg_ports[i] = new($sformatf("exp_bg_ports[%0d]", i), this);

//        this.exp_mbs[mont.ch_id].get(expt);

        this.exp_bg_ports[mont.ch_id].get(expt);

      foreach(exp_bg_ports[i]) begin
        exp_bg_ports[i].connect(refmod.out_tlm_fifos[i].blocking_get_export);
      end

使用uvm_tlm_fifo就可以既使用tlm端口又不用自己实现具体的方法

3.1利用回调函数完成类的复用,先预定义几个虚方法

  typedef class mcdf_base_test;

  class cb_mcdf_base extends uvm_callback;
    `uvm_object_utils(cb_mcdf_base)
    mcdf_base_test test;
    function new (string name = "cb_mcdf_base");
      super.new(name);
    endfunction

    virtual task cb_do_reg();
      // User to define the content
    endtask

    virtual task cb_do_formatter();
      // User to define the content
    endtask

    virtual task cb_do_data();
      // User to define the content
    endtask
  endclass

3.2关联回调类型和对应的test

在对应的test注册时使用callback对应的宏

    `uvm_register_cb(mcdf_base_test, cb_mcdf_base)

3.3回调指定,也就是连接

在对应的test中的虚方法用回调指定宏,参数多了虚方法

    virtual task do_reg();
      //TODO-3.3 Use callback macro to link the callback method
      `uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_reg())
    endtask

    // do external formatter down stream slave configuration
    virtual task do_formatter();
      //TODO-3.3 Use callback macro to link the callback method
      `uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_formatter())
    endtask

    // do data transition from 3 channel slaves
    virtual task do_data();
      //TODO-3.3 Use callback macro to link the callback method
      `uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_data())
    endtask

3.4定义继承于base test的两个test的两个回调函数cb_*********,这两个回调函数都继承于base test的回调函数

把原来mcdf_data_consistence_basic_test完全复制到回调函数cb_mcdf_data_consistence_basic_test中,全部方法前面加上cb_前缀,相当于做了两次相同的mcdf_data_consistence_basic_test。也可以定义新的方法或修改原有方法,作为test的扩展

  class cb_mcdf_data_consistence_basic extends cb_mcdf_base;
    `uvm_object_utils(cb_mcdf_data_consistence_basic)
    function new (string name = "cb_mcdf_data_consistence_basic");
      super.new(name);
    endfunction
    task cb_do_reg();
      bit[31:0] wr_val, rd_val;
      super.cb_do_reg();
      // slv0 with len=8,  prio=0, en=1
      wr_val = (1<<3)+(0<<1)+1;
      test.write_reg(`SLV0_RW_ADDR, wr_val);
      test.read_reg(`SLV0_RW_ADDR, rd_val);
      void'(test.diff_value(wr_val, rd_val, "SLV0_WR_REG"));

      // slv1 with len=16, prio=1, en=1
      wr_val = (2<<3)+(1<<1)+1;
      test.write_reg(`SLV1_RW_ADDR, wr_val);
      test.read_reg(`SLV1_RW_ADDR, rd_val);
      void'(test.diff_value(wr_val, rd_val, "SLV1_WR_REG"));

      // slv2 with len=32, prio=2, en=1
      wr_val = (3<<3)+(2<<1)+1;
      test.write_reg(`SLV2_RW_ADDR, wr_val);
      test.read_reg(`SLV2_RW_ADDR, rd_val);
      void'(test.diff_value(wr_val, rd_val, "SLV2_WR_REG"));

      // send IDLE command
      test.idle_reg();
    endtask

    task cb_do_formatter();
      super.cb_do_formatter();
      void'(test.fmt_gen.randomize() with {fifo == LONG_FIFO; bandwidth == HIGH_WIDTH;});
      test.fmt_gen.start();
    endtask

    task cb_do_data();
      super.cb_do_data();
      void'(test.chnl_gens[0].randomize() with {ntrans==100; ch_id==0; data_nidles==0; pkt_nidles==1; data_size==8; });
      void'(test.chnl_gens[1].randomize() with {ntrans==100; ch_id==1; data_nidles==1; pkt_nidles==4; data_size==16;});
      void'(test.chnl_gens[2].randomize() with {ntrans==100; ch_id==2; data_nidles==2; pkt_nidles==8; data_size==32;});
      fork
        test.chnl_gens[0].start();
        test.chnl_gens[1].start();
        test.chnl_gens[2].start();
      join
      #10us; // wait until all data haven been transfered through MCDF
    endtask
  endclass: cb_mcdf_data_consistence_basic

注意:原来test中用this.的地方表示当前类,在回调函数中改成test.1

4在mcdf_base_test中添加新的end_of_elaboration_phase函数;利用uvm_root类设置信息冗余度为UVM_high;利用uvm_root::set_report_max_quit_count()函数设置仿真退出的最大数值;利用uvm_root::set_timeout()设置仿真的最大时间长度

    function void end_of_elaboration_phase(uvm_phase phase);
      super.end_of_elaboration_phase(phase);
      uvm_root::get().set_report_verbosity_level_hier(UVM_HIGH);
      uvm_root::get().set_report_max_quit_count(1);
      uvm_root::get().set_timeout(10ms);
    endfunction

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值