Nothing Special   »   [go: up one dir, main page]

Uvm

Download as pdf or txt
Download as pdf or txt
You are on page 1of 47
At a glance
Powered by AI
The key takeaways are that UVM is a standard methodology for verification that supports constrained random testing and coverage-driven verification. It provides a base class library and methodology for reuse and consistency.

UVM is the Universal Verification Methodology, which is a SystemVerilog based methodology for verification. Its main features include supporting constrained random and coverage-driven verification, being an open-source base class library, and being an Accellera standard supported by major simulator vendors. It aims to provide best practices, consistency, and reuse.

Some of the challenges of UVM include the large number of classes in its base class library, questions not being fully answered by the documentation, and different ways to implement the same tasks requiring a methodology. Learning UVM and using its features properly requires time and effort.

Easier UVM – Making Verification

Methodology More Productive

John Aynsley, Dr David Long, Doulos


What is UVM?

• The Universal Verification Methodology for SystemVerilog

• Supports constrained random, coverage-driven verification

• An open-source SystemVerilog base class library

• An Accellera standard!

• Supported by all major simulator vendors

© Accellera Systems Initiative 2


Why UVM?

• Best practice
• Consistency, uniformity, don't reinvent the wheel, avoid pitfalls

• Reuse
• Verification IP, verification environments, tests, people, knowhow

© Accellera Systems Initiative 3


UVM Itself is Challenging

• Doulos training

Verilog SystemVerilog for Verification UVM Adopter

4 days 4 days

What next?

Tools?
Coaching?
Guidelines?

© Accellera Systems Initiative 4


UVM Itself is Challenging

• ~ 300 classes in UVM Base Class Library

• The UVM documentation does not answer all the questions

• There are many ways to do the same thing - need a methodology

© Accellera Systems Initiative 5


Easier UVM

• Coding guidelines – "One way to do it"

• Automatic code generator

• Help individuals and project teams

• learn UVM and avoid pitfalls

• become productive with UVM (saves ~ 6 weeks)

• use UVM consistently

• Reduce the burden of supporting UVM code

© Accellera Systems Initiative 6


Coding Guidelines
Consistency
Avoiding pitfalls
Reusability
High quality verification

Naming conventions and code structure Where to do certain things

Restrictions on feature usage Macros, policy objects,


pre/post_body
Canonical structure for the component hierarchy Envs, agents, subscribers,
ports/exports, interfaces
Consistent pattern for writing classes and instantiating objects Components, transaction,
sequences, factory
Specific way to use configuration objects Top-down build

Specific way to use sequences and tests For constrained random

© Accellera Systems Initiative 7


www.doulos.com

© Accellera Systems Initiative 8


Constrained Random Verification

Does it work?
Constrained random
stimulus

Are we done?

Increase coverage

© Accellera Systems Initiative 9


UVM Verification Environment
Test Config
Env

Config Config
Class-based

Test
harness
Module-based

© Accellera Systems Initiative 10


UVM Highlights
Test vs Env Checking Coordination

Factory overrides Test Config


Env

Coverage
Configuration
Transaction-Level
Connections Config Config
Stimulus

Agent per-interface Transactions


contain
essential data

Objections Pin wiggles


Test
harness
Message reporting
Register layer

© Accellera Systems Initiative 11


As a Test Writer ...
Test Checking

Test Config
Env
Factory overrides
Configuration

Coverage
Config Config Stimulus

Objections Test
Assertions
harness
Message reporting

© Accellera Systems Initiative 12


Quasi-static vs Dynamic Objects

© Accellera Systems Initiative 13


Quasi-static vs Dynamic Objects

© Accellera Systems Initiative 14


Quasi-static vs Dynamic Objects

© Accellera Systems Initiative 15


Quasi-static vs Dynamic Objects

Pattern 1
class my_comp extends uvm_component;
`uvm_component_utils(my_comp)

function new (string name, uvm_component parent); Pattern 2


super.new(name, parent);
endfunction class my_tx extends uvm_sequence_item;
... `uvm_object_utils(my_tx)
endclass
function new (string name = "");
super.new(name);
endfunction
...
endclass
© Accellera Systems Initiative 16
Easier UVM Code Generator Files

clkndata.tpl Interface template file

common.tpl Common template file

pinlist Pin list file

mydut/files.f List of SystemVerilog files and command line flags

mydut/mydut.sv SystemVerilog source file for the DUT

