首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >uvm中的tlm通信机制

uvm中的tlm通信机制

原创
作者头像
用户9546848
修改2025-10-12 16:57:23
修改2025-10-12 16:57:23
1740
举报

1. DUT示例代码

代码语言:cpp
复制
`timescale 1ns/1ns

/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,
					   parameter WIDTH = 8)(
	 input wclk
	,input wenc
	,input [$clog2(DEPTH)-1:0] waddr  
	,input [WIDTH-1:0] wdata      	
	,input rclk
	,input renc
	,input [$clog2(DEPTH)-1:0] raddr  
	,output reg [WIDTH-1:0] rdata 		
);

reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];

always @(posedge wclk) begin
	if(wenc)
		RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
	if(renc)
		rdata <= RAM_MEM[raddr];
end 

endmodule  

/**********************************SFIFO************************************/
module sfifo#(
	parameter	WIDTH = 8,
	parameter 	DEPTH = 16
)(
	input 					clk		, 
	input 					rst_n	,
	input 					winc	,
	input 			 		rinc	,
	input 		[WIDTH-1:0]	wdata	,

	output reg				wfull	,
	output reg				rempty	,
	output wire [WIDTH-1:0]	rdata
);
    
endmodule

2. 验证环境示例代码

2.1 in_utils组件

2.1.1 in_transaction.sv

代码语言:cpp
复制
class in_transaction#(parameter WIDTH=8,parameter DEPTH=16) extends uvm_sequence_item;

    rand bit         winc;
    rand bit         rinc;
    rand bit[WIDTH-1:0]         wdata;

    `uvm_object_utils_begin(in_transaction)
        `uvm_field_int(winc) 
        `uvm_field_int(rinc) 
        `uvm_field_queue(winc)  
    `uvm_object_utils_end

    extern virtual function new(string name="in_transaction",uvm_component parent);

    // constraint winc_rinc_con 
    extren virtual function void pack(input bit winc,input bit rinc, input bit[WIDTH-1:0] wdata);

endclass:in_transaction

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

    super.new(name,parent);

endfunction:new

function in_transaction::pack(input bit winc,input bit rinc, input bit[WIDTH-1:0] wdata);

    this.winc <= winc;
    this.rinc <= rinc;
    this.wdata <= wdata;
    
endfunction:pack

2.1.2 in_sequence.sv

代码语言:cpp
复制
class in_sequence#(parameter WIDTH=8,parameter DEPTH=16) extends uvm_sequence#(in_transaction);

    in_transaction  req;
    int             seq_item_num;
    `uvm_object_utils(in_sequence)

    extern virtual function new(string name= "in_sequence",uvm_component parent);
    extern virtual task body();


endclass:in_sequence

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

    super.new(name,parent);

endfunction:new

task in_sequence::body();

    in_transaction tmp_req;

    if(!uvm_config_db#(int)::get(this,"","seq_item_num",this.seq_item_num))begin
        `uvm_fatal("","")
    end

    repeat(this.seq_item_num)begin
        uvm_create(tmp_req);
        assert(req.randomize());
        uvm_send(req);
    end

endtask

2.1.3 in_sequencer.sv

代码语言:cpp
复制
class in_sequencer#(parameter WIDTH=8,parameter DEPTH=16) extends uvm_sequencer#(in_transaction);

    `uvm_component_utils(in_sequencer)
    extern virtual function new(string name="in_sequencer",uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);

endclass:in_transaction

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

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

function in_sequencer::build_phase(uvm_phase phase);

    super.build_phase(phase);

endfunction:build_phase

2.1.4 in_driver.sv

代码语言:cpp
复制
class in_driver#(parameter WIDTH=8,parameter DEPTH=16) extends uvm_driver#(in_transaction);

    uvm_tlm_analysis_pull_port#(in_transaction)    seq_item_port;
    virtual in_interface                           in_bus;

    `uvm_component_utils(in_driver)

    extern virtual function new(string name="in_driver",uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase); 

