关于我的UVM验证的第一个程序

这是我写的第一个测试

首先这个程序是TPO516的RX方向的一个component 我们管这个部分叫做FAS Regen. 它的作用就是给一个overhead被破坏掉的OTN frame重新插入正确的fas信号既f6f6f6282828,一共48bit.

这个程序一共有4部分组成,分别是:fas regen_env下的fasregen_checker和otu4_data_interface;在顶层中的otu_top_harness,以及top test case:FASRegenTest。

这个程序用了一个叫做two kingdom factory的trick 他的目的是利用OTU4DataInterface::type_id::set_type_override(FASRegenInterface::get_type());这句话来overide out4data_interface.即叫做custmize function。

第一步,借鉴别人的datainterface code:

/×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

`ifndef OTU4DataInterface_sv
`define OTU4DataInterface_sv


class OTU4DataInterface extends uvm_component;
  `uvm_component_utils(OTU4DataInterface)
  
  function new(string name = "", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  virtual task sync();
    
  endtask
  
  virtual task read(output bit [319:0] data, output bit enable);
    
  endtask 
  
endclass


`endif //OTU4DataInterface_sv

//可以看到在这个code中,sync()和 read()function都是空的 方便以后override。

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××/

第二步 在图—top— harness里面写入FasRegenInterface.这个程序是用来override datapathinterface的function。首先这个方程需要找到两个来个ntc_otu_top_320的接口。一个为enable一个为inpute data。在top320中RX PATH,INSERT FAS BYTE中enable 信号为rx_lite_frm_oof_fas_en,data为fas regen data. 将这两个信号赋给harness中的readfunction的 data和enable,这样就完成了data的进入dut的这个过程。这个语句always @(posedge sys_clk) fas_regen_enable <= dut.rx_lite_frm_oof_fas_en;使fas—en比regen—enable早一拍。

/×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

logic fas_regen_enable;


  always @(posedge sys_clk) fas_regen_enable <= dut.rx_lite_frm_oof_fas_en;


  class FASRegenInterface extends OTU4DataInterface;
    `uvm_component_utils(FASRegenInterface)


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


    virtual task sync();
      @(posedge sys_clk);
    endtask


    virtual task read(output bit[319:0] data, output bit enable);
      data = dut.rx_fas_regen_data;
      enable = fas_regen_enable;
    endtask
    
  endclass 

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

***************************************************************************************************************************/

下一个module是fas policy。他的作用是把6个fas bytes打乱,然后进入dut。

/**********************************************************************************************************************************

************************************************************************************************************************************

`ifndef FASPolicy_sv
`define FASPolicy_sv


class FASPolicy extends OTNPolicyBase;


  local rand int      random_frames;
  
  local bit           frame_count_flag       =   1'b0;
 
  local rand bit     [47:0] mask;
  local rand bit     bad_fas;
  local int          good_fas_dist = 1;  //deault value
  local int          bad_fas_dist = 1;


  /**
   * @literal constraints dictating the orders in which random variables are solved
   */
  constraint solve_order        {solve bad_fas before mask;}


  /**
   * @literal constraint - frame_size: Ensures that the number of frames is between 0 and 2000
   */
  constraint frame_size         {random_frames > 0; random_frames < 2000;}
      
  constraint fas_dist           {bad_fas dist {0:=good_fas_dist, 1:=bad_fas_dist};}//指定bad fas为1。good为2  weighted distribution,非配数据.
  constraint mask_value         {(bad_fas) -> mask != 48'h0; (!bad_fas) -> mask == 48'h0;} //bad fas = 1. mask dont equal to 0 and do xor with fas byte.-> is implication constrain, it is equal !A//B. 这句话中表示若左面真的是 badfas,则右面mask一定能够不为0. 若左面为goodfas 则右面mask一定为0


  /**
   * Constructor
   *
   * @param name -
   */


  function new(string name);
    super.new(name);
    setRandomizeControl(ON_TRANSACTION); //on transaction means random function will active when execute function begin.
  endfunction
  
  function void post_randomize();
    if(!frame_count_flag) begin
      this.max_lifecycle = random_frames;
    end
  endfunction
    
  /**
   * The number of frames for which the Policy will execute
   *
   * @param frame_count
   */
  
  function void setFrameCount(int frame_count);
    frame_count_flag = 1'b1;
    setMaxLifecycle(frame_count);
  endfunction   


  function void setRandomizeDist (int good_fas_dist, int bad_fas_dist);
    this.good_fas_dist = good_fas_dist;
    this.bad_fas_dist = bad_fas_dist;       // 把这个class里面的bad_fas_dist给了setrandomizeddist中的bad—fas-dist。这个变量不再这个文件中
  endfunction 


  /**
   *Execute is called once per frame. Physically inserts FAS bytes into the frame.
   *
   * @param txn -
   * @param cntxt -
   */
  
  function void execute(OTNFrame txn, ExecutionContext cntxt);
    if(!this.randomize()) `uvm_fatal("RANDOMIZATION_ERROR", "Failed to randomize FASPolicy")// 有random都需要这个语句来开始执行random function.
    `uvm_info("FASPolicy", $sformatf("bad_fas = %0d, mask = %0h", bad_fas, mask), UVM_MEDIUM)
    txn.getAlignment().setFAS(48'hf6f6f6282828 ^ mask); //因为mask是一个random,当mask为1 就开始破坏fas。
  endfunction
      
endclass


`endif //FASPolicy_sv

