zoukankan      html  css  js  c++  java
  • UVM Primer

    基础知识

    uvm_component有两大特性,一是通过在new的时候指定parent参数来形成一种树形的组织结构,二是有phase的自动执行特点

    要用UVM 干活 , 你需要自如的定义和例化 UVM 组件 . 这里是步骤

    • 第 1 步 : 从 uvm_component 类或其子类继承定义你的组件
    • 第 2 步 : 用 uvm_component_utils() 宏注册这个类到 Factory
    • 第 3 步 : 提供 uvm_component 构造器
    • 第 4 步 : 在必要时重写 UVM 的 phase 方法

    写UVM Test 的时候 , 我创建了 run_phase() 方法来解释 UVM 会自动调用 run_phase()来启动仿真 . run_phase() 方法是 UVM phase 方法中的一个

    所有UVMcomponent都继承了这些phase方法。UVM在所有的component里以设定的顺序调用这些 phase 方法。你可以在你的component里重写这些phase方法,然后UVM会按顺序调用。

    UVM按照以下顺序调用 phase 方法

    • function void build_phase   UVM用这个方法自顶向下建立你的 验证平台 . 你要在这个方法里例化你的 uvm_component , 如果在别的方法里例化的话 , 你会得到 UVM 的致命报错
    • function void connect_phase   connect phase 把各个模块连接到一起 . 我们会在后面的章节学习连接
    • function void end_of_elaboration_phase   UVM在所有 component 都就位并连接好以后调用这个方法 , 需要在 UVM 层次设定完之后再对 验证平台 进行调整的话可以用这个 phase.
    • task run_phase   UVM会在各自的线程调用这个 task. 验证平台 中的 run_phase() 是 同时 运行的 , 所以你不知道那个会最先启动
    • function void report_phase   这个phase 会在最后一个 objection 撤销后运行,然后 测试用例就结束了。你可以用来报告结果

    tinyalu_pkg.sv

    package tinyalu_pkg;
       import uvm_pkg::*;
    `include "uvm_macros.svh"
       
          typedef enum bit[2:0] {no_op  = 3'b000,
                              add_op = 3'b001, 
                              and_op = 3'b010,
                              xor_op = 3'b011,
                              mul_op = 3'b100,
                              rst_op = 3'b111} operation_t;
    
       virtual tinyalu_bfm bfm_g;
       
    
    `include "coverage.svh"
    `include  "random_tester.svh"
    `include "add_tester.svh"   
    `include "scoreboard.svh"
    `include "random_test.svh"
    `include "add_test.svh"
       
       
    endpackage : tinyalu_pkg

     tinyalu_bfm.sv(和UVM test那一节一样)

    interface tinyalu_bfm;
       import tinyalu_pkg::*;
    
       byte         unsigned        A;
       byte         unsigned        B;
       bit          clk;
       bit          reset_n;
       wire [2:0]   op;
       bit          start;
       wire         done;
       wire [15:0]  result;
       operation_t  op_set;
    
       assign op = op_set;
    
       task reset_alu();
          reset_n = 1'b0;
          @(negedge clk);
          @(negedge clk);
          reset_n = 1'b1;
          start = 1'b0;
       endtask : reset_alu
       
    
    
       task send_op(input byte iA, input byte iB, input operation_t iop, shortint alu_result);
          if (iop == rst_op) begin
             @(negedge clk);
             op_set = iop;
             @(posedge clk);
             reset_n = 1'b0;
             start = 1'b0;
             @(posedge clk);
             #1;
             reset_n = 1'b1;
          end else begin
             @(negedge clk);
             op_set = iop;
             A = iA;
             B = iB;
             start = 1'b1;
             if (iop == no_op) begin
                @(posedge clk);
                #1;
                start = 1'b0;           
             end else begin
                do
                  @(negedge clk);
                while (done == 0);
                alu_result = result;
                start = 1'b0;
             end
          end // else: !if(iop == rst_op)
          
       endtask : send_op
    
       initial begin
          clk = 0;
          forever begin
             #10;
             clk = ~clk;
          end
       end
    
    
    endinterface : tinyalu_bfm

    tb_classes

    coverage.svh

    class coverage extends uvm_component;
       `uvm_component_utils(coverage)
    
       virtual tinyalu_bfm bfm;
    
       byte         unsigned        A;
       byte         unsigned        B;
       operation_t  op_set;
    
       covergroup op_cov;
    
          coverpoint op_set {
             bins single_cycle[] = {[add_op : xor_op], rst_op,no_op};
             bins multi_cycle = {mul_op};
    
             bins opn_rst[] = ([add_op:no_op] => rst_op);
             bins rst_opn[] = (rst_op => [add_op:no_op]);
    
             bins sngl_mul[] = ([add_op:xor_op],no_op => mul_op);
             bins mul_sngl[] = (mul_op => [add_op:xor_op], no_op);
    
             bins twoops[] = ([add_op:no_op] [* 2]);
             bins manymult = (mul_op [* 3:5]);
    
    
          }
    
       endgroup
    
       covergroup zeros_or_ones_on_ops;
    
          all_ops : coverpoint op_set {
             ignore_bins null_ops = {rst_op, no_op};}
    
          a_leg: coverpoint A {
             bins zeros = {'h00};
             bins others= {['h01:'hFE]};
             bins ones  = {'hFF};
          }
    
          b_leg: coverpoint B {
             bins zeros = {'h00};
             bins others= {['h01:'hFE]};
             bins ones  = {'hFF};
          }
    
          op_00_FF:  cross a_leg, b_leg, all_ops {
             bins add_00 = binsof (all_ops) intersect {add_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins add_FF = binsof (all_ops) intersect {add_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins and_00 = binsof (all_ops) intersect {and_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins and_FF = binsof (all_ops) intersect {and_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins xor_00 = binsof (all_ops) intersect {xor_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins xor_FF = binsof (all_ops) intersect {xor_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins mul_00 = binsof (all_ops) intersect {mul_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins mul_FF = binsof (all_ops) intersect {mul_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins mul_max = binsof (all_ops) intersect {mul_op} &&
                            (binsof (a_leg.ones) && binsof (b_leg.ones));
    
             ignore_bins others_only =
                                      binsof(a_leg.others) && binsof(b_leg.others);
    
          }
    
    endgroup
       
    
       function new (string name, uvm_component parent);
          super.new(name, parent);
          op_cov = new();
          zeros_or_ones_on_ops = new();
       endfunction : new
    
    function void build_phase(uvm_phase phase);
    
     if(!uvm_config_db #(virtual tinyalu_bfm)::get(null, "*","bfm", bfm))
            $fatal("Failed to get BFM");
    endfunction : build_phase
    
       task run_phase(uvm_phase phase);
          forever begin  : sampling_block
             @(negedge bfm.clk);
             A = bfm.A;
             B = bfm.B;
             op_set = bfm.op_set;
             op_cov.sample();
             zeros_or_ones_on_ops.sample();
          end : sampling_block
       endtask : run_phase
          
    endclass : coverage

    scoreboard.svh

    class scoreboard extends uvm_component;
       `uvm_component_utils(scoreboard);
    
       virtual tinyalu_bfm bfm;
    
       function new (string name, uvm_component parent);
          super.new(name, parent);
       endfunction : new
    
    function void build_phase(uvm_phase phase);
    
     if(!uvm_config_db #(virtual tinyalu_bfm)::get(null, "*","bfm", bfm))
            $fatal("Failed to get BFM");
    endfunction : build_phase
    
       task run_phase(uvm_phase phase);
          shortint predicted_result;
          forever begin : self_checker
             @(posedge bfm.done) 
               case (bfm.op_set)
                 add_op: predicted_result = bfm.A + bfm.B;
                 and_op: predicted_result = bfm.A & bfm.B;
                 xor_op: predicted_result = bfm.A ^ bfm.B;
                 mul_op: predicted_result = bfm.A * bfm.B;
               endcase // case (op_set)
             
             if ((bfm.op_set != no_op) && (bfm.op_set != rst_op))
               if (predicted_result != bfm.result)
                 $error ("FAILED: A: %0h  B: %0h  op: %s result: %0h",
                         bfm.A, bfm.B, bfm.op_set.name(), bfm.result);
          end : self_checker
       endtask : run_phase
    endclass : scoreboard

    add_tester.svh

    class add_tester extends random_tester;
       `uvm_component_utils(add_tester)
             
       function new (string name, uvm_component parent);
          super.new(name, parent);
       endfunction : new
    
       function operation_t get_op();
          bit [2:0] op_choice;
          return add_op;
       endfunction : get_op
    
    endclass : add_tester

    ramdom_tester.svh

    class random_tester extends uvm_component;
       `uvm_component_utils (random_tester)
    
       virtual tinyalu_bfm bfm;
    
       function new (string name, uvm_component parent);
          super.new(name, parent);
       endfunction : new
       
       virtual function operation_t get_op();
          bit [2:0] op_choice;
          op_choice = $random;
          case (op_choice)
            3'b000 : return no_op;
            3'b001 : return add_op;
            3'b010 : return and_op;
            3'b011 : return xor_op;
            3'b100 : return mul_op;
            3'b101 : return no_op;
            3'b110 : return rst_op;
            3'b111 : return rst_op;
          endcase // case (op_choice)
       endfunction : get_op
    
       virtual      function byte get_data();
          bit [1:0] zero_ones;
          zero_ones = $random;
          if (zero_ones == 2'b00)
            return 8'h00;
          else if (zero_ones == 2'b11)
            return 8'hFF;
          else
            return $random;
       endfunction : get_data
       
       function void build_phase(uvm_phase phase);
          if(!uvm_config_db #(virtual tinyalu_bfm)::get(null, "*","bfm", bfm))
            $fatal("Failed to get BFM");
       endfunction : build_phase
    
       task run_phase(uvm_phase phase);
          byte         unsigned        iA;
          byte         unsigned        iB;
          operation_t                  op_set;
          shortint     result;
          
          phase.raise_objection(this);
          bfm.reset_alu();
          repeat (1000) begin : random_loop
             op_set = get_op();
             iA = get_data();
             iB = get_data();
             bfm.send_op(iA, iB, op_set, result);
          end : random_loop
          #500;
          phase.drop_objection(this);
       endtask : run_phase
       
       
    endclass : random_tester

    random_test.svh

    class random_test extends uvm_test;
       `uvm_component_utils(random_test);
    
       random_tester tester_h;
       coverage      coverage_h;
       scoreboard    scoreboard_h;
    
       function void build_phase(uvm_phase phase);  //重载了build_phase然后例化了三个验证平台组件
          tester_h      = new("tester_h", this);
          coverage_h    = new("coverage_h",    this);
          scoreboard_h  = new("scoreboard_h",    this);
       endfunction : build_phase
       
       function new (string name, uvm_component parent);
          super.new(name,parent);
       endfunction : new
    
    endclass

    add_test.svh

    class add_test extends random_test;   //add_test继承了random_test
       `uvm_component_utils(add_test);
    
       add_tester tester_h;
       
       function new (string name, uvm_component parent);
          super.new(name,parent);
       endfunction : new
      
    endclass

    用UVM启动仿真

    top.sv(和UVM test那一节一样)

    module top;
       import uvm_pkg::*;
    `include "uvm_macros.svh"
    
       import   tinyalu_pkg::*;
    `include "tinyalu_macros.svh"
    
       tinyalu_bfm       bfm();
       tinyalu DUT (.A(bfm.A), .B(bfm.B), .op(bfm.op), 
                    .clk(bfm.clk), .reset_n(bfm.reset_n), 
                    .start(bfm.start), .done(bfm.done), .result(bfm.result));
    
    initial begin
      uvm_config_db #(virtual tinyalu_bfm)::set(null, "*", "bfm", bfm);
      run_test();  //run_test()方法从命令行得到一个类名字符串,然后用UVM Factory来创建这个类的测试对象,然后这个测试对象开始运行测试
    end
    
    endmodule : top
  • 相关阅读:
    查看mysql版本的四种方法及常用命令
    newInstance和new的区别(good)
    Citrix 服务器虚拟化之六 Xenserver虚拟机创建与快照
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 前缀表达式
    Java实现 蓝桥杯 算法训练 前缀表达式
  • 原文地址:https://www.cnblogs.com/yiyedada/p/12372686.html
Copyright © 2011-2022 走看看