Monitors are for coverage collections and checkings.
A monitor is a passive component that can only observe.
A monitor (standard write method) must not modify the transaction or behavior.
A monitor write method must not block or consume any time.
OVM/UVM OOP Goal and Purpose:
- Standard strutural way to build test environment with standard components
- Reusable VIP
- Layered sequences
- Transaction-level communication
- Separate tests from test bench
- Configurable test bench
Connecting Monitor through Analysis_port
// // can extends ovm_component too // but choose a standard ovm_monitor helps in readability // class my_monitor extends ovm_monitor; `ovm_component_utils(my_monitor) ovm_analysis_port #(my_transaction) aport; virtual dut_if dut_vi; function new ... function void build; super.build(); aport = new("aport", this); endfunction : build // Standard run task includes, // 1. monitor/sampling the pins on DUT, reading the // 2. assembling the transaction // 3. send them to the rest of the verification environment task run; forever begin my_transaction tx; // handle to transaction // synchronize tx with clock used in DUT @(posedge dut_vi.clock); // factory call to create and populate the individual field with tx tx = my_transaction::type_id::create("tx"); tx.cmd = dut_vi.cmd; tx.addr = dut_vi.addr; tx.data = dut_vi.data; // Sends tx through analysis port out to any subscribers registered // in ovm environment aport.write(tx); end endtask // run endclass : my_monitor class my_agent extends ovm_agent; ... ovm_analysis_port #(my_transaction) aport; ... function void build; super.build(); aport = new("aport", this); // use factory method to create child component for this parent my_sequencer_h = my_sequencer::type_id::create ... my_driver_h = my_driver ::type_id::create ... my_monitor_h = my_monitor ::type_id::create ... endfunction: build function void connect; ... // child to parent connection to the analysis port my_monitor_h.aport.connect( aport ); endfunction: connect // Top level verification environment class my_env extends ovm_env; ... my_agent_h.aport.connect( my_subscriber_h.analysis_export ); ... function void build; super.build(); my_agent_h = my_agent ::type_id::create ... my_subscriber_h = my_subscriber::type_id::create ... endfunction: build function void connect; my_agent_h.aport.connect( my_subscriber_h.analysis_export ); endfunction: connect endclass : my_agent // A subscriber need to implement a "write" method/function // log transactions // collect coverage information // check and compare to expected behaviors class my_subscriber extends ovm_subscriber #(my_transaction); `ovm_component_utils(my_subscriber) ... function void write (my_transaction t); ... // Coverage registers bit cmd; int addr; int data; covergroup cover_bus; coverpoint cmd; coverpoint addr { bins a[16] = {[0:255]}; } coverpoint data { bins d[16] = {[0:255]}; } endgroup: cover_bus endfunction: write // use standard reporting to report the observation function void write(my_transaction t); ... cmd = t.cmd; addr = t.addr; data = t.data; cover_bus.sample(); ovm_report_info("ja", "Transaction received"); // ^ ^ ^ // Severity Originator/ID Text endfunction: write endclass : my_subscriber
No comments:
Post a Comment