4. UVM -- TLM通信机制与平台的connect
1. 事务 tansaction
事务 tansaction 是一系列具有一定关系和功能的数据集合。
简单来说,一个tansaction就是把具有某一特定功能的一组信息封装在一起而成为的一个类;
事务是UVM平台中信息交互的基本单元
1.1. 从uvm_sequence_item扩展事务
1.2. 受约束的随机事务
2. UVM TLM通信机制
TLM是Transaction Level Modeling(事务级建模)的缩写起源于SystemC的一种通信标准。
所谓 transaction level是DUT中各个模块之间信号线级别的通信来说的。
2.1. TLM 原理
2.2. 常用的UVM端口
2.2.1. 端对端模式
2.2.1.1. port
- try_ 常用来是否成功为function,
- can_ 常用来是否可传输,为function,非阻塞类型使用;
- put/get 为task;
2.2.1.2. import (使用时要与put端口类型一致)
2.2.1.3. export (中间端口使用)
2.2.2. 方法模式
2.2.2.1. put模式实例
2.2.2.2. get模式实例
2.2.2.3. FIFO模式
-
FIFO的本质是一块缓存加两个IMP。
-
在monitor与FIFO的连接关系中,monitor中依然是 analysis_port,FIF0中是uvm_analysis_imp,数据流和控制流的方向相同。
-
在scoreboard与FIFO的连接关系中,scoreboard中使 blocking_get_port端口。
-
fifo 内建write task,ap口可以直接调用,将Transaction 发送 fifo;
-
而从fifo取Transaction ,我们一般用blocking_get_port端口连接后用get();
-
fifo方法实例
2.2.3. 一对多模式
- uvm_analysis_port #(T) ap;
- uvm_analysis_export #(T) aexp;
- uvm_analysis_imp #(my0_seq_item, my_scoreboard) aimp
注意1:
- scoreboard除了接收monitor的数据之外,还要接收reference model的数据。
- 相应的scoreboard就要再添加一个uvm_analysis_imp的IMP如 model_imp。
- 此时问题就出现了,由于接收到的两路数据应该做不同的处理,以这个新的IMP也要有一个write任务与其对应。但是write只有一个怎么办?
- UVM考虑到了这种情况,它定义了一个uvm_analysis_imp_decl来解决这个问题,其使用方式为:
3. demo -- 平台组件的connect
- test_pkg.sv
//-----------------------------------------------
//@ my_test_pkg
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_test_pkg__SV
`define my_test_pkg__SV
`include "my_intf.sv"
package my_test_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "my_env_list.incl"
`include "my_seq_list.incl"
//`include "my_vseq_list.incl"
`include "my_callbacks.sv"
`include "my_base_test.svh"
endpackage: my_test_pkg
`endif // my_test_pkg__SV
- test_top.sv
//-----------------------------------------------
//@ test_top
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
module test_top;
import uvm_pkg::*;
`include "uvm_macros.svh"
import my_test_pkg::*;
logic clk = 0;
logic reset_n = 0;
//interface
my_intf vif( .clk(clk), .reset_n(reset_n));
// DUT - a 16550 UART:
dut DUT ( .clk ( clk ),
.rst_n ( reset_n ),
.bus_cmd_valid( vif.bus_cmd_valid ),
.bus_op ( vif.bus_op ),
.bus_addr ( vif.bus_addr ),
.bus_wr_data ( vif.bus_wr_data ),
.bus_rd_data ( vif.bus_rd_data ),
.rxd ( vif.rxd ),
.rx_dv ( vif.rx_dv ),
.txd ( vif.txd ),
.tx_en ( vif.tx_en )
);
// clock/reset
always #5ns clk = ~clk;
initial begin
clk = 0;
reset_n = 0;
repeat(10) @(posedge clk);
reset_n = 1;
`uvm_info (" TEST_TOP ", $sformatf("clk = 0x%h , resetn = 0x%h", clk, reset_n), UVM_MEDIUM)
end
// UVM virtual interface handling and run_test()
initial begin
// virtual interface
uvm_config_db #(virtual my_intf)::set(null, "uvm_test_top*", "vif.BUS", vif);
uvm_config_db #(virtual my_intf)::set(null, "uvm_test_top*", "vif.MOD", vif);
// run
run_test();
end
endmodule: test_top
- my_intf.sv
//-----------------------------------------------
//@ my_intf
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_intf__SV
`define my_intf__SV
interface my_intf #(parameter D_WIDTH=16) (input bit clk, input bit reset_n);
parameter setup_time = 0;
parameter hold_time = 0;
// bus_if
logic bus_cmd_valid;
logic bus_op ;
logic [D_WIDTH-1:0] bus_addr ;
logic [D_WIDTH-1:0] bus_wr_data ;
logic [D_WIDTH-1:0] bus_rd_data ;
// my_if
logic [7:0] rxd ;
logic rx_dv ;
logic [7:0] txd ;
logic tx_en ;
clocking bus_cb @(posedge clk);
default input #setup_time output #hold_time;
output bus_cmd_valid;
output bus_op ;
output bus_addr ;
output bus_wr_data ;
input bus_rd_data ;
endclocking : bus_cb
clocking mod_cb @(posedge clk);
default input #setup_time output #hold_time;
output rxd ;
output rx_dv;
input txd ;
input tx_en;
endclocking : mod_cb
modport BUS(clocking bus_cb);
modport MOD(clocking mod_cb);
endinterface: my_intf
`endif // my_intf__SV
- my_base_test.sv
//-----------------------------------------------
//@ my_base_test
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_base_test__SV
`define my_base_test__SV
class my_callback extends CB_A;
virtual my_intf MY0;
`uvm_object_utils(my_callback)
function new(string name= "my_callback");
super.new(name);
endfunction
virtual task drive_item(my0_driver m0_drv, my0_seq_item req);
if(!uvm_config_db #(virtual my_intf)::get(null, "uvm_test_top*", "vif.BUS", MY0))
begin
`uvm_fatal(get_type_name(), "not SET : virtual my_intf")
end
`uvm_info(get_type_name(), $sformatf(" bus_op = %0h ", req.bus_op), UVM_DEBUG)
`uvm_info(get_type_name(), $sformatf(" bus_addr = %0h ", req.bus_addr), UVM_DEBUG)
`uvm_info(get_type_name(), $sformatf(" bus_wr_data = %0h ", req.bus_wr_data), UVM_DEBUG)
`uvm_info(get_type_name(), $sformatf(" bus_rd_data = %0h ", req.bus_rd_data), UVM_DEBUG)
@(posedge MY0.clk);
MY0.bus_addr <= req.bus_addr ;
@(posedge MY0.clk);
if(req.bus_op) begin
MY0.bus_wr_data <= req.bus_wr_data ;
MY0.bus_op <= 1'b1 ;
end
else begin
req.bus_rd_data <= MY0.bus_rd_data;
MY0.bus_op <= 1'b0 ;
end
@(posedge MY0.clk);
MY0.bus_cmd_valid <= 1;
@(posedge MY0.clk);
MY0.bus_addr <= 0;
MY0.bus_cmd_valid <= 0;
MY0.bus_op <= 0;
MY0.bus_wr_data <= 0;
endtask
endclass
class my_base_test extends uvm_test;
`uvm_component_utils(my_base_test)
my_env m_env;
my0_agent_config m0_agent_cfg;
virtual my_intf MY0;
//my0_seq m_seq;
//my0_override_seq m_seq;
extern function new(string name = "my_base_test", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern function void end_of_elaboration_phase(uvm_phase phase);
extern virtual task run_phase(uvm_phase phase);
extern function void report_phase(uvm_phase phase);
extern function void final_phase(uvm_phase phase);
//extern function void init_vseq(my_vseq_base vseq);
endclass: my_base_test
function my_base_test::new(string name = "my_base_test", uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
endfunction: new
function void my_base_test::build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
m_env = my_env::type_id::create("m_env", this);
m0_agent_cfg = my0_agent_config::type_id::create("m0_agent_cfg");
if(!uvm_config_db #(virtual my_intf)::get(this, "", "vif.BUS", m0_agent_cfg.MY0))
begin
`uvm_fatal(get_type_name(), "not SET : virtual my_intf")
end
if(!uvm_config_db #(virtual my_intf)::get(this, "", "vif.BUS", MY0))
begin
`uvm_fatal(get_type_name(), "not SET : virtual my_intf")
end
uvm_config_db #(my0_agent_config)::set(this, "m_env*", "my0_agent_config_hook", m0_agent_cfg);
set_type_override_by_type(my0_seq::get_type(), my0_override_seq::get_type());
//m_seq = my0_seq::type_id::create("m_seq");
//sequence : method 1
uvm_config_db #(uvm_object_wrapper)::set(this, "m_env.m0_agent.m0_seqr.main_phase",
"default_sequence", my0_seq::type_id::get());
//uvm_config_db #(uvm_object_wrapper)::set(this, "m_env.m0_agent.m0_seqr.main_phase",
// "default_sequence", my_seq::type_id::get());
//// sequence : method 2
//uvm_config_db #(uvm_sequence_base)::set(this, "m_env.m0_agent.m0_seqr.main_phase",
// "default_sequence", m_seq);
endfunction: build_phase
function void my_base_test::connect_phase(uvm_phase phase);
my_callback my_cb;
my_cb = my_callback::type_id::create("my_cb");
super.connect_phase(phase);
//my_cb = new("my_cb");
CB_A_pool::add(m_env.m0_agent.m0_drv, my_cb);
endfunction: connect_phase
function void my_base_test::end_of_elaboration_phase(uvm_phase phase);
uvm_top.print_topology;
`uvm_info(get_type_name(), "< 003 > : end_of_elaboration_phase ", UVM_DEBUG)
endfunction: end_of_elaboration_phase
task my_base_test::run_phase(uvm_phase phase);
// sequence : method 3
//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)
//init_vseq(vseq);
// sequence : method 3
//m_seq.start(m_env.m0_agent.m0_seqr);
repeat(1000) begin
@(posedge MY0.clk);
`uvm_info(get_type_name(), $sformatf(" reset_n = %0h ", MY0.reset_n), UVM_DEBUG)
end
#10000ns;
phase.get_objection().set_drain_time(this, 1000);
phase.drop_objection(this);
endtask: run_phase
function void my_base_test::report_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 008 > : report_phase ", UVM_DEBUG)
`uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
`uvm_info(get_type_name(), "+- *** UVM TEST PASSED *** -+", UVM_DEBUG)
`uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
`uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
`uvm_info(get_type_name(), "+- *** UVM TEST FAILED *** -+", UVM_DEBUG)
`uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
endfunction: report_phase
function void my_base_test::final_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 009 > : final_phase ", UVM_DEBUG)
endfunction: final_phase
//function void my_base_test::init_vseq(my_vseq_base vseq);
// //vseq.m0_seqr = m_env.m0_agent.m0_seqr;
//endfunction: init_vseq
`endif // my_base_test__SV
- my_env_list.incl
//-----------------------------------------------
//@ my_env_list
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_env_list__SV
`define my_env_list__SV
`include "my0_agent_list.incl"
`include "my_reference.svh"
`include "my_scoreboard.svh"
`include "my_env.svh"
`endif // my_env_list__SV
- my_env.svh
//-----------------------------------------------
//@ my_env
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_env__SV
`define my_env__SV
class my_env extends uvm_env;
`uvm_component_utils(my_env)
my0_agent m0_agent;
my_scoreboard m_scb;
my_reference m_ref;
//ral
reg_env m_reg_env;
// Create the UVM TLM Fifo that can accept simple_packet
uvm_tlm_analysis_fifo #(my0_seq_item) mon2ref_fifo;
uvm_tlm_analysis_fifo #(my0_seq_item) ref2scb_fifo;
extern function new(string name = "my_env", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
endclass: my_env
function my_env::new(string name = "my_env", uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
endfunction: new
function void my_env::build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
//m_env_cfg = my_env_config::type_id::create("m_env_cfg");
m0_agent = my0_agent::type_id::create("m0_agent", this);
m_scb = my_scoreboard::type_id::create("m_scb", this);
m_ref = my_reference::type_id::create("m_ref", this);
//ral
m_reg_env = reg_env::type_id::create("m_reg_env", this);
// Create a FIFO with depth 2
mon2ref_fifo = new ("mon2ref_fifo", this);
ref2scb_fifo = new ("ref2scb_fifo", this);
endfunction: build_phase
function void my_env::connect_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
//m0_agent.ap.connect(m_scb.imp);
m0_agent.ap.connect(mon2ref_fifo.analysis_export);
m_ref.get_port.connect(mon2ref_fifo.blocking_get_export);
m_ref.ap.connect(ref2scb_fifo.analysis_export);
m_scb.get_port.connect(ref2scb_fifo.blocking_get_export);
//ral
m0_agent.m0_mon.ap.connect(m_reg_env.m_apb2reg_predictor.bus_in);
m_reg_env.m_ral_model.map.set_sequencer(m0_agent.m0_seqr, m_reg_env.m_reg2apb);
//m0_agent.ap.connect(m_ref.analysis_export);
//m_ref.analysis_export.connect(m_scb.analysis_imp);
endfunction: connect_phase
`endif // my_env__SV
- my_env_config.svh
//-----------------------------------------------
//@ my_env_config
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_env_config__SV
`define my_env_config__SV
class my_env_config extends uvm_object;
`uvm_object_utils(my_env_config);
apb_agent_config m_apb_agent_cfg;
my_agent_config m_tx_my_agent_cfg;
my_agent_config m_rx_my_agent_cfg;
modem_config m_modem_agent_cfg;
my_reg_block rm;
virtual interrupt_if IRQ;
function new(string name = "my_env_config");
super.new(name);
endfunction
extern task wait_for_interrupt();
extern function bit get_interrupt_level();
extern task wait_for_clock(int n = 1);
extern task wait_for_baud_rate();
endclass: my_env_config
task my_env_config::wait_for_interrupt();
@(posedge IRQ.IRQ);
endtask: wait_for_interrupt
function bit my_env_config::get_interrupt_level();
if(IRQ.IRQ == 1)
return 1;
else
return 0;
endfunction: get_interrupt_level
task my_env_config::wait_for_clock(int n = 1);
repeat(n)
@(posedge IRQ.CLK);
endtask: wait_for_clock
task my_env_config::wait_for_baud_rate();
@(posedge IRQ.baud_out);
endtask: wait_for_baud_rate
`endif // my_env_config__SV
- my_reference.svh
//-----------------------------------------------
//@ my_reference
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_reference__SV
`define my_reference__SV
// Step1 : Create a new class that extends from uvm_scoreboard
class my_reference extends uvm_component;
`uvm_component_utils (my_reference)
// Step2a: Declare and create a TLM Analysis Port to receive data objects from other TB components
uvm_blocking_get_port #(my0_seq_item) get_port;//exp_port;
uvm_analysis_port #(my0_seq_item) ap;
//uvm_analysis_export #(my0_seq_item) analysis_export;
function new (string name = "my_reference", uvm_component parent);
super.new (name, parent);
endfunction
// Step2b: Instantiate the analysis port, because afterall, its a class object
function void build_phase (uvm_phase phase);
ap = new ("ap", this);
get_port = new ("get_port", this);
//analysis_export = new ("analysis_export", this);
endfunction
// Step3: Define other functions and tasks that operate on the data and call them
// Remember, this is the main task that consumes simulation time in UVM
virtual task run_phase (uvm_phase phase);
my0_seq_item tr;
forever begin
get_port.get(tr);
if( (tr.bus_addr != 0) && (tr.bus_wr_data != 0) ) begin
ap.write(tr);
`uvm_info ("m_tlm_fifo get", $sformatf("tr : \n%s", tr.sprint()), UVM_DEBUG)
end
end
endtask
// Step4: [Optional] Perform any remaining comparisons or checks before end of simulation
virtual function void check_phase (uvm_phase phase);
//...
endfunction
endclass
`endif // my_reference__SV
- my_scoreboard.svh
//-----------------------------------------------
//@ my_scoreboard
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my_scoreboard__SV
`define my_scoreboard__SV
class my_scoreboard extends uvm_scoreboard;
`uvm_component_utils (my_scoreboard)
// Step2a: Declare and create a TLM Analysis Port to receive data objects from other TB components
uvm_blocking_get_port #(my0_seq_item) get_port;
//uvm_analysis_imp_monitor #(my0_seq_item, my_scoreboard) analysis_imp;
function new (string name = "my_scoreboard", uvm_component parent);
super.new (name, parent);
endfunction
// Step2b: Instantiate the analysis port, because afterall, its a class object
function void build_phase (uvm_phase phase);
get_port = new ("get_port", this);
//analysis_imp = new ("analysis_imp", this);
endfunction
// Step3: Define other functions and tasks that operate on the data and call them
// Remember, this is the main task that consumes simulation time in UVM
virtual task run_phase (uvm_phase phase);
my0_seq_item tr;
forever begin
get_port.get(tr);
`uvm_info ("m_tlm_fifo get", $sformatf("Data received = 0x%h , 0x%h", tr.bus_addr, tr.bus_wr_data), UVM_DEBUG)
end
endtask
// Step4: [Optional] Perform any remaining comparisons or checks before end of simulation
virtual function void check_phase (uvm_phase phase);
//...
endfunction
endclass
`endif // my_scoreboard__SV
- my_callbacks.svh
`ifndef CB_A__SV
`define CB_A__SV
class CB_A extends uvm_callback;
`uvm_object_utils(CB_A)
function new(string name= "CB_A");
super.new(name);
endfunction
virtual task drive_item(my0_driver m0_drv, my0_seq_item req);
endtask
endclass
typedef uvm_callbacks#(my0_driver, CB_A) CB_A_pool;
`endif //CB_A__SV
- my0_agent_list.incl
//-----------------------------------------------
//@ my0_agent_list
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_agent_list__SV
`define my0_agent_list__SV
`include "uart_reg_pkg.sv"
`include "my0_seq_item.svh"
`include "my0_agent_config.svh"
`include "my0_driver.svh"
`include "my0_monitor.svh"
`include "my0_sequencer.svh"
`include "reg_env.sv"
`include "my0_agent.svh"
`endif // my0_agent_list__SV
- my0_agent.svh
//-----------------------------------------------
//@ my0_agent
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_agent__SV
`define my0_agent__SV
class my0_agent extends uvm_agent;
`uvm_component_utils(my0_agent)
my0_agent_config m0_agent_cfg;
my0_driver m0_drv;
my0_monitor m0_mon;
my0_sequencer m0_seqr;
uvm_analysis_port #(my0_seq_item) ap;
extern function new(string name = "my0_agent", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
endclass: my0_agent
function my0_agent::new(string name = "my0_agent", uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
endfunction: new
function void my0_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
if(!uvm_config_db #(my0_agent_config)::get(this, "", "my0_agent_config_hook", m0_agent_cfg))
begin
`uvm_fatal(get_type_name(), "not SET : my0_agent_config")
end
else begin
`uvm_info(get_type_name(),$sformatf(" object structure:\n%s", m0_agent_cfg.sprint()),UVM_DEBUG)
end
ap = new("ap", this);
if(m0_agent_cfg.active == UVM_ACTIVE) begin
m0_drv = my0_driver::type_id::create("m0_drv", this);
m0_seqr = my0_sequencer::type_id::create("m0_seqr", this);
end
if(m0_agent_cfg.has_functional_coverage) begin
//m_fcov_monitor = apb_coverage_monitor::type_id::create("m_fcov_monitor", this);
end
m0_mon = my0_monitor::type_id::create("m0_mon", this);
endfunction: build_phase
function void my0_agent::connect_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
// connect : test_top <--> m0_drv
if(m0_agent_cfg.active == UVM_ACTIVE) begin
m0_drv.seq_item_port.connect(m0_seqr.seq_item_export);
m0_drv.MY0 = m0_agent_cfg.MY0;
end
m0_mon.ap.connect(ap);
m0_mon.MY0 = m0_agent_cfg.MY0;
endfunction: connect_phase
`endif // my0_agent__SV
- my0_agent_config.svh
//-----------------------------------------------
//@ my0_agent_config
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_agent_config__SV
`define my0_agent_config__SV
class my0_agent_config extends uvm_object;
// Virtual Interface
virtual my_intf MY0;
// Is the agent active or passive
uvm_active_passive_enum active = UVM_ACTIVE;
// Include the APB functional coverage monitor
bit has_functional_coverage = 0;
// Include the APB RAM based scoreboard
bit has_scoreboard = 0;
//
// Address decode for the select lines:
int no_select_lines = 1;
int apb_index = 0; // Which PSEL is the monitor connected to
logic[31:0] start_address[];
logic[31:0] range[];
`uvm_object_utils_begin(my0_agent_config)
`uvm_field_enum(uvm_active_passive_enum, active, UVM_ALL_ON)
`uvm_field_int(has_functional_coverage, UVM_DEFAULT | UVM_HEX)
`uvm_field_int(has_scoreboard, UVM_DEFAULT | UVM_HEX)
`uvm_field_int(no_select_lines, UVM_DEFAULT | UVM_HEX)
`uvm_field_int(apb_index, UVM_DEFAULT | UVM_HEX)
`uvm_field_array_int(start_address, UVM_ALL_ON)
`uvm_field_array_int(range, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my0_agent_config");
super.new(name);
endfunction
endclass: my0_agent_config
`endif // my0_agent_config__SV
- my0_seq_item.svh
//-----------------------------------------------
//@ my0_seq_item
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_seq_item__SV
`define my0_seq_item__SV
class my0_seq_item extends uvm_sequence_item;
//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
// bus_if
rand logic bus_cmd_valid;
rand logic bus_op ;
rand logic [16-1:0] bus_addr ;
rand logic [16-1:0] bus_wr_data ;
logic [16-1:0] bus_rd_data ;
// my_if
rand logic [7:0] rxd ;
rand logic rx_dv ;
logic [7:0] txd ;
logic tx_en ;
// UVM Factory Registration Macro
`uvm_object_utils_begin(my0_seq_item)
`uvm_field_int( bus_cmd_valid, UVM_ALL_ON )
`uvm_field_int( bus_op , UVM_ALL_ON )
`uvm_field_int( bus_addr , UVM_ALL_ON )
`uvm_field_int( bus_wr_data , UVM_ALL_ON )
`uvm_field_int( bus_rd_data , UVM_ALL_ON )
`uvm_field_int( rxd , UVM_ALL_ON )
`uvm_field_int( rx_dv , UVM_ALL_ON )
`uvm_field_int( txd , UVM_ALL_ON )
`uvm_field_int( tx_en , UVM_ALL_ON )
`uvm_object_utils_end
//------------------------------------------
// Constraints
//------------------------------------------
constraint addr_alignment {
bus_addr >= 32'h4000;
bus_addr%2 == 0;
}
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
function new(string name = "my0_seq_item");
super.new(name);
endfunction
endclass:my0_seq_item
`endif // my0_seq_item__SV
- my0_driver.svh
//-----------------------------------------------
//@ my0_driver
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_driver__SV
`define my0_driver__SV
//callback
typedef class CB_A;
class my0_driver extends uvm_driver#(my0_seq_item);
`uvm_component_utils(my0_driver)
//callback
`uvm_register_cb(my0_driver, CB_A)
virtual my_intf MY0;
my0_seq_item rsp;
extern function new(string name = "my0_driver", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
//extern virtual task drive_item(my0_seq_item req);
endclass: my0_driver
function my0_driver::new(string name = "my0_driver", uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
endfunction: new
function void my0_driver::build_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
endfunction: build_phase
function void my0_driver::connect_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
endfunction: connect_phase
task my0_driver::run_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 005 > : run_phase ", UVM_DEBUG)
super.run_phase(phase);
// Loop the following steps
MY0.bus_addr <= 0;
MY0.bus_cmd_valid <= 0;
MY0.bus_op <= 0;
MY0.bus_wr_data <= 0;
while(!MY0.reset_n)
@(posedge MY0.clk);
while(1) begin
`uvm_info(get_type_name(), $sformatf(" 1. Get next item from the sequencer !!!"), UVM_DEBUG)
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(), $sformatf(" 2-1. drive item into DUT interface !!! \n%s\n", req.sprint()), UVM_DEBUG)
//callback
`uvm_do_callbacks(my0_driver, CB_A, drive_item(this, req))
//drive_item(req);
`uvm_info(get_type_name(), $sformatf(" 2-2. put_response !!!"), UVM_DEBUG)
rsp = new("rsp");
$cast(rsp, req.clone());
rsp.set_id_info(req);
seq_item_port.put_response(rsp);
`uvm_info(get_type_name(), $sformatf(" 3. Finish driving transaction !!!"), UVM_DEBUG)
seq_item_port.item_done();
end
endtask: run_phase
//task my0_driver::drive_item(my0_seq_item req);
// `uvm_info(get_type_name(), $sformatf(" bus_op = %0h ", req.bus_op), UVM_DEBUG)
// `uvm_info(get_type_name(), $sformatf(" bus_addr = %0h ", req.bus_addr), UVM_DEBUG)
// `uvm_info(get_type_name(), $sformatf(" bus_wr_data = %0h ", req.bus_wr_data), UVM_DEBUG)
// `uvm_info(get_type_name(), $sformatf(" bus_rd_data = %0h ", req.bus_rd_data), UVM_DEBUG)
//
// @(posedge MY0.clk);
// MY0.bus_addr <= req.bus_addr ;
// @(posedge MY0.clk);
// if(req.bus_op) begin
// MY0.bus_wr_data <= req.bus_wr_data ;
// MY0.bus_op <= 1'b1 ;
// end
// else begin
// req.bus_rd_data <= MY0.bus_rd_data;
// MY0.bus_op <= 1'b0 ;
// end
// @(posedge MY0.clk);
// MY0.bus_cmd_valid <= 1;
//
// @(posedge MY0.clk);
// MY0.bus_addr <= 0;
// MY0.bus_cmd_valid <= 0;
// MY0.bus_op <= 0;
// MY0.bus_wr_data <= 0;
//
//endtask: drive_item
`endif // my0_driver__SV
- my0_monitor.svh
//-----------------------------------------------
//@ my0_monitor
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_monitor__SV
`define my0_monitor__SV
class my0_monitor extends uvm_monitor;
`uvm_component_utils(my0_monitor)
virtual my_intf MY0;
uvm_analysis_port #(my0_seq_item) ap;
my0_seq_item pkg;
extern function new(string name = "my0_monitor", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
endclass: my0_monitor
function my0_monitor::new(string name = "my0_monitor", uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
endfunction: new
function void my0_monitor::build_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
ap = new("ap", this);
endfunction: build_phase
function void my0_monitor::connect_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
endfunction: connect_phase
task my0_monitor::run_phase(uvm_phase phase);
`uvm_info(get_type_name(), "< 005 > : run_phase ", UVM_DEBUG)
forever begin
@(posedge MY0.clk);
pkg = my0_seq_item::type_id::create("pkg");
pkg.bus_addr = MY0.bus_addr ;
pkg.bus_wr_data = MY0.bus_wr_data ;
pkg.bus_op = MY0.bus_op ;
pkg.bus_cmd_valid = MY0.bus_cmd_valid ;
pkg.bus_rd_data = MY0.bus_rd_data ;
ap.write(pkg);
end
endtask: run_phase
`endif // my0_monitor__SV
- my0_sequencer.svh
//-----------------------------------------------
//@ my0_sequencer
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_sequencer__SV
`define my0_sequencer__SV
class my0_sequencer extends uvm_sequencer #(my0_seq_item);
`uvm_component_utils(my0_sequencer)
function new(string name = "my0_sequencer", uvm_component parent = null);
super.new(name, parent);
`uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
endfunction: new
endclass: my0_sequencer
`endif // my0_sequencer__SV
- reg_env.sv
class reg2apb_adapter extends uvm_reg_adapter;
`uvm_object_utils (reg2apb_adapter)
function new (string name = "reg2apb_adapter");
super.new (name);
endfunction
virtual function uvm_sequence_item reg2bus (const ref uvm_reg_bus_op rw);
my0_seq_item pkt = my0_seq_item::type_id::create ("pkt");
pkt.bus_op = (rw.kind == UVM_WRITE) ? 1: 0;
pkt.bus_addr = rw.addr;
pkt.bus_wr_data = rw.data;
`uvm_info ("adapter", $sformatf ("reg2bus addr=0x%0h data=0x%0h kind=%s", pkt.bus_addr, pkt.bus_wr_data, rw.kind.name), UVM_DEBUG)
return pkt;
endfunction
virtual function void bus2reg (uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
my0_seq_item pkt;
if (! $cast (pkt, bus_item)) begin
`uvm_fatal ("reg2apb_adapter", "Failed to cast bus_item to pkt")
end
rw.kind = pkt.bus_op ? UVM_WRITE : UVM_READ;
rw.addr = pkt.bus_addr;
rw.data = pkt.bus_rd_data;
`uvm_info ("adapter", $sformatf("bus2reg : addr=0x%0h data=0x%0h kind=%s status=%s", rw.addr, rw.data, rw.kind.name(), rw.status.name()), UVM_DEBUG)
endfunction
endclass
// Register environment class puts together the model, adapter and the predictor
class reg_env extends uvm_env;
`uvm_component_utils (reg_env)
function new (string name="reg_env", uvm_component parent);
super.new (name, parent);
endfunction
uart_reg_block m_ral_model; // Register Model
reg2apb_adapter m_reg2apb; // Convert Reg Tx <-> Bus-type packets
uvm_reg_predictor #(my0_seq_item) m_apb2reg_predictor; // Map APB tx to register in model
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_ral_model = uart_reg_block::type_id::create ("m_ral_model", this);
m_reg2apb = reg2apb_adapter :: type_id :: create ("m_reg2apb");
m_apb2reg_predictor = uvm_reg_predictor #(my0_seq_item) :: type_id :: create ("m_apb2reg_predictor", this);
m_ral_model.build ();
m_ral_model.lock_model ();
m_ral_model.reset ();
uvm_config_db #(uart_reg_block)::set (null, "uvm_test_top", "m_ral_model", m_ral_model);
endfunction
virtual function void connect_phase (uvm_phase phase);
super.connect_phase (phase);
m_apb2reg_predictor.map = m_ral_model.map;
m_apb2reg_predictor.adapter = m_reg2apb;
m_ral_model.default_map.set_auto_predict(1);
endfunction
endclass
- uart_reg_pkg.sv
//-----------------------------------------------
// Copyright 2012 Mentor Graphics Corporation
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//-----------------------------------------------
class txd_reg extends uvm_reg;
`uvm_object_utils(txd_reg)
rand uvm_reg_field data;
function new(string name = "txd_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
data = uvm_reg_field::type_id::create("data");
data.configure(this, 8, 0, "WO", 0, 8'h0, 0, 1, 0);
endfunction: build
endclass: txd_reg
class rxd_reg extends uvm_reg;
`uvm_object_utils(rxd_reg)
uvm_reg_field data;
function new(string name = "rxd_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
data = uvm_reg_field::type_id::create("data");
data.configure(this, 8, 0, "RO", 0, 8'h0, 0, 0, 0);
endfunction: build
endclass: rxd_reg
class ier_reg extends uvm_reg;
`uvm_object_utils(ier_reg)
rand uvm_reg_field RDI;
rand uvm_reg_field TXE;
rand uvm_reg_field RXS;
rand uvm_reg_field MSI;
function new(string name = "ier_reg");
super.new(name, 4, UVM_NO_COVERAGE);
endfunction
function void build();
RDI = uvm_reg_field::type_id::create("RDI");
RDI.configure(this, 1, 0, "RW", 0, 0, 1, 1, 0);
TXE = uvm_reg_field::type_id::create("TXE");
TXE.configure(this, 1, 1, "RW", 0, 0, 1, 1, 0);
RXS = uvm_reg_field::type_id::create("RXS");
RXS.configure(this, 1, 2, "RW", 0, 0, 1, 1, 0);
MSI = uvm_reg_field::type_id::create("MSI");
MSI.configure(this, 1, 3, "RW", 0, 0, 1, 1, 0);
endfunction: build
endclass: ier_reg
class fcr_reg extends uvm_reg;
`uvm_object_utils(fcr_reg)
rand uvm_reg_field unused;
rand uvm_reg_field RFITL;
function new(string name = "fcr_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
unused = uvm_reg_field::type_id::create("unused");
unused.configure(this, 6, 0, "WO", 0, 0, 1, 0, 0);
RFITL = uvm_reg_field::type_id::create("RFITL");
RFITL.configure(this, 2, 6, "WO", 0, 2'b11, 1, 1, 0);
endfunction: build
endclass: fcr_reg
class iid_reg extends uvm_reg;
`uvm_object_utils(iid_reg)
uvm_reg_field ID;
uvm_reg_field unused;
function new(string name = "iid_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
ID = uvm_reg_field::type_id::create("ID");
ID.configure(this, 4, 0, "RO", 1, 4'h1, 1, 0, 0);
unused = uvm_reg_field::type_id::create("unused");
unused.configure(this, 4, 4, "RO", 1, 4'hc, 1, 0, 0);
endfunction: build
endclass: iid_reg
class lcr_reg extends uvm_reg;
`uvm_object_utils(lcr_reg)
rand uvm_reg_field WL;
rand uvm_reg_field STP;
rand uvm_reg_field PE;
rand uvm_reg_field EP;
rand uvm_reg_field SP;
rand uvm_reg_field BRK;
rand uvm_reg_field DLAB;
function new(string name = "lcr_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
WL = uvm_reg_field::type_id::create("WL");
WL.configure(this, 2, 0, "RW", 0, 2'b11, 1, 1, 0);
STP = uvm_reg_field::type_id::create("STP");
STP.configure(this, 1, 2, "RW", 0, 1'b0, 1, 1, 0);
PE = uvm_reg_field::type_id::create("PE");
PE.configure(this, 1, 3, "RW", 0, 1'b0, 1, 1, 0);
EP = uvm_reg_field::type_id::create("EP");
EP.configure(this, 1, 4, "RW", 0, 1'b0, 1, 1, 0);
SP = uvm_reg_field::type_id::create("SP");
SP.configure(this, 1, 5, "RW", 0, 1'b0, 1, 1, 0);
BRK = uvm_reg_field::type_id::create("BRK");
BRK.configure(this, 1, 6, "RW", 0, 1'b0, 1, 1, 0);
DLAB = uvm_reg_field::type_id::create("DLAB");
DLAB.configure(this, 1, 7, "RW", 0, 1'b0, 1, 1, 0);
endfunction
endclass: lcr_reg
class mcr_reg extends uvm_reg;
`uvm_object_utils(mcr_reg)
rand uvm_reg_field DTR;
rand uvm_reg_field RTS;
rand uvm_reg_field OUT1;
rand uvm_reg_field OUT2;
rand uvm_reg_field LBACK;
function new(string name = "mcr_reg");
super.new(name, 5, UVM_NO_COVERAGE);
endfunction
function void build();
DTR = uvm_reg_field::type_id::create("DTR");
DTR.configure(this, 1, 0, "WO", 0, 1'b0, 1, 1, 0);
RTS = uvm_reg_field::type_id::create("RTS");
RTS.configure(this, 1, 1, "WO", 0, 1'b0, 1, 1, 0);
OUT1 = uvm_reg_field::type_id::create("OUT1");
OUT1.configure(this, 1, 2, "WO", 0, 1'b0, 1, 1, 0);
OUT2 = uvm_reg_field::type_id::create("OUT2");
OUT2.configure(this, 1, 3, "WO", 0, 1'b0, 1, 1, 0);
LBACK = uvm_reg_field::type_id::create("LBACK");
LBACK.configure(this, 1, 4, "WO", 0, 1'b0, 1, 1, 0);
endfunction: build
endclass: mcr_reg
class lsr_reg extends uvm_reg;
`uvm_object_utils(lsr_reg)
uvm_reg_field DR;
uvm_reg_field OE;
uvm_reg_field PE;
uvm_reg_field FE;
uvm_reg_field BI;
uvm_reg_field TFE;
uvm_reg_field TXE;
uvm_reg_field RFE;
function new(string name = "lsr_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
DR = uvm_reg_field::type_id::create("DR");
DR.configure(this, 1, 0, "RO", 0, 1'b0, 1, 0, 0);
OE = uvm_reg_field::type_id::create("OE");
OE.configure(this, 1, 1, "RC", 0, 1'b0, 1, 0, 0);
PE = uvm_reg_field::type_id::create("PE");
PE.configure(this, 1, 2, "RC", 0, 1'b0, 1, 0, 0);
FE = uvm_reg_field::type_id::create("FE");
FE.configure(this, 1, 3, "RC", 0, 1'b0, 1, 0, 0);
BI = uvm_reg_field::type_id::create("BI");
BI.configure(this, 1, 4, "RC", 0, 1'b0, 1, 0, 0);
TFE = uvm_reg_field::type_id::create("TFE");
TFE.configure(this, 1, 5, "RO", 0, 1'b0, 1, 0, 0);
TXE = uvm_reg_field::type_id::create("TXE");
TXE.configure(this, 1, 6, "RO", 0, 1'b0, 1, 0, 0);
RFE = uvm_reg_field::type_id::create("RFE");
RFE.configure(this, 1, 7, "RC", 0, 1'b0, 1, 0, 0);
endfunction: build
endclass: lsr_reg
class msr_reg extends uvm_reg;
`uvm_object_utils(msr_reg)
uvm_reg_field DCTS;
uvm_reg_field DDSR;
uvm_reg_field TERI;
uvm_reg_field DDCD;
uvm_reg_field CTS;
uvm_reg_field DSR;
uvm_reg_field RI;
uvm_reg_field DCD;
function new(string name = "msr_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
DCTS = uvm_reg_field::type_id::create("DCTS");
DCTS.configure(this, 1, 0, "RC", 0, 1'b0, 1, 0, 0);
DDSR = uvm_reg_field::type_id::create("DDSR");
DDSR.configure(this, 1, 1, "RC", 0, 1'b0, 1, 0, 0);
TERI = uvm_reg_field::type_id::create("TERI");
TERI.configure(this, 1, 2, "RC", 0, 1'b0, 1, 0, 0);
DDCD = uvm_reg_field::type_id::create("DDCD");
DDCD.configure(this, 1, 3, "RC", 0, 1'b0, 1, 0, 0);
CTS = uvm_reg_field::type_id::create("CTS");
CTS.configure(this, 1, 4, "RO", 0, 1'b0, 1, 0, 0);
DSR = uvm_reg_field::type_id::create("DSR");
DSR.configure(this, 1, 5, "RO", 0, 1'b0, 1, 0, 0);
RI = uvm_reg_field::type_id::create("RI");
RI.configure(this, 1, 6, "RO", 0, 1'b0, 1, 0, 0);
DCD = uvm_reg_field::type_id::create("DCD");
DCD.configure(this, 1, 7, "RO", 0, 1'b0, 1, 0, 0);
endfunction: build
endclass: msr_reg
class div_reg extends uvm_reg;
`uvm_object_utils(div_reg)
rand uvm_reg_field DIV;
function new(string name = "div_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
function void build();
DIV = uvm_reg_field::type_id::create("DIV");
DIV.configure(this, 8, 0, "RW", 0, 8'h0, 1, 1, 0);
endfunction: build
endclass: div_reg
class uart_reg_block extends uvm_reg_block;
`uvm_object_utils(uart_reg_block)
rand txd_reg TXD;
rand rxd_reg RXD;
rand ier_reg IER;
iid_reg IID;
rand fcr_reg FCR;
rand lcr_reg LCR;
rand mcr_reg MCR;
lsr_reg LSR;
msr_reg MSR;
rand div_reg DIV1;
rand div_reg DIV2;
uvm_reg_map map;
function new(string name = "uart_reg_block");
super.new(name, UVM_NO_COVERAGE);
endfunction
function void build();
TXD = txd_reg::type_id::create("TXD");
TXD.build();
TXD.configure(this);
RXD = rxd_reg::type_id::create("RXD");
RXD.build();
RXD.configure(this);
IER = ier_reg::type_id::create("IER");
IER.build();
IER.configure(this);
IID = iid_reg::type_id::create("IID");
IID.build();
IID.configure(this);
FCR = fcr_reg::type_id::create("FCR");
FCR.build();
FCR.configure(this);
LCR = lcr_reg::type_id::create("LCR");
LCR.build();
LCR.configure(this);
MCR = mcr_reg::type_id::create("MCR");
MCR.build();
MCR.configure(this);
LSR = lsr_reg::type_id::create("LSR");
LSR.build();
LSR.configure(this);
MSR = msr_reg::type_id::create("MSR");
MSR.build();
MSR.configure(this);
DIV1 = div_reg::type_id::create("DIV1");
DIV1.build();
DIV1.configure(this);
DIV2 = div_reg::type_id::create("DIV2");
DIV2.build();
DIV2.configure(this);
map = create_map("map", 'h0, 4, UVM_LITTLE_ENDIAN);
map.add_reg(TXD, 32'h0, "WO");
map.add_reg(RXD, 32'h0, "RO");
map.add_reg(IER, 32'h4, "RW");
map.add_reg(IID, 32'h8, "RO");
map.add_reg(FCR, 32'h8, "WO");
map.add_reg(LCR, 32'hc, "RW");
map.add_reg(MCR, 32'h10, "RW");
map.add_reg(LSR, 32'h14, "RO");
map.add_reg(MSR, 32'h18, "RO");
map.add_reg(DIV1, 32'h1c, "RW");
map.add_reg(DIV2, 32'h20, "RW");
lock_model();
endfunction
endclass: uart_reg_block
- my0_seq.svh
//-----------------------------------------------
//@ my0_seq
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_seq__SV
`define my0_seq__SV
class my0_seq extends uvm_sequence #(my0_seq_item);
`uvm_object_utils(my0_seq)
`uvm_declare_p_sequencer (my0_sequencer)
rand int no_rx_chars;
rand bit[7:0] lcr;
rand bit[15:0] baud_divisor;
rand bit no_errors;
rand bit[3:0] IER;
uvm_status_e status;
uart_reg_block rm;
virtual my_intf MY0;
my0_seq_item req;
function new(string name = "my0_seq");
super.new(name);
//UVM1.2
//set_automatic_phase_objection(1);
endfunction
virtual task pre_body;
uvm_phase phase;
super.pre_body();
`ifdef UVM_VERSION_1_2
phase = get_starting_phase();
`else
phase = starting_phase;
`endif
if(phase != null) phase.raise_objection(this);
`uvm_info(get_type_name(), "< SEQ-1 > : pre_body ", UVM_DEBUG)
endtask: pre_body
virtual task post_body;
uvm_phase phase;
super.post_body();
`ifdef UVM_VERSION_1_2
phase = get_starting_phase();
`else
phase = starting_phase;
`endif
if(phase != null) phase.drop_objection(this);
`uvm_info(get_type_name(), "< SEQ-3 > : post_body ", UVM_DEBUG)
endtask: post_body
virtual task body;
bit[31:0] data;
if(!uvm_config_db #(virtual my_intf)::get(null, "uvm_test_top*", "vif.BUS", MY0))
begin
`uvm_fatal(get_type_name(), "not SET : virtual my_intf")
end
//if(!uvm_config_db #(uart_reg_block)::get(null, "uvm_test_top", "m_ral_model", rm))
//begin
// `uvm_fatal(get_type_name(), "not SET : m_ral_model")
//end
//@(posedge MY0.clk);
//IER = 4'h8;
//rm.IER.write(status, {'0, IER}, UVM_FRONTDOOR);
//@(posedge MY0.clk);
//assert(this.randomize() with {data[4] == 1;});
//rm.MCR.write(status, data, UVM_FRONTDOOR);
//@(posedge MY0.clk);
//rm.MCR.write(status, 32'ha, UVM_FRONTDOOR);
//rm.MCR.write(status, 32'h4, UVM_FRONTDOOR);
//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.bus_wr_data >= 100;}); // 3. randomize()
// finish_item(req); // 4. send item to driver
// `uvm_info(get_type_name(), $sformatf("< SEQ-2-1 > : %h, %h", req.bus_addr, req.bus_wr_data), UVM_DEBUG)
// get_response(rsp);
// //`uvm_info(get_type_name(), $sformatf("rsp \n%s\n", rsp.sprint()), UVM_DEBUG)
// rsp.print();
//end
repeat(100) begin
@(posedge MY0.clk);
req = new("req"); // 1. create item
`uvm_do_with(req, {req.bus_addr < 32'h4FFFFFFF; req.bus_wr_data != 32'h4444FFFF;})
`uvm_info(get_type_name(), $sformatf("< SEQ-2-2 > : %h, %h", req.bus_addr, req.bus_wr_data), UVM_DEBUG)
get_response(rsp);
`uvm_info(get_type_name(), $sformatf("rsp \n%s\n", rsp.sprint()), UVM_DEBUG)
end
`uvm_info(get_type_name(), "< SEQ-2 > : body ", UVM_DEBUG)
endtask: body
endclass: my0_seq
`endif // my0_seq__SV
- my0_override_seq.svh
//-----------------------------------------------
//@ my0_override_seq
//@ Version : V0.1
//@ Wesley 2022.04.10
//-----------------------------------------------
`ifndef my0_override_seq__SV
`define my0_override_seq__SV
class my0_override_seq extends my0_seq;
`uvm_object_utils(my0_override_seq)
`uvm_declare_p_sequencer (my0_sequencer)
virtual my_intf MY0;
function new(string name = "my0_override_seq");
super.new(name);
//UVM1.2
//set_automatic_phase_objection(1);
endfunction
virtual task pre_body;
uvm_phase phase;
super.pre_body();
`ifdef UVM_VERSION_1_2
phase = get_starting_phase();
`else
phase = starting_phase;
`endif
if(phase != null) phase.raise_objection(this);
`uvm_info(get_type_name(), "< SEQ-1 > : pre_body ", UVM_DEBUG)
endtask: pre_body
virtual task post_body;
uvm_phase phase;
super.post_body();
`ifdef UVM_VERSION_1_2
phase = get_starting_phase();
`else
phase = starting_phase;
`endif
if(phase != null) phase.drop_objection(this);
`uvm_info(get_type_name(), "< SEQ-3 > : post_body ", UVM_DEBUG)
endtask: post_body
virtual task body;
bit[31:0] data;
if(!uvm_config_db #(virtual my_intf)::get(null, "uvm_test_top*", "vif.BUS", MY0))
begin
`uvm_fatal(get_type_name(), "not SET : virtual my_intf")
end
repeat(50) begin
@(posedge MY0.clk);
req = new("req"); // 1. create item
`uvm_do_with(req, {req.bus_addr == 32'h00000004; req.bus_wr_data == 32'h0000000F;})
`uvm_info(get_type_name(), $sformatf("< SEQ-2-2 > : %h, %h", req.bus_addr, req.bus_wr_data), UVM_DEBUG)
get_response(rsp);
`uvm_info(get_type_name(), $sformatf("rsp \n%s\n", rsp.sprint()), UVM_DEBUG)
end
`uvm_info(get_type_name(), "< SEQ-2 > : body ", UVM_DEBUG)
endtask: body
endclass: my0_override_seq
- wave.tcl
call {$fsdbDumpvars(0, test_top, "+all")}
call {$fsdbDumpSVA (0, test_top)}
call {$fsdbDumpMDA (0, test_top)}
run
- filelist.f
+incdir+../tb
+incdir+../tb/env
+incdir+../tb/env/agents
+incdir+../tb/env/agents/apb_agent
+incdir+../tb/env/agents/my0_agent
+incdir+../tb/env/protocol_monitor
+incdir+../tb/register_model
+incdir+../tc
+incdir+../tc/virtual_sequences
+incdir+../tc/sequences
+incdir+../tc/tests
-F ../rtl/filelist.f
../tb/my_test_pkg.sv
../tb/test_top.sv
本文来自博客园,作者:Thisway2014,转载请注明原文链接:https://www.cnblogs.com/thisway2014/p/16488147.html