MCDF实验回顾

目录

一、lab1

  实验流程

二、lab2

实验流程

1、数组、队列、索引

2、类的三要素

3、接口设置、clocking块

4、package具有隔离作用

三、lab3

1、随机约束使用

2、邮箱使用

3、软约束用chnl_generator想控制chnl_trans生成值

4、关联数组启动仿真

5、mcdt_monitor

6、gen正常/非正常发送数据

7、约束constraint

8、其他

四、lab4

以部分知识点的形式列出:

1、实验知识

2、常见验证方法

3、事件、 旗语

4、结构体、枚举

5、其他

五、lab5

1、covergroup根据测试功能点设计

2、其他


一、lab1

  实验流程

            1、chnl_initiator是module,module chnl_initiator(input clk,...);

            2、在tb中例化连接mcdt dut(.clk_i(clk),...)、chnl_initiator chnl1_init(.clk(clk),...);

            3、通过chnl0_arr = new[100],foreach生成数据,write发送数据;

            4、判断dut中的ready决定是否发送下一个数据,给tb中的valid高电平,表示准备好了

二、lab2

实验流程

      类放在package中

      module tb4_ref中 1、连接dut

                                   2、initial clk、rst

                                   3、import chnl_pkg::*;   注意pkg中的intf都是virtual intf;( interface是硬件                                         语言,无法放在测试平台实例化,virtual interface本质是指向interface的                                         指针。)

                                   4、例化接口、例化test

                                   5、initial中实例化test,并用test中的方法传入接口,然后run;

1、数组、队列、索引

2、类的三要素

封装:属性、方法封装在内部,而不是暴露在外部,public(内部与外部可访问)、protected(父类、子类)、local(仅父类)。

以下为关联知识点:

  • 属性:可用static设置为静态,这种可以在未例化对象前用 class名::var 找到,且无论例化多少次,都是唯一的。
  • new()函数:用来开辟空间放入成员变量的初始化值,当无初始化变量时,可以省略function new()函数。
  • 类与结构体区别:stuct时就开辟了内存,不用new()函数创建对象。类可以有方法。
  • 类与模块区别:module是硬件,默认为静态方法,静态变量,仿真一开始就确定是否例化。类任何时间例化,有封装、继承、多态特性。

继承:通过extends子类继承父类的属性、方法。

以下为关联知识点:

  • function new()中先super.new()才可以继承父类new()的属性,
  • 父类有llp方法,子类也设置类llp方法,两者仅是同名的方法,无关联。
  • 父类有llp方法,子类也设置类llp方法,并在第一行写super.llp()、则继承父类方法,名字可以不同,但是如果父类需要传入参数,则子类方法传入参数需要一致,不然父类所需参数会找不到。

多态:通过虚方法进行动态绑定,达到句柄根据指向对象调用对应方法的效果。

以下为关联知识点:

  • 两种情况:父类方法(task或function都可以)virtual A,子类方法virtual A;或 父类方法virtual A,子类方法 A;
  • 当父类句柄指向子类对象时,如果父与子有同名函数且加了virtual(或只是父类加viretual),则父类句柄会调用子类中的方法。(更深入来讲是依然调用父类方法,但是父类方法加了virtual,方法被重写了)
  • 但是注意:1、方法加virtual,方法名字一样;2、且有一致的参数和返回值。与继承不同的是没有加super.moth() ;益处是父类句柄可调用子类方法的一种设置。
  • 动态绑定,根据指向对象调用方法,结合之前实验,父类句柄test[xxx]=t1(子类);后,test[xxx].run()是父类的run(),但父类中的virtual task do_reg()等都被子类更新了,且不是方法继承的方式,没有super.do_reg()

3、接口设置、clocking块

interface chnl_intf(input clk, input rstn);
  logic [31:0] ch_data;
  logic        ch_valid;
  logic        ch_ready;
  logic [ 5:0] ch_margin;
  clocking drv_ck @(posedge clk);
    default input #1ns output #1ns;
    output ch_data, ch_valid;
    input ch_ready, ch_margin;
  endclocking
endinterface

     接口传入:module tb4中例化接口chnl_intf chnl0_if(.*);并通过asic_test.set_interface(chnl0_if, chnl1_if, chnl2_if);传入

     接口接收:在package的类中例化local virtual chnl_intf intf;