include/clkndata_do_drive.sv Implementation of driver

gen Script to run the code generator

run Script to run the simulator

© Accellera Systems Initiative 17


Template Files
Interface template file
Test Config
agent_name = clkndata Env
trans_item = data_tx
trans_var = rand byte data;

driver_inc = clkndata_do_drive.sv Config Config

if_port = logic clk;


if_port = byte data;
if_clock = clk

Test
Common template file harness

dut_source_path = mydut
inc_path = include
dut_top = mydut
dut_pfile = pinlist

© Accellera Systems Initiative 18


Transaction Class
`ifndef CLKNDATA_SEQ_ITEM_SV
`define CLKNDATA_SEQ_ITEM_SV
Interface template file
class data_tx extends uvm_sequence_item; trans_item = data_tx
`uvm_object_utils(data_tx) trans_var = rand byte data;

rand byte data;

extern function new(string name="");


extern function void do_copy(uvm_object rhs);
extern function bit do_compare(uvm_object rhs, uvm_comparer comparer);
extern function string convert2string();
extern function void do_print(uvm_printer printer);
extern function void do_record(uvm_recorder recorder);

endclass : data_tx

© Accellera Systems Initiative 19


Transaction Methods
function data_tx::new(string name = "");
super.new(name);
endfunction : new

function void data_tx::do_copy(uvm_object rhs);


data_tx rhs_;
if(!$cast(rhs_, rhs))
`uvm_fatal("do_copy", "cast of rhs object failed") Standard reporting
super.do_copy(rhs);
data = rhs_.data;
endfunction : do_copy

function bit data_tx::do_compare(uvm_object rhs, uvm_comparer comparer);


data_tx rhs_;
if(!$cast(rhs_, rhs))
`uvm_fatal("do_copy", "cast of rhs object failed")
return super.do_compare(rhs, comparer) && data == rhs_.data;
endfunction : do_compare

function string data_tx::convert2string();


string s; $sformat(s, "%s\n", super.convert2string());
$sformat(s, "%s\n data = \t%0h\n", get_full_name(), data);
return s;
endfunction : convert2string

© Accellera Systems Initiative 20


Transaction Methods

function void data_tx::do_print(uvm_printer printer);


if(printer.knobs.sprint == 0)
`uvm_info(get_type_name(), convert2string(), UVM_MEDIUM) Standard reporting
else
printer.m_string = convert2string();
endfunction : do_print

function void data_tx::do_record(uvm_recorder recorder);


super.do_record(recorder);
`uvm_record_field("data", data)
endfunction : do_record

`endif // CLKNDATA_SEQ_ITEM_SV

© Accellera Systems Initiative 21


Agent Class
class clkndata_agent extends uvm_agent;
`uvm_component_utils(clkndata_agent)
Config
uvm_analysis_port #(data_tx) ap; TLM port
clkndata_config m_cfg;
clkndata_sequencer m_sequencer;
clkndata_driver m_driver;
clkndata_monitor m_monitor;

extern function new(string name, uvm_component parent);


extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);

endclass : clkndata_agent

function clkndata_agent::new(string name, uvm_component parent);


super.new(name, parent);
endfunction : new

© Accellera Systems Initiative 22


Execution Phases
Consistent execution phases

Env

© Accellera Systems Initiative 23


Agent Methods
function void clkndata_agent::build_phase(uvm_phase phase);
if(!uvm_config_db #(clkndata_config)::get(this, "", "clkndata_config", m_cfg))
`uvm_error(get_type_name(), "clkndata config not found")
...
m_monitor = clkndata_monitor::type_id::create("m_monitor",this);
ap = new("ap", this);
if (m_cfg.is_active == UVM_ACTIVE) Active vs passive
begin
m_driver = clkndata_driver ::type_id::create("m_driver",this);
m_sequencer = clkndata_sequencer::type_id::create("m_sequencer",this);
end
endfunction : build_phase

function void clkndata_agent::connect_phase(uvm_phase phase);


