如果有多个生产者和单个消费者,该怎么办?

时间:2016-07-05 19:01:31

标签: system-verilog verification uvm

在开发测试平台时,您可能面临多个生产者和单个消费者的情况。

e.g。单个记分板(消费者)从驱动程序和监视器(多个生产者)接收数据。

如何借助端口连接将数据从多个生产者发送到消费者?

1 个答案:

答案 0 :(得分:2)

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

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

如何实现这个目标!!

UVM支持此类功能,以帮助您实现此目的。 借助分析端口可以实现这一点。

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

您必须在消费者类之前声明宏。

例如.uvm_analysis_imp_decl( _name

端口声明如下:

eguvm_analysis_imp _name #(transaction,consumer_1)write_imp_1;

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

egfunction void write _name (transaction tr_inst);

$ display(“函数调用”);

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