function void set_interface(virtual chnl_intf intf);
      if(intf == null)
        $error("interface handle is NULL, please check if target interface has been intantiated");
      else
        this.intf = intf;
    endfunction

    接口与dut连接方式:

mcdt dut(
     .clk_i       (clk                )
    ,.rstn_i      (rstn               )
    ,.ch0_data_i  (chnl0_if.ch_data   )
    ,.ch0_valid_i (chnl0_if.ch_valid  )
。。。。。。。。。。。。。。。。。。。。

4、package具有隔离作用

类型1:先写好.sv文件,再在module tb中import reg_pkg::*;reg_mon mon1=new()是声明句柄同时建立对象。

package reg_pkg;

        `include "regs_stm.sv";

endpackage

module mcdf_tb;

        import reg_pkg::*;

        reg_mon mon1=new();
endmodule

类型二:直接在package中写入class,然后在module tb4_ref中import chnl_pkg::*;便可以使用package中的class了。

三、lab3

1、随机约束使用

class chnl_trans;
     rand bit[31:0] data[];
     rand int ch_id;
     constraint cstr{
      soft data.size inside {[4:8]};
      foreach(data[i]) data[i] == 'hC000_0000 + (this.ch_id<<24) + (this.pkt_id<<8) + i;
      soft ch_id == 0;
      };
endclass

//调用
chnl_trans t;
t=new();
assert(t.randomize with {ch_id == 5;})

2、邮箱使用

  • init、gen两个类声明:mailbox #(chnl_trans) req_mb; 注意:名字不一定一样,连接到同一对象即可通信。
  • init、gen两个类建立对象:function new()中req_mb=new()
  • 进行连接:init.req_mb = gen.req_mb;
class chnl_generator;
    mailbox #(chnl_trans) req_mb;

    ....

    function new();
      this.req_mb = new();
    endfunction

    ....

    task send_trans();
        ...
      this.req_mb.put(req);
        ...
    endtask

endclass

class chnl_initiator;
   
    mailbox #(chnl_trans) req_mb;
    
    ...

    task drive();
        forever begin
         ...
         this.req_mb.get(req);
         ...
        end
    endtask
  
   ...
    
endclass: chnl_initiator

///////////在上层进行连接。
class chnl_root_test;
    ...
    this.agents[i].init.req_mb = this.gen[i].req_mb;//指向建立的对象
    ...
endclass

3、软约束用chnl_generator想控制chnl_trans生成值

chnl_generator中对chnl_trans进行randomize,并通过邮箱给到chnl_initiator,在chnl_write()中写到dut。

进一步思考,通过软约束用chnl_generator想控制chnl_trans生成值,在chnl_basic_test中先对genp[i].randomize且用with进行约束,这样gen就不是默认的软约束值了。

4、关联数组启动仿真

父类句柄数组,然后关联数组如tests["chnl_basic_test"] = basic_test,父类句柄指向子类对象中的父类部分,调用父类的virtual run(),方法是在子类中进行的更新,用到了方法的多态。

5、mcdt_monitor

mcdt_monitor从mcdt(DUT)中获得id和data,通过mailbox给cheaker,然后out_mb.get(on)后,case(om.id)决定和哪个chnl_monitor.get(im)后data比较;

6、gen正常/非正常发送数据

       gen正常完成全部发送时,每个gen完成都会run_stop_flag.put(),三个通道全部完成run_stop_callback()启动结束仿真$finish();

       gen未正常完成全部发送时,用以下表示全部接受完停止下来

    fork
        wait(agents[0].vif.ch_margin == 'h20);
        wait(agents[1].vif.ch_margin == 'h20);
        wait(agents[2].vif.ch_margin == 'h20);
    join
    $finish();

7、约束constraint

constraint cstr {
                da.size() inside{3,4};
                da dist{10:=50,[10:20]:=20};
                }

8、其他

  • 字符串s={s,$sformatf("------",this.af)},
  • 仿真结束$finish
  • b变化且iff为真@事件,才可以触发 ,always@(b iff en) auto<=a;

四、lab4

以部分知识点的形式列出:

1、实验知识

  • fmt_trans中lenght的作用是接收DUT中的length,intf.length和intf.mon_ck.fmt_lenth是一致的;
  • 参考模型建立,通过monitor捕捉reg_trans进行设置更新参考模型值,参考模型输出打包后的chnl_trans和fmt_trans进行比较;
  • 控制寄存器CMD,CMD_ADDR,CMD_DATA_IN(31:0),CMD_DATA_OUT(31:0)约束是data和addr,cmd的关系,其中write为读是先发送CMD和ADDR,一个周期后在将数据给出reg_write()后 rsp=req.clone();reg与chnl_trans的关系是控制使能通道和优先级,与formatter的关系是控制数据包输出长度;
  • this本类中找不到去父类找,do_formatter(),do_data(),do_reg(),是完成数据传输前的设置工作,给上确定的发送数据个数,模式等等。

2、常见验证方法

  • 动态仿真
  • 静态仿真(STA):语法、语义、跨时钟域CDC(setup、hold)、形式验证
  • 效能验证:能耗、门控时钟、区域时钟、多核

3、事件、 旗语

  • 事件:   event e1,e2;    触发为->e1,等待触发为@e1或wait(e1.triggered)
  • 旗语:  semaphore sem;  分配1个钥匙sem=new(1),sem.get(1);.......  sem.put(1);形成每次都只能一个进行访问 

4、结构体、枚举

结构体 struct{bit[7:0],r,g,b} pixel 只是把数据组织到一起,不如用类;

使用方法:typedef  stuct{int a;byte b ...} my_struct_s;  先定义;

                   my_strut_s  st='{32'haaaa_aaaa,8'hbb,...}后赋值;

枚举使用

typedef enum {SHORT_FIFO, MED_FIFO, ....} fmt_fifo_t;  //定义
fmt_fifo_t  fifo;                                      //声明

case(req.fifo)                                         //一种使用方式
          SHORT_FIFO: this.fifo_bound = 64;
          MED_FIFO: this.fifo_bound = 256;
          LONG_FIFO: this.fifo_bound = 512;
          ULTRA_FIFO: this.fifo_bound = 2048;
endcase

5、其他

  • 过程语句 initial always
  • 语句块 begin fork
  • 线程 fork...join_any,for...join_none会执行完内部程序,想要在其未执行完前结束线程,指明fork:aa   ......   join   disable  aa;

五、lab5

1、covergroup根据测试功能点设计

设计

        covergroup coverport;

                coverpoint tr{xxxx};

        endgroup

例化  coverport = new();

触发 1、coverport.sample   2、covergroup coverport@(trans_ready)

例子如下:

 class mcdf_coverage;
    ......
    covergroup cg_mcdf_reg_write_read;
      addr: coverpoint reg_vif.mon_ck.cmd_addr {
        type_option.weight = 0;
        bins slv0_rw_addr = {`SLV0_RW_ADDR};
        bins slv1_rw_addr = {`SLV1_RW_ADDR};
      }
      cmd: coverpoint reg_vif.mon_ck.cmd {
        type_option.weight = 0;
        bins write = {`WRITE};
        bins read  = {`READ};
        bins idle  = {`IDLE};
      }
      cmdXaddr: cross cmd, addr {
        bins slv0_rw_addr = binsof(addr.slv0_rw_addr);
        bins slv1_rw_addr = binsof(addr.slv1_rw_addr);
        bins write        = binsof(cmd.write);
        bins read         = binsof(cmd.read );
        bins write_slv0_rw_addr  = binsof(cmd.write) && binsof(addr.slv0_rw_addr);
        bins write_slv1_rw_addr  = binsof(cmd.write) && binsof(addr.slv1_rw_addr);
        ...........
      }
    endgroup

task run();
        this.do_reg_sample();
    endtask

task do_reg_sample();
      forever begin
        @(posedge reg_vif.clk iff reg_vif.rstn);
        this.cg_mcdf_reg_write_read.sample();
      end
endtask

endclass

2、其他

  • $cast(A,B)认为B不变,将B的类型转换成A型后赋值给A
  • $cast(Ta,Tb)Ta句柄是Tb对象的子类句柄,成功转化的前提是Tb指向的对象是子类对象(既通过Tb=Ta操作后),是cast的目的是Ta指向Tb指向的对象,此时可以通过操作Ta句柄改变Tb指向对象中的内容。
  • mcdf_intf从dut.ctrl_regs_intf拿到slvo_en_o,并放到mcdf_pkg中去,当其为0时(通道关闭),不允许ch_valid===1同时ch_ready也为1;
  • $get_coverage()为平均覆盖率,type_option.weight=0为不统计该coverpaint的权重;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值