if(m_cfg.vif == null)
`uvm_fatal(get_type_name(), "clkndata virtual interface is not set!")
m_monitor.vif = m_cfg.vif;
m_monitor.ap.connect(ap); TLM connections
if (m_cfg.is_active == UVM_ACTIVE)
begin
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
m_driver.vif = m_cfg.vif;
end
endfunction : connect_phase

© Accellera Systems Initiative 24


Interface and Test Harness
Test
Env

Class-based

Virtual
interfaces
Test
harness
Module-based

© Accellera Systems Initiative 25


Interface and Test Harness
module top_th; Interface template file
timeunit 1ns;
if_port = logic clk;
timeprecision 1ps;
if_port = byte data;
if_clock = clk
logic clock = 0;
logic reset;
interface clkndata_if();
clkndata_if clkndata_if0(); import clkndata_pkg::*;
logic clk;
assign clkndata_if0.clk = clock; byte data;
endinterface : clkndata_if
mydut uut (
.clk(clkndata_if0.clk), Pin list file
.data(clkndata_if0.data) !clkndata_if
); clk clk
data data
//example clock generator process
always #10 clock = ~clock;

//example reset generator process


initial
begin
reset=0; //active low reset for this example
#75 reset=1;
end
endmodule
© Accellera Systems Initiative 26
Driver Class
class clkndata_driver extends uvm_driver #(data_tx);
`uvm_component_utils(clkndata_driver)

virtual clkndata_if vif;

extern function new(string name, uvm_component parent);


extern task run_phase(uvm_phase phase);
extern function void report_phase(uvm_phase phase);
extern task do_drive();

endclass : clkndata_driver

function clkndata_driver::new(string name, uvm_component parent);


super.new(name, parent);
endfunction : new

© Accellera Systems Initiative 27


Driver Methods
task clkndata_driver::run_phase(uvm_phase phase);
`uvm_info(get_type_name(), "run_phase", UVM_HIGH)
forever
begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(), {"req item\n", req.sprint}, UVM_MEDIUM)

do_drive();

$cast(rsp, req.clone());
seq_item_port.item_done();
end
endtask : run_phase

`include "clkndata_do_drive.sv"

task clkndata_driver::do_drive();
vif.data <= req.data;
@(posedge vif.clk); Pin wiggles
endtask

© Accellera Systems Initiative 28


Top-Level Module
module top_tb;

timeunit 1ns;
timeprecision 1ps;

import uvm_pkg::*;
`include "uvm_macros.svh"

import top_test_pkg::*;

top_th th();

initial
begin
uvm_config_db #(virtual clkndata_if)::set(
null, "uvm_test_top", "clkndata_if", th.clkndata_if0); config_db

run_test();
end
endmodule

© Accellera Systems Initiative 29


Stimulus

Test Config
Env

Config Config Sequences

Test
harness

© Accellera Systems Initiative 30


Sequence Base Class

class clkndata_base_seq extends uvm_sequence #(data_tx);


`uvm_object_utils(clkndata_base_seq)

clkndata_config cfg;
data_tx item;

extern function new(string name = "");


extern task body();

endclass : clkndata_base_seq

function clkndata_base_seq::new(string name = "");


super.new(name);
endfunction : new

task clkndata_base_seq::body();
`uvm_info(get_type_name(), "clkndata_base_seq", UVM_MEDIUM)
endtask : body
Placeholder, going to be overridden

© Accellera Systems Initiative 31


Extended Sequence Class
class clkndata_default_seq extends clkndata_base_seq;
`uvm_object_utils(clkndata_default_seq)

rand byte data;

extern function new(string name = "");


extern task body();

endclass : clkndata_default_seq

function clkndata_default_seq::new(string name = "");


super.new(name);
endfunction : new

