多生产者单消费者怎么办?
What to do in case of multiple producer and single consumer?
在开发测试平台时,您可能会遇到多个生产者和一个消费者的情况。
例如单个记分板(消费者)从驱动程序和监视器(多个生产者)接收数据。
如何通过端口连接将多个生产者的数据发送给消费者?
验证工程师在多个生产者和一个消费者的情况下经常遇到这种情况。
如果使用端口连接,那么对于所有生产者,在单个消费者中必须有不同的方法。但是只有一种"write"方法(用于分析端口)。
如何实现这个东西!!
UVM 支持这样的功能,可以帮助您完成此操作。
这可以在分析端口的帮助下实现。
让我们考虑以下场景:
有三个生产者和一个消费者。
现在所有三个生产者都调用了消费者的写方法。
为此,您必须执行以下步骤:
您必须在消费者之前声明宏 class。
例如`uvm_analysis_imp_decl( _name )
端口声明如下:
e.g.uvm_analysis_imp_name#(交易,consumer_1)write_imp_1;
现在可以修改write方法的名称为write_name.
e.g.function void write_name(事务tr_inst);
$display("Function called");
结束函数
这里是多个生产者和一个消费者的示例代码,可以让您更加清楚。
Multiple producers and a single consumer
代码
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
这里我也提供了scoreboard(单个消费者)和driver、monitor(多个生产者)的示例代码
Driver, Monitor and Scoreboard connection
代码
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
在开发测试平台时,您可能会遇到多个生产者和一个消费者的情况。
例如单个记分板(消费者)从驱动程序和监视器(多个生产者)接收数据。
如何通过端口连接将多个生产者的数据发送给消费者?
验证工程师在多个生产者和一个消费者的情况下经常遇到这种情况。
如果使用端口连接,那么对于所有生产者,在单个消费者中必须有不同的方法。但是只有一种"write"方法(用于分析端口)。
如何实现这个东西!!
UVM 支持这样的功能,可以帮助您完成此操作。 这可以在分析端口的帮助下实现。
让我们考虑以下场景: 有三个生产者和一个消费者。 现在所有三个生产者都调用了消费者的写方法。 为此,您必须执行以下步骤:
您必须在消费者之前声明宏 class。
例如`uvm_analysis_imp_decl( _name )
端口声明如下:
e.g.uvm_analysis_imp_name#(交易,consumer_1)write_imp_1;
现在可以修改write方法的名称为write_name.
e.g.function void write_name(事务tr_inst);
$display("Function called");
结束函数
这里是多个生产者和一个消费者的示例代码,可以让您更加清楚。
Multiple producers and a single consumer
代码
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
这里我也提供了scoreboard(单个消费者)和driver、monitor(多个生产者)的示例代码
Driver, Monitor and Scoreboard connection
代码
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