endclass:in_driver

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

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

function in_driver::build_phase(uvm_phase phase);

    super.build_phase(phase);
    if(!uvm_config_db#(virtual in_interface)::get(this,"","in_bus",this,in_bus))begin
        `uvm_fatal("the bus has not been set","check in_driver bus")
    end
    this.seq_item_port = new("seq_item_port",this);
endfunction:build_phase

task in_driver::main_phase(uvm_phase phase);

    in_transaction req;

    super.main_phase(phase);

    while(1)begin
        if(this.seq_item_port.has_do_available())begin
            this.seq_item_port.get_next_item(req);
        end
        @this.in_bus.drv_cb;
        this.in_bus.winc <= req.winc;
        this.in_bus.rinc <= req.rinc;
        this.in_bus.wdata <= req.wdata;

    end

endtask:main_phase

2.1.5 in_monitor.sv

代码语言:cpp
复制
class in_monitor#(parameter WIDTH=8,parameter DEPTH=16) extends uvm_monitor#(in_transaction);

    in_interface              in_bus;

    logic                     winc;
    logic                     ricn;
    bit[WIDTH-1:0]            wdata;

    uvm_tlm_analysis_fifo#(in_transaction)          in_mon2rm_fifo;

    `uvm_component_utils(in_monitor)

    extern virtual function new(string name = "in_monitor",uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);

endclass:in_monitor

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

    super.new(name,parent);

endfunction:new

function void in_monitor::build_phase(uvm_phase phase);

    super.build_phase(phase);
    if(!uvm_config_db#(virtual in_interface)::get(this,"","in_bus",this.in_bus))begin
        `uvm_fatal("","")
    end

endfunction:build_phase

task in_monitor::main_phase(uvm_phase phase);

    automatic in_transaction            req;
    super.main_phase(phase);
    while(1)begin
        @this.in_bus.mon_cb;
        this.winc <= this.in_bus.winc;
        this.rinc <= this.in_bus.rinc;
        this.wdata <= this.in_bus.wdata;

        this.req = in_transaction::type_id::create("req",this);
        this.req.winc = this.winc;
        this.req.rinc = this.rinc;
        this.req.wdata = this.wdata;

        if(this.in_mon2rm_fifo != null)begin
            this.in_mon2rm_fifo.write(this.req);
        end

    end
endtask:main_phase

2.1.6 in_interface.sv

代码语言:cpp
复制
interface in_interface#(parameter WIDTH=8,parameter DEPTH=16)(input logic clk,input logic rst_n);

    logic               winc;
    logic               rinc;
    bit[WIDTH-1:0]      wdata;

    clocking in_drv_cb@(clk);
        output      winc;
        output      rinc;
        output      wdata;

        output      rst_n;

    endclocking:in_drv_cb

    clocking in_mon_cb@(clk);
        input       winc;
        input       rinc;
        input       wdata;

        input       rst_n;

    endclocking:in_mon_cb


endinterface:in_interface

3. 接口自测试

3.1 in_utils组件自验证

3.1.1 unit_test_env

代码语言:cpp
复制
class unit_test_env extends uvm_env;

    in_driver              drv;
    in_monitor             in_mon;
    in_monitor             out_mon;
    unit_test_rm           rm;
    in_sequencer           seqr;
    unit_test_scb          scb;

    `uvm_component_utils(unit_test_env)

    extern virtual function new(string name="unit_test_env",uvm_component parent);
    extren virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);
    extern virtual function void connect_phase(uvm_phase phase);

endclass:unit_test_env

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

    super.new(name,parent);

endfunction:unit_test_env

function void unit_test_env::build_phase(uvm_phase phase);

    super.build_phase(phase);
    this.drv = in_driver::type_id::create("drv",this);
    this.mon = in_monitor::type_id::create("mon",this);
    this.rm = unit_test_rm::type_id::create("rm",this);
    this.seqr = in_sequencer::type_id::create("seqr",this);
    this.scb = unit_test_scb::type_id::create("scb",this);

endfunction:build_phase

task unit_test_env::main_phase(uvm_phase phase);

    super.main_phase(phase);

endtask:main_phase

function void unit_test_env::connect_phase(uvm_phase phase);

    super.connect_phase(phase);
    this.drv.seq_item_port.connect(this.seqr.seq_item_export);
    this.rm.in_fifo = this.in_mon.in_mon2rm_fifo;
    this.scb.from_rm_fifo = this.rm.out2scb_fifo;
    this.scb.from_dut_fifo = this.out_mon.out_mon2scb_fifo;

endfunction:connect_phase

3.1.2 unit_test_rm.sv

代码语言:cpp
复制
class unit_test_rm extends uvm_component;

    uvm_tlm_analysis_fifo#(in_transaction)      in_fifo;
    uvm_tlm_analysis_fifo#(in_transaction)      out2scb_fifo;
    `uvm_component_utils(unit_test_rm)

    extern virtual function new(string name="unit_test_rm",uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);

endclass:unit_test_rm

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

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

function void unit_test_rm::build_phase(uvm_phase phase);

    super.build_phase(phase);
    this.in_fifo = new("in_fifo",this);
    this.out_fifo = new("out_fifo",this);

endfunction:build_phase

task unit_test_rm::main_phase(uvm_phase phase);

    in_transaction   req;

    super.main_phase(phase);
    while(1)begin
        if(this.in_fifo != null)begin
            this.in_fifo.get(req);
        end
        if(this.out2scb_fifo != null)begin
            this.out2scb_fifo.write(req);
        end
    end
    
endtask:main_phase

3.1.3 unit_test_scb.sv

代码语言:cpp
复制
class unit_test_scb extends uvm_scoreboard;

    uvm_tlm_analysis_fifo#(in_transaction)       from_rm_fifo;
    uvm_tlm_analysis_fifo#(in_transaction)       from_dut_fifo;

    `uvm_component_utils(unit_test_scb)

    extern virtual function new(string name="unit_test_scb",uvm_component parent);
    extren virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);