task clkndata_default_seq::body();
`uvm_info(get_type_name(), "default sequence starting", UVM_MEDIUM)
super.body();
item = data_tx::type_id::create("item");
start_item(item);
if ( !item.randomize() )
`uvm_warning(get_type_name(), "randomization failed!")
finish_item(item);
`uvm_info(get_type_name(), "default sequence completed", UVM_MEDIUM)
endtask : body

© Accellera Systems Initiative 32


Top-Level Env
class top_env extends uvm_env;
`uvm_component_utils(top_env) Config
Env
clkndata_agent m_clkndata_agent;
clkndata_config m_clkndata_cfg;
clkndata_coverage m_clkndata_coverage;
top_config m_cfg; Config
//top_scoreboard m_scoreboard;
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
endclass : top_env
...
function void top_env::build_phase(uvm_phase phase);
...
if (!uvm_config_db #(top_config)::get(this, "", "top_config", m_cfg))
`uvm_error(get_type_name(), "unable to get top_config")

m_clkndata_cfg = new("m_clkndata_cfg"); config_db


m_clkndata_cfg.vif = m_cfg.clkndata_vif;
m_clkndata_cfg.is_active = m_cfg.is_active_clkndata;
uvm_config_db #(clkndata_config)::set(this, "m_clkndata_agent", ...
m_clkndata_agent = clkndata_agent ::type_id::create(...
m_clkndata_coverage = clkndata_coverage::type_id::create(...
endfunction : build_phase
...

© Accellera Systems Initiative 33


Configuration Class

class clkndata_config extends uvm_object;


// Don't register with the factory!

virtual clkndata_if vif;

uvm_active_passive_enum is_active = UVM_ACTIVE;

extern function new(string name = "");


//You may add more arguments to the constructor

endclass : clkndata_config

function clkndata_config::new(string name = "");


super.new(name);
endfunction : new

© Accellera Systems Initiative 34


Summary of Coding Idioms
Pattern 1
Pattern 2a
class my_comp extends uvm_component;
`uvm_component_utils(my_comp) class my_tx extends uvm_sequence_item;
`uvm_object_utils(my_tx)
function new(string name, uvm_component parent);
super.new(name, parent); function new (string name = "");
endfunction super.new(name);
endfunction
function void build_phase(...);
... function bit do_compare(...);
endclass ...
Pattern 2b
endclass
class my_seq extends uvm_sequence #(my_tx); Pattern 2c
`uvm_object_utils(my_seq) class my_config extends uvm_object;
`uvm_object_utils(my_config)
function new(string name = "");
super.new(name); function new(string name = "");
endfunction super.new(name);
... endfunction
task body; ...
... endclass
endclass

© Accellera Systems Initiative 35


Virtual Sequence
class top_default_seq extends top_base_seq;
`uvm_object_utils(top_default_seq)
Env
extern function new(string name = "");
extern task body();
endclass : top_default_seq
...

task top_default_seq::body();
super.body();
repeat(m_seq_count)
begin
fork
if (m_clkndata_agent.m_cfg.is_active == UVM_ACTIVE)
begin
clkndata_base_seq seq;
seq = clkndata_base_seq::type_id::create("seq");
seq.randomize();
seq.start(m_clkndata_agent.m_sequencer, this);
end
... // Other agents
join
`uvm_info(get_type_name(), "default sequence completed", UVM_MEDIUM)
end
endtask : body

© Accellera Systems Initiative 36


Monitor Class
class clkndata_monitor extends uvm_monitor;
`uvm_component_utils(clkndata_monitor)
Env
virtual clkndata_if vif;
uvm_analysis_port #(data_tx) ap; TLM port
clkndata_config cfg;
data_tx trans;

extern function new(string name, uvm_component parent);


extern function void build_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
extern task do_mon();
endclass : clkndata_monitor
...
task clkndata_monitor::run_phase(uvm_phase phase);
data_tx trans_clone;
`uvm_info(get_type_name(), "run_phase", UVM_MEDIUM)
trans = data_tx::type_id::create("trans");
do_mon();
endtask : run_phase task clkndata_monitor::do_mon();
forever @(posedge vif.clk)
begin
trans.data = vif.data; User-defined
ap.write(trans);
end
endtask : do_mon
© Accellera Systems Initiative 37
Subscriber Class
class clkndata_coverage extends uvm_subscriber #(data_tx);
`uvm_component_utils(clkndata_coverage)
bit is_covered; Env
data_tx item;

covergroup clkndata_cov;
option.per_instance = 1;
`include "clkndata_cover_inc.sv"
endgroup

extern function new(string name, uvm_component parent);


extern function void write(input data_tx t);
extern function void report_phase(uvm_phase phase);
endclass : clkndata_coverage
...

function void clkndata_coverage::write(input data_tx t);


item = t;
clkndata_cov.sample(); cp_data: coverpoint item.data {
bins
if (clkndata_cov.get_inst_coverage() >=zero
100)= is_covered
{0}; = 1;
endfunction : write bins > bins negative = { [-128:-1] };
bins positive = { [1:127] };
option.at_least = 16; User-defined
}

© Accellera Systems Initiative 38


Constrained Random Generation
• Populate/randomize configuration objects
Test

• Set factory overrides


• Top-down build

Env

• Factory-made sequences
• Factory-made transactions
• Constraints

© Accellera Systems Initiative 39


Test Base Class
class top_base_test extends uvm_test;
`uvm_component_utils(top_base_test)

top_config m_cfg;
top_env m_env;

extern function new(string name, uvm_component parent);


extern function void build_phase(uvm_phase phase);
extern function void start_of_simulation_phase(uvm_phase phase);
endclass : top_base_test
...

function void top_base_test::build_phase(uvm_phase phase);


m_cfg = new("m_cfg");
if(!uvm_config_db #(virtual clkndata_if)::get(..., m_cfg.clkndata_vif) )
`uvm_error(get_type_name(), "no virtual interface found")
m_cfg.is_active_clkndata = UVM_ACTIVE; config_db
uvm_config_db #(top_config)::set(this, "m_env", "top_config", m_cfg);

m_env = top_env::type_id::create("m_env", this);


endfunction : build_phase

© Accellera Systems Initiative 40


Test Class
class top_test extends top_base_test;
`uvm_component_utils(top_test)

extern function new(string name, uvm_component parent);


extern function void build_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
endclass : top_test

function top_test::new(string name, uvm_component parent);


super.new(name, parent);
endfunction : new

function void top_test::build_phase(uvm_phase phase);

top_base_seq::type_id::set_type_override(top_default_seq::get_type());

clkndata_base_seq::type_id::set_type_override(
clkndata_default_seq::get_type());
super.build_phase(phase);
endfunction : build_phase Factory overrides

© Accellera Systems Initiative 41


Test Class

task top_test::run_phase(uvm_phase phase);


top_base_seq vseq;
vseq = top_base_seq::type_id::create("vseq");
vseq.m_clkndata_agent = m_env.m_clkndata_agent;

phase.raise_objection(this, "Starting virtual sequence"); Objection


`uvm_info(get_type_name(), "Objection raised", UVM_MEDIUM)

//uncomment and modify the following line


//vseq.m_seq_count = 1;

vseq.start(null);

phase.drop_objection(this, "Finished virtual sequence");

`uvm_info(get_type_name(), "Objection dropped", UVM_MEDIUM)


endtask : run_phase

© Accellera Systems Initiative 42


Simulation Out-of-the-Box
Test
Env

Configuration

Factory overrides

Test
harness

© Accellera Systems Initiative 43


Adding a User-Defined Sequence

class my_clkndata_seq extends clkndata_base_seq;


`uvm_object_utils(my_clkndata_seq)
rand byte data;
extern function new(string name = "");
extern task body();
endclass : my_clkndata_seq
...

task my_clkndata_seq::body();
`uvm_info(...
super.body();
for (int i = 0; i < 16; i++)
begin
item = data_tx::type_id::create("item");
start_item(item);
if ( !item.randomize() with { data == i; })
`uvm_warning(get_type_name(),"randomization failed!")
finish_item(item);
`uvm_info(...
end User-defined
endtask : body

© Accellera Systems Initiative 44


Adding a User-Defined Sequence
agent_name = clkndata
trans_item = data_tx Interface template file
trans_var = rand byte data;

driver_inc = clkndata_do_drive.sv
monitor_inc = clkndata_do_mon.sv
agent_cover_inc = clkndata_cover_inc.sv
agent_seq_inc = my_clkndata_seq.sv

agent_factory_set = clkndata_base_seq my_clkndata_seq

if_port = logic clk;


if_port = byte data;
if_clock = clk

function void top_test::build_phase(uvm_phase phase);


... Generated test
clkndata_base_seq::type_id::set_type_override(
my_clkndata_seq::get_type());
super.build_phase(phase);
endfunction : build_phase

© Accellera Systems Initiative 45


Simulation Log
sed 's/UVM_VERBOSITY=UVM_FULL/UVM_VERBOSITY=UVM_NONE/' ...

...
# uvm_test_top top_test - @471
# m_env top_env - @484
# m_clkndata_agent clkndata_agent - @497
# ap uvm_analysis_port - @527
# m_driver clkndata_driver - @535
# m_monitor clkndata_monitor - @520
# ap uvm_analysis_port - @667
# m_sequencer uvm_sequencer - @558
# m_clkndata_coverage clkndata_coverage - @504
# analysis_imp uvm_analysis_imp - @511
...
# mydut data = 00
# mydut data = 01
# mydut data = 02
# mydut data = 03
# mydut data = 04 Edited highlights
...

© Accellera Systems Initiative 46


Questions?

For Further Information

http://www.doulos.com/knowhow/sysverilog/uvm