UVM Monitor

2023-12-01
UVM

What is a monitor?

UVM monitor負責從design interface擷取訊號活動(activity),並將其轉換為可傳送至其他component的data object。
為此,需要滿足以下條件:

  • 一個virtual interface handle,用於監視此monitor正在嘗試監視的實際interface。
  • 宣言一個TLM Analysis Port,用於向其他人廣播capture到的資料。

What does a UVM monitor do?

UVM monitorr繼承了uvm_monitor,具有以下功能:

  • 透過virtual interface收集bus或signal的資訊
  • 收集的數據可用於protocol檢查和覆蓋(coverage)
  • 透過analysis port將收集的數據匯出

UVM monitor的功能應該要盡量只有基本且一定需要的基本監控。它可能具有用於基本啟用/停用protocol的checking和coverage collection。比較high level的functional的checking應該要在scoreboard。

Steps to create a UVM monitor

  1. 建立一個繼承uvm_monitor的class,然後註冊到factory上

    1
    2
    3
    4
    5
    6
    7
    8
    class my_monitor extends uvm_monitor;

    `uvm_component_utils (my_monitor)

    function new (string name = "my_monitor", uvm_component parent = null);
    super.new (name, parent);
    endfunction
    endclass
  2. 宣告analysis port和virtual interface handle

    1
    2
    3
    4
    5
    6
    7
    8
    class my_monitor extends uvm_monitor;
    ...
    // Actual interface object is later obtained by doing a get() call on uvm_config_db
    virtual if_name vif;

    uvm_analysis_port #(my_data) mon_analysis_port;
    ...
    endclass
  3. 建置UVM monitor,並在build phase建立analysis port的instance

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class my_monitor extends uvm_monitor;
    ...
    virtual function void build_phase (uvm_phase phase);
    super.build_phase (phase);

    mon_analysis_port = new("mon_analysis_port", this);

    // Get virtual interface handle from the configuration DB
    if (! uvm_config_db #(virtual if_name)::get(this, "", "vif", vif)) begin
    `uvm_error (get_type_name (), "DUT interface not found")
    end
    endfunction
    ...
    endclass
  4. Code the run_phase

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class my_monitor extends uvm_monitor;
    ...
    virtual task run_phase (uvm_phase phase);
    // Fork off multiple threads "if" required to monitor the interface, for example:
    fork
    // Thread 1: Monitor address channel
    // Thread 2: Monitor data channel, populate "obj" data object
    // Thread 3: Monitor control channel, decide if transaction is over

    // Thread 4: When data transfer is complete, send captured information
    // through the declared analysis port
    mon_analysis_port.write(obj);
    join_none
    endtask
    ...
    endclass