******************************************************************************************************************************************

******************************************************************************************************************************************/

下一部分是checker, 他负责检查从dut出来的数据, 看看是否是正确的fasbyte.

/****************************************************************************************************************************************************

******************************************************************************************************************************************************

`ifndef FASRegenChecker_sv
`define FASRegenChecker_sv


class FASRegenChecker extends uvm_component;
  `uvm_component_utils(FASRegenChecker)
   
  local OTU4DataInterface datapath;


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


  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    datapath = OTU4DataInterface::type_id::create("datapath", this);
  endfunction


  virtual task run_phase(uvm_phase phase);
    forever begin
      bit [319:0] data;  //一clock cycle有320byte

      bit         enable;


      datapath.sync();
      datapath.read(data, enable);


      if(enable) begin
        if(data[319:272] == 48'hf6f6f6282828) begin 进行比较 判断
           `uvm_info("CHECKER", "FAS found - Simulation of the current frame is passing!", UVM_MEDIUM)
        end
        else begin
           `uvm_error("CHECKER", "FAS not correct - Simulation of the current frame fails!")
        end
      end
    end
  endtask


endclass


`endif //FASRegenChecker_sv

*********************************************************************************************************************************************************

**********************************************************************************************************************************************************/

下一个就是顶层的testcase,这个需要在questa 里面运行

/**************************************************************************************************************************************************

****************************************************************************************************************************************************

`ifndef FASRegenTest_sv
`define FASRegenTest_sv


class FASRegenTest extends BaseTest;                                                 //因为我没有env这个class所以我需要extends BaseTest 这里包含了环境配置
  `uvm_component_utils(FASRegenTest)


  protected FASRegenChecker check;
  protected ProcessStack       stack;                     //policy need stack to run
  protected FASPolicy          good_fas;                  //例化policy
  protected FASPolicy          fas_corrupt;
  protected Node               node;                             //在mld模块右侧
  function new(string name = "", uvm_component parent = null);
    super.new(name, parent);
  endfunction


  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);                                                                                            //    不是 super。phase                
    check = FASRegenChecker::type_id::create("check", this);                                     //声明的变量都需要在这里contruct
    good_fas = new("good_fas");
    fas_corrupt = new("fas_corrupt");
  endfunction


virtual function void connect_phase(uvm_phase phase);
    Node nodes [$];
    MasterGraph graph = Framework::getInstance().getMasterGraph();
    graph.getTransceiverNodes("mld_xcvr", nodes);
    node = nodes[0];
  
    stack = ProcessStack::construct("OTNFrame", node, "mld_xcvr", ProcessStack::SRC);
    good_fas.setRandomizeDist(1, 0);                                                        //全是 goodfas
    good_fas.setFrameCount(250);                                                              // goodfas运行250frame
    fas_corrupt.setRandomizeDist(2, 5);                                                       //badfas domains 2/7,goodfas 5/7
    fas_corrupt.setFrameCount(1000);                                                            //对1000frame 进行corrupt
    stack.add(good_fas).next().add(fas_corrupt).finish();
endfunction




  virtual task main_phase(uvm_phase phase);
   phase.raise_objection(this);
   stack.start(phase, 1'b0);
   phase.drop_objection(this);
  endtask


endclass


`endif //FASRegenTest_sv

**************************************************************************************************************************************************

**************************************************************************************************************************************************/



你可能感兴趣的:(关于我的UVM验证的第一个程序)