endclass:unit_test_scb

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

    super.new(name,parent);

endfunction:new

function void unit_test_scb::build_phase(uvm_phase phase);

    super.build_phase(phase);
    this.from_dut_fifo = new("from_dut_fifo",this);
    this.from_rm_fifo = new("from_rm_fifo",this);

endfunction:build_phase

task unit_test_scb::main_phase(uvm_phase phase);

    in_transaction              req_rm;
    in_transaction              req_dut;

    super.main_phase(phase);
    while(1)begin
        fork 
            begin
                if(this.from_rm_fifo != null)begin
                    this.from_rm_fifo.get(req_rm);
                    this.rm_fifo.write(req_rm);
                end
            end 
            begin
                if(this.from_dut_fifo != null)begin
                    this.from_dut_fifo.get(req_dut);
                    this.dut_fifo.write(req_dut);
                end
            end
            begin
                this.normal_check();
            end
        join

    end

endtask:main_phase

function void unit_test_scb::normal_check();

    in_transaction   rm_tr;
    in_transaction   dut_tr;

    if(this.dut_fifo.size()>0)begin
        dut_tr = this.dut_fifo.pop_front();
        if(this.rm_fifo.size()>0)begin
            rm_tr  = this.rm_fifo.pop_front();
        end
        result = dut_tr.compare(rm_tr);
        if(result)begin
            `uvm_info("","",UVM_LOW)
        end
        else begin
            `uvm_error("","")
        end
    end

endfunction:normal_check

3.1.4 out_monitor.sv

