2016-07-05 25 views

回答

2

当有多个生产者和一个消费者时,验证工程师经常会遇到这种情况。

如果使用端口连接,那么对于所有的生产者,在单个消费者中必须有不同的方法。但是只有一个“写入”方法(用于分析端口)。

如何实现这件事!

UVM支持这种功能,以帮助您做到这一点。 这可以借助分析端口进行。

让我们考虑以下情景: 有三个生产者和一个消费者。 现在所有三个生产者都称为消费者的写作方法。 为此,您必须遵循以下步骤:

您必须在使用者类之前声明宏。

e.g.`uvm_analysis_imp_decl(_name

端口声明是这样的:

e.g.uvm_analysis_imp _name#(事务,consumer_1)write_imp_1;

现在您可以将写入方法的名称修改为write_name

egfunction void write _name(transaction tr_inst);

$ display(“Function called”);

endfunction这样

这里是多个生产者示例代码和一个单一的消费者,给你更清晰。

Multiple producers and a single consumer

CODE

class transaction extends uvm_sequence_item; 
    `uvm_object_utils(transaction); 
    rand int unsigned a; 
    rand int unsigned b; 

    function new(string name =""); 
    super.new(name); 
    endfunction 

endclass 


class producer_1 extends uvm_component; 
    `uvm_component_utils(producer_1); 
    transaction tr_inst; 
    uvm_analysis_port #(transaction) producer_1_to_consumer_p; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    producer_1_to_consumer_p = new("producer_1_to_consumer_p",this); 
    tr_inst = new("tr_inst"); 
    endfunction 


    task run_phase(uvm_phase phase) ; 
    super.run_phase(phase); 
    phase.raise_objection(this);  
    tr_inst.randomize with {{b < 20};{a < 20};}; 
    $display("Write the data"); 
    tr_inst.a = 10; tr_inst.b = 20; 
    producer_1_to_consumer_p.write(tr_inst); 
    phase.drop_objection(this); 
    endtask 

endclass 

class producer_2 extends uvm_component; 
    `uvm_component_utils(producer_2); 
    transaction tr_inst; 
    uvm_analysis_port #(transaction) producer_2_to_consumer_p; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    producer_2_to_consumer_p = new("producer_2_to_consumer_p",this); 
    tr_inst = new("tr_inst"); 
    endfunction 


    task run_phase(uvm_phase phase) ; 
    super.run_phase(phase); 
    phase.raise_objection(this); 

    tr_inst.randomize with {{b < 20};{a < 20};}; 
    $display("Write the data"); 
    tr_inst.a = 10; tr_inst.b = 20; 
    producer_2_to_consumer_p.write(tr_inst); 
    phase.drop_objection(this); 
    endtask 

endclass 

class producer_3 extends uvm_component; 
    `uvm_component_utils(producer_3); 
    transaction tr_inst; 
    uvm_analysis_port #(transaction) producer_3_to_consumer_p; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    producer_3_to_consumer_p = new("producer_3_to_consumer_p",this); 
    tr_inst = new("tr_inst"); 
    endfunction 


    task run_phase(uvm_phase phase) ; 
    super.run_phase(phase); 
    phase.raise_objection(this); 

    tr_inst.randomize with {{b < 20};{a < 20};}; 
    $display("Write the data"); 
    tr_inst.a = 10; tr_inst.b = 20; 
    producer_3_to_consumer_p.write(tr_inst); 
    phase.drop_objection(this); 
    endtask 

endclass 

`uvm_analysis_imp_decl(_pro_1) 
`uvm_analysis_imp_decl(_pro_2) 
`uvm_analysis_imp_decl(_pro_3) 

class consumer_1 extends uvm_component; 
    `uvm_component_utils(consumer_1); 

    uvm_analysis_imp_pro_1#(transaction,consumer_1) write_imp_1; 
    uvm_analysis_imp_pro_2#(transaction,consumer_1) write_imp_2; 
    uvm_analysis_imp_pro_3#(transaction,consumer_1) write_imp_3; 
    //transaction tr_inst; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    write_imp_1 = new("write_imp_1",this); 
    write_imp_2 = new("write_imp_2",this); 
    write_imp_3 = new("write_imp_3",this); 
    endfunction 

    function void write_pro_1(transaction tr_inst); 
    $display("Got the data"); 
    `uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW); 
    endfunction 

    function void write_pro_2(transaction tr_inst); 
    $display("Got the data"); 
    `uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW); 
    endfunction 

    function void write_pro_3(transaction tr_inst); 
    $display("Got the data"); 
    `uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW); 
    endfunction 

endclass 



class env extends uvm_component; 
    `uvm_component_utils(env); 

    producer_1 p_inst_1; 
    producer_2 p_inst_2; 
    producer_3 p_inst_3; 
    consumer_1 c_inst_1; 

    function new(string name="",uvm_component parent); 
    super.new(name,parent); 
    p_inst_1 = new("p_inst_1",this); 
    p_inst_2 = new("p_inst_2",this); 
    p_inst_3 = new("p_inst_3",this); 
    c_inst_1 = new("c_inst_1",this); 

    endfunction 

    function void connect(); 
    p_inst_1.producer_1_to_consumer_p.connect(c_inst_1.write_imp_1); 
    p_inst_2.producer_2_to_consumer_p.connect(c_inst_1.write_imp_2); 
    p_inst_3.producer_3_to_consumer_p.connect(c_inst_1.write_imp_3); 
    endfunction 

endclass 

module main(); 

    env env_inst; 
    initial 
    begin 
    env_inst = new("env_inst",null); 
    run_test(); 
    end 

endmodule 

在这里,我还提供了用于一个记分板的示例代码(单个消费者)和驱动器,监视器(多个生产者)。

Driver, Monitor and Scoreboard connection

CODE

class transaction extends uvm_sequence_item; 
    `uvm_object_utils(transaction); 
    rand int unsigned a; 
    rand int unsigned b; 
    rand int unsigned sum; 

    function new(string name =""); 
    super.new(name); 
    endfunction 

