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