代码语言:cpp
复制
class in_monitor#(parameter WIDTH=8,parameter DEPTH=16) extends uvm_monitor#(in_transaction);

    in_interface              in_bus;

    logic                     winc;
    logic                     ricn;
    bit[WIDTH-1:0]            wdata;

    uvm_tlm_analysis_fifo#(in_transaction)          in_mon2rm_fifo;

    `uvm_component_utils(in_monitor)

    extern virtual function new(string name = "in_monitor",uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);

endclass:in_monitor

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

    super.new(name,parent);

endfunction:new

function void in_monitor::build_phase(uvm_phase phase);

    super.build_phase(phase);
    if(!uvm_config_db#(virtual in_interface)::get(this,"","in_bus",this.in_bus))begin
        `uvm_fatal("","")
    end

endfunction:build_phase

task in_monitor::main_phase(uvm_phase phase);

    automatic in_transaction            req;
    super.main_phase(phase);
    while(1)begin
        @this.in_bus.mon_cb;
        this.winc <= this.in_bus.winc;
        this.rinc <= this.in_bus.rinc;
        this.wdata <= this.in_bus.wdata;

        this.req = in_transaction::type_id::create("req",this);
        this.req.winc = this.winc;
        this.req.rinc = this.rinc;
        this.req.wdata = this.wdata;

        if(this.in_mon2rm_fifo != null)begin
            this.in_mon2rm_fifo.write(this.req);
        end

    end
endtask:main_phase

3.1.5 base_test.sv

代码语言:cpp
复制
class base_test extends uvm_test;

    unit_test_env           env;

    in_interface            in_bus;
    out_interface           out_bus;

    `uvm_component_utils(base_test)

    extern virtual function new(string name= "base_test",uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);

    
endclass:base_test

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

    super.new(name,parent);

endfunction:new

function void base_test::build_phase(uvm_phase phase);

    super.build_phase(phase);
    this.env = unit_test_env::type_id::create("env",this);
    if(!uvm_config_db#(virtual in_interface)::get(this,"","in_bus",this.in_bus))begin
        `uvm_fatal("","")
    end
    uvm_config_db#(virtual in_interface)::set(this,"env.in_agt.drv","in_bus",this.in_bus);
    uvm_config_db#(virtual in_interface)::set(this,"env.in_agt.mon","in_bus",this.in_bus);

endfunction:build_phase

task base_test::main_phase(uvm_phase phase);

    super.main_phase(phase);
    phase.raise_objection(this);

    this.wait(5000);

    phase.drop_objection(this);
    
endtask:main_phase

4. uvm中的tlm通信机制简介

uvm中的通信方式主要包含port、export、imp和analysis_port共四大类端口和fifo通信。

按照动作类型划分,在port、export、imp这四钟端口中还可以区分put、get、peek、get_peek和transport共五种动作,这五种动作又可以去区分为blocking、nonblocking和正常三种模式。

4. 1端口列表

4.1.1 port

代码语言:txt
复制
#### put action
uvm_put_port#(req);
uvm_blocking_put_port#(req);
uvm_nonblocking_put_port#(req);
#### get action
uvm_get_port#(req);
uvm_blocking_get_port#(req);
uvm_nonblocking_get_port#(req);
#### peek action
uvm_peek_port#(req);
uvm_blocking_peek_port#(req);
uvm_nonblocking_peek_port#(req);
#### get_peek action
uvm_get_peek_port#(req);
uvm_blocking_get_peek_port#(req);
uvm_nonblocking_get_peek_port#(req);
#### transport action
uvm_transport_port#(req,rsp);
uvm_blocking_transport_port#(req,rsp);
uvm_nonblocking_transport_port#(req,rsp);

4.1.2 export

代码语言:txt
复制
#### put action
uvm_put_export#(req);
uvm_blocking_put_export#(req);
uvm_nonblocking_put_export#(req);

#### get action
uvm_get_export#(req);
uvm_blocking_get_export#(req);
uvm_nonblocking_get_export#(req);

#### peek action
uvm_peek_export#(req);
uvm_blocking_peek_export#(req);
uvm_nonblocking_peek_export#(req);

#### get_peek action
uvm_get_peek_export#(req);
uvm_blocking_get_peek_export#(req);
uvm_nonblocking_get_peek_export#(req);