endclass 

class driver extends uvm_driver; 
    `uvm_component_utils(driver); 
    transaction tr_inst; 
    uvm_analysis_port #(transaction) driver_to_sb_p; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    driver_to_sb_p = new("driver_to_sb_p",this); 
    tr_inst = new("tr_inst"); 
    endfunction 


    task run_phase(uvm_phase phase) ; 
    super.run_phase(phase); 
    phase.raise_objection(this);  
    `uvm_info("DRIVER","driver drive the data to scoreboard",UVM_LOW) 
    tr_inst.a = 10; tr_inst.b = 20; 
    tr_inst.sum = tr_inst.a + tr_inst.b; 
    driver_to_sb_p.write(tr_inst); 
    phase.drop_objection(this); 
    endtask 

endclass 

class monitor extends uvm_monitor; 
    `uvm_component_utils(monitor); 
    transaction tr_inst; 
    uvm_analysis_port #(transaction) monitor_to_sb_p; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    monitor_to_sb_p = new("monitor_to_sb_p",this); 
    tr_inst = new("tr_inst"); 
    endfunction 


    task run_phase(uvm_phase phase) ; 
    super.run_phase(phase); 
    phase.raise_objection(this); 
    `uvm_info("MONITOR","monitor drive the data to scoreboard",UVM_LOW) 
    tr_inst.a = 10; tr_inst.b = 20; 
    tr_inst.sum = tr_inst.a + tr_inst.b; 
    monitor_to_sb_p.write(tr_inst); 
    phase.drop_objection(this); 
    endtask 

endclass 

`uvm_analysis_imp_decl(_dri) 
`uvm_analysis_imp_decl(_mon) 

class scoreboard extends uvm_scoreboard; 
    `uvm_component_utils(scoreboard); 
    int dri_sum,mon_sum; 
    uvm_analysis_imp_dri#(transaction,scoreboard) write_imp_1; 
    uvm_analysis_imp_mon#(transaction,scoreboard) write_imp_2; 
    //transaction tr_inst; 

    function new(string name ="",uvm_component parent); 
    super.new(name,parent); 
    write_imp_1 = new("write_imp_1",this); 
    write_imp_2 = new("write_imp_2",this); 
    endfunction 

    function void write_dri(transaction tr_inst); 
    `uvm_info("SCORE BOARD","Receive data form driver",UVM_LOW) 
     `uvm_info("SCORE BOARD",$sformatf("the value of a = %0d and b = %0d sum = %0d",tr_inst.a,tr_inst.b,tr_inst.sum),UVM_LOW); 
    dri_sum = tr_inst.sum; 
    endfunction 

    function void write_mon(transaction tr_inst); 
    `uvm_info("SCORE BOARD","Receive data form monitor",UVM_LOW) 
    `uvm_info("SCORE BOARD",$sformatf("the value of a = %0d and b = %0d sum = %0d",tr_inst.a,tr_inst.b,tr_inst.sum),UVM_LOW); 
    mon_sum = tr_inst.sum; 
    endfunction 

    task compare_data(); 
    if (mon_sum == dri_sum) 
     begin 
     `uvm_info("SCORE BOARD","--------- data is matched ----------",UVM_LOW) 
     end 
    else 
     begin 
     `uvm_info("SCORE BOARD","data is not matched",UVM_LOW) 
     end 
    endtask 

    task run_phase(uvm_phase phase) ; 
    super.run_phase(phase); 
    phase.raise_objection(this); 
    compare_data(); 
    phase.drop_objection(this); 
    endtask 

endclass 

class env extends uvm_component; 
    `uvm_component_utils(env); 

    driver dri_inst; 
    monitor mon_inst; 
    scoreboard sb_inst; 

    function new(string name="",uvm_component parent); 
    super.new(name,parent); 
    dri_inst = new("dri_inst",this); 
    mon_inst = new("mon_inst",this); 
    sb_inst = new("sb_inst",this); 

    endfunction 

    function void connect(); 
    dri_inst.driver_to_sb_p.connect(sb_inst.write_imp_1); 
    mon_inst.monitor_to_sb_p.connect(sb_inst.write_imp_2); 
    endfunction 

endclass 


module main(); 

    env env_inst; 
    initial 
    begin 
    env_inst = new("env_inst",null); 
    run_test(); 
    end 

endmodule 
+0

为什么分号;在'uvm_component_utils(司机);'和所有其他()?我认为这不是一个单一的消费者,但它是不同生产者的不同港口和单一类别的不同(进出口)港口之间的一对一连接。所以,它可能仍然是一对一的连接。 (生产者端口总数=消费者端口总数) – sharvil111

+1

在宣布宏时,分号(;)没有任何区别。 –

+1

是的,它是一对一连接(监视器和驱动程序)与单个消费者(记分板)的连接。驾驶员和监视器与一个记分牌连接。为什么它不是一个消费者?记分板接收(消费)来自两个不同组件的数据。 (生产者端口总数=消费者端口总数)但仍然有两个不同的组件(监视器和驱动程序)和一个组件(记分板)。 –

相关问题