5. UVM -- suquence机制
UVM -- suquence机制
1.1. sequence 机制的原理
1.2. sequence机制的使用
1.3. sequence 的启动 (2种方法)
1.3.1. 方法一:设置default_sequence
1.3.2. 方法二:手动启动sequence (更常用)
task my_base_test::run_phase(uvm_phase phase);
my0_seq m_seq = my0_seq::type_id::create("m_seq");
super.run_phase(phase);
phase.raise_objection(this);
`uvm_info(get_type_name(), "< 005 > : run_phase ", UVM_DEBUG)
// seq start
m_seq.start(m_env.m0_agent.m0_seqr);
phase.get_objection().set_drain_time(this, 1000);
phase.drop_objection(this);
endtask: run_phase
1.4. sequence do_item 方法
1.4.1. 方法一:start_item(req);
repeat(100) begin
@(posedge MY0.clk);
req = my0_seq_item::type_id::create("req"); // 1. create item
start_item(req); // 2. start item to sequencer
assert(req.randomize() with {req.pwdata == 100;}); // 3. randomize()
finish_item(req); // 4. send item to driver
`uvm_info(get_type_name(), $sformatf("< SEQ-2-1 > : %h, %h", req.paddr, req.pwdata), UVM_DEBUG)
end
1.4.2. 方法二:uvm_do_with()
repeat(100) begin
@(posedge MY0.clk);
req = new("req"); // 1. create item
`uvm_do_with(req, {req.paddr < 32'h40000000; req.pwdata == 32'h4444FFFF;})
`uvm_info(get_type_name(), $sformatf("< SEQ-2-2 > : %h, %h", req.paddr, req.pwdata), UVM_DEBUG)
end
1.5. sequence 的嵌套
1.6. sequence 的仲裁
1.7. sequence获取响应
1.8. UVM sequence library
1.8.1. 什么是UVM sequence library
其 本质是一个sequence, 相对于普通的sequence, sequence library有以下功能:
- 其他sequence可以向sequence library注册
- 可根据配置产生并且执行已经在其内部注册过的sequence
- 具有多种内嵌的选择sequence的算法
- 支持用户自定义的sequence;选择算法
- 注册方式的多样化
1.8.2. 向UVM sequence library注册sequence
1.8.2.1. 永久注册
1.8.2.2. 临时注册
1.8.3. sequence_library中添加sequence
1.8.4. UVM sequence library相关变量及配置类
1.8.4.1. 相关变量
1.8.4.2. 配置类
1.9. Virtual sequence
1.9.1. 什么是Virtual sequence 及 Virtual sequencer
1.9.2. Virtual sequence 与 Virtual sequencer 的使用方法
1.10 demo
1.10.1 dut
//------------------------------------------------------------------------
// Memory Model RTL - www.verificationguide.com
//------------------------------------------------------------------------
/*
-----------------
| |
addr ---->| |
| |------> rdata
| Memory Model |
wdata ---->| |
| |
-----------------
^ ^
| |
wr_en rd_en
-------------------------------------------------------------------------- */
module memory
#( parameter ADDR_WIDTH = 2,
parameter DATA_WIDTH = 8 ) (
input clk,
input reset,
//control signals
input [ADDR_WIDTH-1:0] addr,
input wr_en,
input rd_en,
//data signals
input [DATA_WIDTH-1:0] wdata,
output [DATA_WIDTH-1:0] rdata
);
reg [DATA_WIDTH-1:0] rdata;
//Memory
reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH];
//Reset
always @(posedge reset)
for(int i=0;i<2**ADDR_WIDTH;i++) mem[i]=8'hFF;
// Write data to Memory
always @(posedge clk)
if (wr_en) mem[addr] <= wdata;
// Read data from memory
always @(posedge clk)
if (rd_en) rdata <= mem[addr];
endmodule
1.10.2 tbench_top
//-------------------------------------------------------------------------
// www.verificationguide.com testbench.sv
//-------------------------------------------------------------------------
//---------------------------------------------------------------
//including interfcae and testcase files
`include "mem_interface.sv"
`include "mem_base_test.sv"
`include "mem_wr_rd_test.sv"
//---------------------------------------------------------------
module tbench_top;
//---------------------------------------
//clock and reset signal declaration
//---------------------------------------
bit clk;
bit reset;
//---------------------------------------
//clock generation
//---------------------------------------
always #5 clk = ~clk;
//---------------------------------------
//reset Generation
//---------------------------------------
initial begin
reset = 1;
#5 reset =0;
end
//---------------------------------------
//interface instance
//---------------------------------------
mem_if intf(clk,reset);
//---------------------------------------
//DUT instance
//---------------------------------------
memory DUT (
.clk(intf.clk),
.reset(intf.reset),
.addr(intf.addr),
.wr_en(intf.wr_en),
.rd_en(intf.rd_en),
.wdata(intf.wdata),
.rdata(intf.rdata)
);
//---------------------------------------
//passing the interface handle to lower heirarchy using set method
//and enabling the wave dump
//---------------------------------------
initial begin
uvm_config_db#(virtual mem_if)::set(uvm_root::get(),"*","vif",intf);
//enable wave dump
$dumpfile("dump.vcd");
$dumpvars;
end
//---------------------------------------
//calling test
//---------------------------------------
initial begin
run_test();
end
endmodule
1.10.3 mem_if
//-------------------------------------------------------------------------
// mem_interface - www.verificationguide.com
//-------------------------------------------------------------------------
interface mem_if(input logic clk,reset);
//---------------------------------------
//declaring the signals
//---------------------------------------
logic [1:0] addr;
logic wr_en;
logic rd_en;
logic [7:0] wdata;
logic [7:0] rdata;
//---------------------------------------
//driver clocking block
//---------------------------------------
clocking driver_cb @(posedge clk);
default input #1 output #1;
output addr;
output wr_en;
output rd_en;
output wdata;
input rdata;
endclocking
//---------------------------------------
//monitor clocking block
//---------------------------------------
clocking monitor_cb @(posedge clk);
default input #1 output #1;
input addr;
input wr_en;
input rd_en;
input wdata;
input rdata;
endclocking
//---------------------------------------
//driver modport
//---------------------------------------
modport DRIVER (clocking driver_cb,input clk,reset);
//---------------------------------------
//monitor modport
//---------------------------------------
modport MONITOR (clocking monitor_cb,input clk,reset);
endinterface
1.10.4 sequence_item
//-------------------------------------------------------------------------
// mem_seq_item - www.verificationguide.com
//-------------------------------------------------------------------------
class mem_seq_item extends uvm_sequence_item;
//---------------------------------------
//data and control fields
//---------------------------------------
rand bit [1:0] addr;
rand bit wr_en;
rand bit rd_en;
rand bit [7:0] wdata;
bit [7:0] rdata;
//---------------------------------------
//Utility and Field macros
//---------------------------------------
`uvm_object_utils_begin(mem_seq_item)
`uvm_field_int(addr,UVM_ALL_ON)
`uvm_field_int(wr_en,UVM_ALL_ON)
`uvm_field_int(rd_en,UVM_ALL_ON)
`uvm_field_int(wdata,UVM_ALL_ON)
`uvm_object_utils_end
//---------------------------------------
//Constructor
//---------------------------------------
function new(string name = "mem_seq_item");
super.new(name);
endfunction
//---------------------------------------
//constaint, to generate any one among write and read
//---------------------------------------
constraint wr_rd_c { wr_en != rd_en; };
endclass
1.10.5 sequence
//-------------------------------------------------------------------------
// mem_sequence's - www.verificationguide.com
//-------------------------------------------------------------------------
//=========================================================================
// mem_sequence - random stimulus
//=========================================================================
class mem_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(mem_sequence)
//---------------------------------------
//Constructor
//---------------------------------------
function new(string name = "mem_sequence");
super.new(name);
endfunction
`uvm_declare_p_sequencer(mem_sequencer)
//---------------------------------------
// create, randomize and send the item to driver
//---------------------------------------
virtual task body();
repeat(2) begin
req = mem_seq_item::type_id::create("req");
wait_for_grant();
req.randomize();
send_request(req);
wait_for_item_done();
end
endtask
endclass
//=========================================================================
//=========================================================================
// write_sequence - "write" type
//=========================================================================
class write_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(write_sequence)
//---------------------------------------
//Constructor
//---------------------------------------
function new(string name = "write_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_do_with(req,{req.wr_en==1;})
endtask
endclass
//=========================================================================
//=========================================================================
// read_sequence - "read" type
//=========================================================================
class read_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(read_sequence)
//---------------------------------------
//Constructor
//---------------------------------------
function new(string name = "read_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_do_with(req,{req.rd_en==1;})
endtask
endclass
//=========================================================================
//=========================================================================
// write_read_sequence - "write" followed by "read"
//=========================================================================
class write_read_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(write_read_sequence)
//---------------------------------------
//Constructor
//---------------------------------------
function new(string name = "write_read_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_do_with(req,{req.wr_en==1;})
`uvm_do_with(req,{req.rd_en==1;})
endtask
endclass
//=========================================================================
//=========================================================================
// wr_rd_sequence - "write" followed by "read" (sequence's inside sequences)
//=========================================================================
class wr_rd_sequence extends uvm_sequence#(mem_seq_item);
//---------------------------------------
//Declaring sequences
//---------------------------------------
write_sequence wr_seq;
read_sequence rd_seq;
`uvm_object_utils(wr_rd_sequence)
//---------------------------------------
//Constructor
//---------------------------------------
function new(string name = "wr_rd_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_do(wr_seq)
`uvm_do(rd_seq)
endtask
endclass
//=========================================================================
1.10.6 sequencer
//-------------------------------------------------------------------------
// mem_sequencer - www.verificationguide.com
//-------------------------------------------------------------------------
class mem_sequencer extends uvm_sequencer#(mem_seq_item);
`uvm_component_utils(mem_sequencer)
//---------------------------------------
//constructor
//---------------------------------------
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
endclass
1.10.7 driver
//-------------------------------------------------------------------------
// mem_driver - www.verificationguide.com
//-------------------------------------------------------------------------
`define DRIV_IF vif.DRIVER.driver_cb
class mem_driver extends uvm_driver #(mem_seq_item);
//---------------------------------------
// Virtual Interface
//---------------------------------------
virtual mem_if vif;
`uvm_component_utils(mem_driver)
//---------------------------------------
// Constructor
//---------------------------------------
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
//---------------------------------------
// build phase
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
`uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
endfunction: build_phase
//---------------------------------------
// run phase
//---------------------------------------
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
drive();
seq_item_port.item_done();
end
endtask : run_phase
//---------------------------------------
// drive - transaction level to signal level
// drives the value's from seq_item to interface signals
//---------------------------------------
virtual task drive();
`DRIV_IF.wr_en <= 0;
`DRIV_IF.rd_en <= 0;
@(posedge vif.DRIVER.clk);
`DRIV_IF.addr <= req.addr;
if(req.wr_en) begin // write operation
`DRIV_IF.wr_en <= req.wr_en;
`DRIV_IF.wdata <= req.wdata;
@(posedge vif.DRIVER.clk);
end
else if(req.rd_en) begin //read operation
`DRIV_IF.rd_en <= req.rd_en;
@(posedge vif.DRIVER.clk);
`DRIV_IF.rd_en <= 0;
@(posedge vif.DRIVER.clk);
req.rdata = `DRIV_IF.rdata;
end
endtask : drive
endclass : mem_driver
1.10.8 monitor
//-------------------------------------------------------------------------
// mem_monitor - www.verificationguide.com
//-------------------------------------------------------------------------
class mem_monitor extends uvm_monitor;
//---------------------------------------
// Virtual Interface
//---------------------------------------
virtual mem_if vif;
//---------------------------------------
// analysis port, to send the transaction to scoreboard
//---------------------------------------
uvm_analysis_port #(mem_seq_item) item_collected_port;
//---------------------------------------
// The following property holds the transaction information currently
// begin captured (by the collect_address_phase and data_phase methods).
//---------------------------------------
mem_seq_item trans_collected;
`uvm_component_utils(mem_monitor)
//---------------------------------------
// new - constructor
//---------------------------------------
function new (string name, uvm_component parent);
super.new(name, parent);
trans_collected = new();
item_collected_port = new("item_collected_port", this);
endfunction : new
//---------------------------------------
// build_phase - getting the interface handle
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
endfunction: build_phase
//---------------------------------------
// run_phase - convert the signal level activity to transaction level.
// i.e, sample the values on interface signal ans assigns to transaction class fields
//---------------------------------------
virtual task run_phase(uvm_phase phase);
forever begin
@(posedge vif.MONITOR.clk);
wait(vif.monitor_cb.wr_en || vif.monitor_cb.rd_en);
trans_collected.addr = vif.monitor_cb.addr;
if(vif.monitor_cb.wr_en) begin
trans_collected.wr_en = vif.monitor_cb.wr_en;
trans_collected.wdata = vif.monitor_cb.wdata;
trans_collected.rd_en = 0;
@(posedge vif.MONITOR.clk);
end
if(vif.monitor_cb.rd_en) begin
trans_collected.rd_en = vif.monitor_cb.rd_en;
trans_collected.wr_en = 0;
@(posedge vif.MONITOR.clk);
@(posedge vif.MONITOR.clk);
trans_collected.rdata = vif.monitor_cb.rdata;
end
item_collected_port.write(trans_collected);
end
endtask : run_phase
endclass : mem_monitor
1.10.9 agent
//-------------------------------------------------------------------------
// mem_agent - www.verificationguide.com
//-------------------------------------------------------------------------
`include "mem_seq_item.sv"
`include "mem_sequencer.sv"
`include "mem_sequence.sv"
`include "mem_driver.sv"
`include "mem_monitor.sv"
class mem_agent extends uvm_agent;
//---------------------------------------
// component instances
//---------------------------------------
mem_driver driver;
mem_sequencer sequencer;
mem_monitor monitor;
`uvm_component_utils(mem_agent)
//---------------------------------------
// constructor
//---------------------------------------
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
//---------------------------------------
// build_phase
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
monitor = mem_monitor::type_id::create("monitor", this);
//creating driver and sequencer only for ACTIVE agent
if(get_is_active() == UVM_ACTIVE) begin
driver = mem_driver::type_id::create("driver", this);
sequencer = mem_sequencer::type_id::create("sequencer", this);
end
endfunction : build_phase
//---------------------------------------
// connect_phase - connecting the driver and sequencer port
//---------------------------------------
function void connect_phase(uvm_phase phase);
if(get_is_active() == UVM_ACTIVE) begin
driver.seq_item_port.connect(sequencer.seq_item_export);
end
endfunction : connect_phase
endclass : mem_agent
1.10.10 scoreboard
//-------------------------------------------------------------------------
// mem_scoreboard - www.verificationguide.com
//-------------------------------------------------------------------------
class mem_scoreboard extends uvm_scoreboard;
//---------------------------------------
// declaring pkt_qu to store the pkt's recived from monitor
//---------------------------------------
mem_seq_item pkt_qu[$];
//---------------------------------------
// sc_mem
//---------------------------------------
bit [7:0] sc_mem [4];
//---------------------------------------
//port to recive packets from monitor
//---------------------------------------
uvm_analysis_imp#(mem_seq_item, mem_scoreboard) item_collected_export;
`uvm_component_utils(mem_scoreboard)
//---------------------------------------
// new - constructor
//---------------------------------------
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
//---------------------------------------
// build_phase - create port and initialize local memory
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
item_collected_export = new("item_collected_export", this);
foreach(sc_mem[i]) sc_mem[i] = 8'hFF;
endfunction: build_phase
//---------------------------------------
// write task - recives the pkt from monitor and pushes into queue
//---------------------------------------
virtual function void write(mem_seq_item pkt);
//pkt.print();
pkt_qu.push_back(pkt);
endfunction : write
//---------------------------------------
// run_phase - compare's the read data with the expected data(stored in local memory)
// local memory will be updated on the write operation.
//---------------------------------------
virtual task run_phase(uvm_phase phase);
mem_seq_item mem_pkt;
forever begin
wait(pkt_qu.size() > 0);
mem_pkt = pkt_qu.pop_front();
if(mem_pkt.wr_en) begin
sc_mem[mem_pkt.addr] = mem_pkt.wdata;
`uvm_info(get_type_name(),$sformatf("------ :: WRITE DATA :: ------"),UVM_LOW)
`uvm_info(get_type_name(),$sformatf("Addr: %0h",mem_pkt.addr),UVM_LOW)
`uvm_info(get_type_name(),$sformatf("Data: %0h",mem_pkt.wdata),UVM_LOW)
`uvm_info(get_type_name(),"------------------------------------",UVM_LOW)
end
else if(mem_pkt.rd_en) begin
if(sc_mem[mem_pkt.addr] == mem_pkt.rdata) begin
`uvm_info(get_type_name(),$sformatf("------ :: READ DATA Match :: ------"),UVM_LOW)
`uvm_info(get_type_name(),$sformatf("Addr: %0h",mem_pkt.addr),UVM_LOW)
`uvm_info(get_type_name(),$sformatf("Expected Data: %0h Actual Data: %0h",sc_mem[mem_pkt.addr],mem_pkt.rdata),UVM_LOW)
`uvm_info(get_type_name(),"------------------------------------",UVM_LOW)
end
else begin
`uvm_error(get_type_name(),"------ :: READ DATA MisMatch :: ------")
`uvm_info(get_type_name(),$sformatf("Addr: %0h",mem_pkt.addr),UVM_LOW)
`uvm_info(get_type_name(),$sformatf("Expected Data: %0h Actual Data: %0h",sc_mem[mem_pkt.addr],mem_pkt.rdata),UVM_LOW)
`uvm_info(get_type_name(),"------------------------------------",UVM_LOW)
end
end
end
endtask : run_phase
endclass : mem_scoreboard
1.10.11 env
//-------------------------------------------------------------------------
// mem_env - www.verificationguide.com
//-------------------------------------------------------------------------
`include "mem_agent.sv"
`include "mem_scoreboard.sv"
class mem_model_env extends uvm_env;
//---------------------------------------
// agent and scoreboard instance
//---------------------------------------
mem_agent mem_agnt;
mem_scoreboard mem_scb;
`uvm_component_utils(mem_model_env)
//---------------------------------------
// constructor
//---------------------------------------
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
//---------------------------------------
// build_phase - crate the components
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
mem_agnt = mem_agent::type_id::create("mem_agnt", this);
mem_scb = mem_scoreboard::type_id::create("mem_scb", this);
endfunction : build_phase
//---------------------------------------
// connect_phase - connecting monitor and scoreboard port
//---------------------------------------
function void connect_phase(uvm_phase phase);
mem_agnt.monitor.item_collected_port.connect(mem_scb.item_collected_export);
endfunction : connect_phase
endclass : mem_model_env
1.10.11 base_test
//-------------------------------------------------------------------------
// mem_test - www.verificationguide.com
//-------------------------------------------------------------------------
`include "mem_env.sv"
class mem_model_base_test extends uvm_test;
`uvm_component_utils(mem_model_base_test)
//---------------------------------------
// env instance
//---------------------------------------
mem_model_env env;
//---------------------------------------
// constructor
//---------------------------------------
function new(string name = "mem_model_base_test",uvm_component parent=null);
super.new(name,parent);
endfunction : new
//---------------------------------------
// build_phase
//---------------------------------------
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Create the env
env = mem_model_env::type_id::create("env", this);
endfunction : build_phase
//---------------------------------------
// end_of_elobaration phase
//---------------------------------------
virtual function void end_of_elaboration();
//print's the topology
print();
endfunction
//---------------------------------------
// end_of_elobaration phase
//---------------------------------------
function void report_phase(uvm_phase phase);
uvm_report_server svr;
super.report_phase(phase);
svr = uvm_report_server::get_server();
if(svr.get_severity_count(UVM_FATAL)+svr.get_severity_count(UVM_ERROR)>0) begin
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
`uvm_info(get_type_name(), "---- TEST FAIL ----", UVM_NONE)
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
end
else begin
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
`uvm_info(get_type_name(), "---- TEST PASS ----", UVM_NONE)
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
end
endfunction
endclass : mem_model_base_test
1.10.11 wr_rd_test
//-------------------------------------------------------------------------
// mem_write_read_test - www.verificationguide.com
//-------------------------------------------------------------------------
class mem_wr_rd_test extends mem_model_base_test;
`uvm_component_utils(mem_wr_rd_test)
//---------------------------------------
// sequence instance
//---------------------------------------
wr_rd_sequence seq;
//---------------------------------------
// constructor
//---------------------------------------
function new(string name = "mem_wr_rd_test",uvm_component parent=null);
super.new(name,parent);
endfunction : new
//---------------------------------------
// build_phase
//---------------------------------------
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Create the sequence
seq = wr_rd_sequence::type_id::create("seq");
endfunction : build_phase
//---------------------------------------
// run_phase - starting the test
//---------------------------------------
task run_phase(uvm_phase phase);
phase.raise_objection(this);
seq.start(env.mem_agnt.sequencer);
phase.drop_objection(this);
//set a drain-time for the environment if desired
phase.phase_done.set_drain_time(this, 50);
endtask : run_phase
endclass : mem_wr_rd_test
本文来自博客园,作者:Thisway2014,转载请注明原文链接:https://www.cnblogs.com/thisway2014/p/16503021.html