#### transport action
uvm_transport_export#(req,rsp);
uvm_blocking_transport_export#(req,rsp);
uvm_nonblocking_transport_export#(req,rsp);

4.1.3 imp

代码语言:txt
复制
#### put action
uvm_put_imp#(req,T);
uvm_blocking_put_imp#(req,T);
uvm_nonblocking_put_imp#(req,T);

#### get action
uvm_get_imp#(req,T);
uvm_blocking_get_imp#(req,T);
uvm_nonblocking_get_imp#(req,T);

#### peek action
uvm_peek_imp#(req,T);
uvm_blocking_peek_imp#(req,T);
uvm_nonblocking_peek_imp#(req,T);

#### get_peek action
uvm_get_peek_imp#(req,T);
uvm_blocking_get_peek_imp#(req,T);
uvm_nonblocking_get_peek_imp#(req,T);

#### transport action
uvm_transport_imp#(req,rsp,T);
uvm_blocking_transport_imp#(req,rsp,T);
uvm_nonblocking_transport_imp#(req,rsp,T);

4.1.4 analysis_port

代码语言:txt
复制
uvm_tlm_analysis_port#(req);
uvm_tlm_analysis_export#(req);

4.1.5 fifo

代码语言:txt
复制
uvm_tlm_analysis_fifo#(req);
uvm_analysis_fifo#(req);

4.2 端口之间的连接

4.2.1 端口之间的优先级

在port、export和imp之间是存在数据传输的优先级的,即优先级port>export>imp。端口之间的优先级限制了控制流的传输方向,即控制流只能由高优先级端口类型传向低优先级的端口,export不能向port提出控制流请求,但是可以向imp提出控制流请求。跨级之间的控制流请求是允许的,但是还是需要遵循优先级限制,即port直接向imp提出请求是允许的。

4.2.2 端口连接的数量和类型限制

默认情况下port、exporth和imp的连接是一对一的,除非在 初始化端口的时候去指定min_size和max_size。同时port、export和imp的put、get等类型需要保持一致,在imp所在的类中同时必须实现对应的方法,将在“端口连接的阻塞和非阻塞的约束”章节详细描述。

但是对于analysis_port则没有数量的限制,因为analysis_port的连接是广播的形式。因此,对analysis_port来说也没有阻塞和非阻塞的约束,uvm_tlm_analysis_port#(req)和uvm_tlm_analysis_export#(req)只有一个方法,即write(req)方法。

4.2.3 端口连接的阻塞和非阻塞的约束

通过上面的描述,port、export和imp类型的端口是由阻塞和非阻塞的区分的,*_blocking_*类型的端口是阻塞的,其对应的方法是put()、get()、peek()、get_peek()和transport。*_nonblocking_*是非阻塞的,对应的方法是try_put、can_put、try_get、can_get......等。

对于analysis_port来讲由于是广播,所以不存在阻塞和非阻塞的概念。

4.2.4 port和export、imp的连接

代码语言:txt
复制
首先阻塞、动作类型需要保持一致;
class A extends uvm_component;

    transaction              tr;
    
    uvm_blocking_put_port#(transaction)       block_put_port;
    uvm_blocking_get_port#(transaction)       block_get_port;
    uvm_nonblocking_put_port#(transaction)     nonblock_put_port;
    ......
    
    virtual task main_phase(uvm_phase phase);
        .......
        this.block_put_port.put(tr);
        this.block_get_port.get(tr);
        if(this.nonblock_put_port.can_put())begin
            this.nonblock_put_port.try_put(tr);
        end
    endtask:main_phase
endclass:A

class B extends uvm_component;

    uvm_blocking_put_port#(transaction)       block_put_export;
    uvm_blocking_get_port#(transaction)       block_put_export;
    uvm_nonblocking_put_port#(transaction)     nonblock_put_export;
    
    uvm_blocking_put_imp#(transaction,this)       block_put_imp;
    uvm_blocking_get_imp#(transaction,this)       block_put_imp;
    uvm_nonblocking_put_imp#(transaction,this)    nonblock_put_imp;
    
    ......
    
    virtual function void put(transaction tr);
        .......
    endfunction:put
    virtual function void get(transaction tr);
        .......
    endfunction:put
    virtual function void try_put(transaction tr);
        .......
    endfunction:put
    virtual function void can_put(transaction tr);
        .......
    endfunction:put
    
    virtual function void connect_phase(uvm_phase phase);
        .......
        this.block_put_export.connect(this.block_put_imp);
        this.block_get_export.connect(this.block_get_imp);
        this.nonblock_put_export.connect(this.nonblock_put_imp);
    
    endfunction:connect_phase
    
endclass:B

class env extends uvm_env;

    A     A_inst;
    B     B_inst;
    
    ......
    virtual function void connect_phase(uvm_phase phase);
        A_inst.block_put_port.connect(B_inst.block_put_export);
        A_inst.block_get_port.connect(B_inst.block_get_export);
        A_inst.nonblock_put_port.connect(B_inst.nonblock_put_export);
    
    endfunction:connect_phase
endclass:env

4.2.5 port和imp的直接连接

代码语言:txt
复制
首先阻塞、动作类型需要保持一致;
class A extends uvm_component;

    transaction              tr;
    
    uvm_blocking_put_port#(transaction)       block_put_port;
    uvm_blocking_get_port#(transaction)       block_get_port;
    uvm_nonblocking_put_port#(transaction)     nonblock_put_port;
    ......
    
    virtual task main_phase(uvm_phase phase);
        .......
        this.block_put_port.put(tr);
        this.block_get_port.get(tr);
        if(this.nonblock_put_port.can_put())begin
            this.nonblock_put_port.try_put(tr);
        end
    endtask:main_phase
endclass:A

class B extends uvm_component;
    
    uvm_blocking_put_imp#(transaction,this)       block_put_imp;
    uvm_blocking_get_imp#(transaction,this)       block_put_imp;
    uvm_nonblocking_put_imp#(transaction,this)    nonblock_put_imp;
    
    ......
    
    virtual function void put(transaction tr);
        .......
    endfunction:put
    virtual function void get(transaction tr);
        .......
    endfunction:put
    virtual function void try_put(transaction tr);
        .......
    endfunction:put
    virtual function void can_put(transaction tr);
        .......
    endfunction:put
    
    virtual function void connect_phase(uvm_phase phase);
        .......
    
    endfunction:connect_phase
    
endclass:B

class env extends uvm_env;

    A     A_inst;
    B     B_inst;
    
    ......
    virtual function void connect_phase(uvm_phase phase);
        A_inst.block_put_port.connect(B_inst.block_put_imp);
        A_inst.block_get_port.connect(B_inst.block_get_imp);
        A_inst.nonblock_put_port.connect(B_inst.nonblock_put_imp);
    
    endfunction:connect_phase
endclass:env

4.2.6 analysis_port和imp的连接

代码语言:txt
复制
首先阻塞、动作类型需要保持一致;
class A extends uvm_component;

    transaction              tr;
    
    uvm_tlm_analysis_port#(transaction)        A_ap_port;
    ......
    
    virtual task main_phase(uvm_phase phase);
        .......
        this.A_ap_port.write(tr);
    endtask:main_phase
endclass:A

class B extends uvm_component;
    
    uvm_tlm_analysis_imp(transaction, B)    B_imp;
    
    ......
    
    virtual function void write(transaction tr);
        .......
    endfunction:write
    
endclass:B

class C extends uvm_component;
    
    uvm_tlm_analysis_imp(transaction, C)    C_imp;
    
    ......
    
    virtual function void write(transaction tr);
        .......
    endfunction:write
    
endclass:C

class env extends uvm_env;

    A     A_inst;
    B     B_inst;
    
    ......
    virtual function void connect_phase(uvm_phase phase);
        A_inst.A_ap_port.connect(B_inst.B_imp);
        A_inst.A_ap_port.connect(C_inst.C_imp);
    endfunction:connect_phase
    
endclass:env

4.2.7 fifo通信

fifo简介:

本质上fifo是fifo加uvm_analysis_imp。fifo中包含许多端口,通过观察uvm中的tlm1.0代码可知大部分port本质上都是uvm_*_imp;

uvm源代码:

代码语言:cpp
复制
virtual class uvm_tlm_fifo_base #(type T=int) extends uvm_component;

  typedef uvm_tlm_fifo_base #(T) this_type;
  
  // Port: put_export
  //
  // The ~put_export~ provides both the blocking and non-blocking put interface
  // methods to any attached port:
  //
  //|  task put (input T t)
  //|  function bit can_put ()
  //|  function bit try_put (input T t)
  //
  // Any ~put~ port variant can connect and send transactions to the FIFO via this
  // export, provided the transaction types match. See <uvm_tlm_if_base #(T1,T2)>
  // for more information on each of the above interface methods.

  uvm_put_imp #(T, this_type) put_export;
  

  // Port: get_peek_export
  //
  // The ~get_peek_export~ provides all the blocking and non-blocking get and peek
  // interface methods:
  //
  //|  task get (output T t)
  //|  function bit can_get ()
  //|  function bit try_get (output T t)
  //|  task peek (output T t)
  //|  function bit can_peek ()
  //|  function bit try_peek (output T t)
  //
  // Any ~get~ or ~peek~ port variant can connect to and retrieve transactions from
  // the FIFO via this export, provided the transaction types match. See
  // <uvm_tlm_if_base #(T1,T2)> for more information on each of the above interface
  // methods.

  uvm_get_peek_imp #(T, this_type) get_peek_export;  


  // Port: put_ap
  //
  // Transactions passed via ~put~ or ~try_put~ (via any port connected to the
  // <put_export>) are sent out this port via its ~write~ method.
  //
  //|  function void write (T t)
  //
  // All connected analysis exports and imps will receive put transactions.
  // See <uvm_tlm_if_base #(T1,T2)> for more information on the ~write~ interface
  // method.

  uvm_analysis_port #(T) put_ap;


  // Port: get_ap
  //
  // Transactions passed via ~get~, ~try_get~, ~peek~, or ~try_peek~ (via any
  // port connected to the <get_peek_export>) are sent out this port via its
  // ~write~ method.
  //
  //|  function void write (T t)
  //
  // All connected analysis exports and imps will receive get transactions.
  // See <uvm_tlm_if_base #(T1,T2)> for more information on the ~write~ method.

  uvm_analysis_port #(T) get_ap;


  // The following are aliases to the above put_export.

  uvm_put_imp      #(T, this_type) blocking_put_export;
  uvm_put_imp      #(T, this_type) nonblocking_put_export;

  // The following are all aliased to the above get_peek_export, which provides
  // the superset of these interfaces.

  uvm_get_peek_imp #(T, this_type) blocking_get_export;
  uvm_get_peek_imp #(T, this_type) nonblocking_get_export;
  uvm_get_peek_imp #(T, this_type) get_export;
  
  uvm_get_peek_imp #(T, this_type) blocking_peek_export;
  uvm_get_peek_imp #(T, this_type) nonblocking_peek_export;
  uvm_get_peek_imp #(T, this_type) peek_export;
  
  uvm_get_peek_imp #(T, this_type) blocking_get_peek_export;
  uvm_get_peek_imp #(T, this_type) nonblocking_get_peek_export;


  // Function: new
  //
  // The ~name~ and ~parent~ are the normal uvm_component constructor arguments. 
  // The ~parent~ should be ~null~ if the uvm_tlm_fifo is going to be used in a
  // statically elaborated construct (e.g., a module). The ~size~ indicates the
  // maximum size of the FIFO. A value of zero indicates no upper bound.

  function new(string name, uvm_component parent = null);
    super.new(name, parent);

    put_export = new("put_export", this);
    blocking_put_export     = put_export;
    nonblocking_put_export  = put_export;

    get_peek_export = new("get_peek_export", this);
    blocking_get_peek_export    = get_peek_export;
    nonblocking_get_peek_export = get_peek_export;
    blocking_get_export         = get_peek_export;
    nonblocking_get_export      = get_peek_export;
    get_export                  = get_peek_export;
    blocking_peek_export        = get_peek_export;
    nonblocking_peek_export     = get_peek_export;
    peek_export                 = get_peek_export;

    put_ap = new("put_ap", this);
    get_ap = new("get_ap", this);
    
  endfunction

  //turn off auto config
  function void build_phase(uvm_phase phase);
    build(); //for backward compat, won't cause auto-config
    return;
  endfunction

  virtual function void flush();
    uvm_report_error("flush", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
  endfunction
  
  virtual function int size();
    uvm_report_error("size", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual task put(T t);
    uvm_report_error("put", `UVM_TLM_FIFO_TASK_ERROR, UVM_NONE);
  endtask

  virtual task get(output T t);
    uvm_report_error("get", `UVM_TLM_FIFO_TASK_ERROR, UVM_NONE);
  endtask

  virtual task peek(output T t);
    uvm_report_error("peek", `UVM_TLM_FIFO_TASK_ERROR, UVM_NONE);
  endtask
  
  virtual function bit try_put(T t);
    uvm_report_error("try_put", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual function bit try_get(output T t);
    uvm_report_error("try_get", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual function bit try_peek(output T t);
    uvm_report_error("try_peek", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction
  
  virtual function bit can_put();
    uvm_report_error("can_put", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual function bit can_get();
    uvm_report_error("can_get", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual function bit can_peek();
    uvm_report_error("can_peek", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual function uvm_tlm_event ok_to_put();
    uvm_report_error("ok_to_put", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return null;
  endfunction

  virtual function uvm_tlm_event ok_to_get();
    uvm_report_error("ok_to_get", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return null;
  endfunction

  virtual function uvm_tlm_event ok_to_peek();
    uvm_report_error("ok_to_peek", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return null;
  endfunction

  virtual function bit is_empty();
    uvm_report_error("is_empty", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

  virtual function bit is_full();
    uvm_report_error("is_full", `UVM_TLM_FIFO_FUNCTION_ERROR);
    return 0;
  endfunction

  virtual function int used();
    uvm_report_error("used", `UVM_TLM_FIFO_FUNCTION_ERROR, UVM_NONE);
    return 0;
  endfunction

endclass

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. DUT示例代码
  • 2. 验证环境示例代码
    • 2.1 in_utils组件
      • 2.1.1 in_transaction.sv
      • 2.1.2 in_sequence.sv
      • 2.1.3 in_sequencer.sv
      • 2.1.4 in_driver.sv
      • 2.1.5 in_monitor.sv
      • 2.1.6 in_interface.sv
  • 3. 接口自测试
    • 3.1 in_utils组件自验证
      • 3.1.1 unit_test_env
      • 3.1.2 unit_test_rm.sv
      • 3.1.3 unit_test_scb.sv
      • 3.1.4 out_monitor.sv
      • 3.1.5 base_test.sv
  • 4. uvm中的tlm通信机制简介
    • 4. 1端口列表
      • 4.1.1 port
      • 4.1.2 export
      • 4.1.3 imp
      • 4.1.4 analysis_port
      • 4.1.5 fifo
    • 4.2 端口之间的连接
      • 4.2.1 端口之间的优先级
      • 4.2.2 端口连接的数量和类型限制
      • 4.2.3 端口连接的阻塞和非阻塞的约束
      • 4.2.4 port和export、imp的连接
      • 4.2.5 port和imp的直接连接
      • 4.2.6 analysis_port和imp的连接
      • 4.2.7 fifo通信
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档