我需要将模块输出连接到受uvm_driver
控制的输入上。
我是这样看的。
----- ---------------------
| MON |---->|uvm_tlm_analysis_fifo|
----- ---------------------
^ |
| |
------------- | ------- |
| |---------->| slave | v
| DUT | ------- --------
| |<---------------------| master |
------------- --------
我尝试了以下方法。
typedef class seq_item extends uvm_sequence_item;
typedef class driver extends uvm_driver(seq_item);
class agent extends uvm_agent;
`uvm_component_utils(agent)
uvm_analysis_port#(seq_item) ap;
uvm_tlm_analysis_fifo#(seq_item) fifo;
driver drv;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
ap = new("ap", this);
fifo= new("fifo",this);
drv = driver::type_id::create("driver", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap.connect(fifo.analysis_export);
drv.seq_item_port.connect(fifo.get_peek_export);
endfunction: connect_phase
task main_phase(uvm_phase phase);
seq_item trans;
phase.raise_objection(this);
repeat(5) begin
trans = seq_item::type_id::create("inTrans");
assert(trans.randomize());
ap.write(trans);
end
phase.drop_objection(this);
endtask
endclass: agent
这里是最小的,可重复的示例。
`include "uvm_macros.svh"
package t;
import uvm_pkg::*;
class seq_item extends uvm_sequence_item;
`uvm_object_utils(seq_item)
rand bit [31:0] data;
function new(string name = "seq_item");
super.new(name);
endfunction: new
endclass: seq_item
class driver extends uvm_driver#(seq_item);
`uvm_component_utils(driver)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction: new
task main_phase(uvm_phase phase);
fork
super.main_phase(phase);
join_none
forever begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(),$psprintf("Got item with data: %h",req.data),UVM_NONE);
seq_item_port.item_done();
end
endtask: main_phase
endclass: driver
class test extends uvm_test;
`uvm_component_utils(test)
uvm_analysis_port#(seq_item) ap;
uvm_tlm_analysis_fifo#(seq_item) fifo;
driver drv;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
ap = new(.name("apb_ap"), .parent(this));
fifo= new("fifo",this);
drv = driver ::type_id::create(.name("driver"), .parent(this) );
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap.connect(fifo.analysis_export);
drv.seq_item_port.connect(fifo.get_peek_export);
endfunction: connect_phase
task main_phase(uvm_phase phase);
seq_item trans;
phase.raise_objection(this);
repeat(5) begin
trans = seq_item::type_id::create("inTrans");
assert(trans.randomize());
ap.write(trans);
end
phase.drop_objection(this);
endtask
endclass: test
endpackage
module top();
import uvm_pkg::*;
import t::*;
initial begin
run_test();
end
endmodule
它会产生以下错误。
** Error: (vsim-7065) 5.sv(51): Illegal assignment to class mtiUvm.uvm_pkg::uvm_port_base #(class mtiUvm.uvm_pkg::uvm_sqr_if_base #(class work.t::seq_item, class work.t::seq_item)) from class mtiUvm.uvm_pkg::uvm_get_peek_imp #(class work.t::seq_item, class mtiUvm.uvm_pkg::uvm_tlm_fifo_base #(class work.t::seq_item))
# Time: 0 ns Iteration: 0 Region: /t File: 5.sv
# ** Error: (vsim-8754) 5.sv(51): Actual input arg. of type 'class mtiUvm.uvm_pkg::uvm_get_peek_imp #(class work.t::seq_item, class mtiUvm.uvm_pkg::uvm_tlm_fifo_base #(class work.t::seq_item))' for formal 'provider' of 'connect' is not compatible with the formal's type 'class mtiUvm.uvm_pkg::uvm_port_base #(class mtiUvm.uvm_pkg::uvm_sqr_if_base #(class work.t::seq_item, class work.t::seq_item))'.
据我所知,我无法将fifo连接到主人的seq_item_port
。有没有办法实施这种方案?如果驱动程序真的可以从音序器中获取项目,如何将音序器中的项目手动写入seq_item_port
?
答案 0 :(得分:1)
您需要一个uvm_sequencer
和seq_item_export
才能连接到驱动程序的seq_item_port
。您没有一个。
如果要使用fifo路径,则需要在驱动程序类中创建并连接通用端口。
这是vcs生成的消息:
Error-[ICTTFC] Incompatible complex type usage
Incompatible complex type usage in task or function call.
The following expression is incompatible with the formal parameter of the
function. The type of the actual is 'class uvm_pkg::uvm_get_peek_imp#(class
t::seq_item,class uvm_pkg::uvm_tlm_fifo_base#(class t::seq_item))', while
the type of the formal is 'class uvm_pkg::uvm_port_base#(class
uvm_pkg::uvm_sqr_if_base#(class t::seq_item,class t::seq_item))'.
Expression: this.fifo.get_peek_export
Source info: this.drv.seq_item_port.connect(this.fifo.get_peek_export)
据我所知,您仍然需要创建一个端口以及自己的seq_item_export
的实现,其任务是在它们之间传递序列项。我认为您可以创建一个伪造的音序器来处理它(并让驱动程序不理会)。
答案 1 :(得分:0)
我怀疑,如果没有音序器,我将无法实施问题解决方案。因此结果方案如下:
----- ---------
| MON |---->|sequencer|
----- | ------|
^ | | fifo |
| ---------
------------- | ------- |
| |-------->| slave | v
| DUT | ------- --------
| |<-----------------| master |
------------- --------
问题是如何使定序器在不运行序列的情况下写入seq_item_export。如上答案中所述,要实现这一点,我需要在自定义sequencer class中实现get_next_item
任务,如下所示:
class fifo_sequencer#(type REQ=uvm_sequence_item,RSP=REQ) extends uvm_sequencer#(REQ,RSP);
`uvm_component_param_utils(fake_sequencer#(REQ,RSP))
uvm_tlm_analysis_fifo#(REQ) fifo;
function new(string name, uvm_component parent);
super.new(name, parent);
fifo = new("fifo", this);
endfunction
task get_next_item(output REQ t);
fifo.get_peek_export.get(t);
endtask
function void item_done(RSP item = null);
if (item != null) begin
seq_item_export.put_response(item);
end
endfunction
endclass
请注意,除了get_next_item task
之外,还必须实现item_done function
(否则您可能会遇到Item_done() called with no outstanding requests
fatal_error)。
因此,最小的,可复制的示例将转换为:
`include "uvm_macros.svh"
package t;
import uvm_pkg::*;
class seq_item extends uvm_sequence_item;
`uvm_object_utils(seq_item)
rand bit [31:0] data;
function new(string name = "seq_item");
super.new(name);
endfunction: new
endclass: seq_item
class driver extends uvm_driver#(seq_item);
`uvm_component_utils(driver)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction: new
task main_phase(uvm_phase phase);
fork
super.main_phase(phase);
join_none
forever begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(),$psprintf("Got item with data: %h",req.data),UVM_NONE);
seq_item_port.item_done();
end
endtask: main_phase
endclass: driver
class fifo_sequencer#(type REQ=uvm_sequence_item,RSP=REQ) extends uvm_sequencer#(REQ,RSP);
`uvm_component_param_utils(fifo_sequencer#(REQ,RSP))
uvm_tlm_analysis_fifo#(REQ) fifo;
function new(string name, uvm_component parent);
super.new(name, parent);
fifo = new("fifo", this);
endfunction
task get_next_item(output REQ t);
fifo.get_peek_export.get(t);
endtask
function void item_done(RSP item = null);
if (item != null) begin
seq_item_export.put_response(item);
end
endfunction
endclass
class test extends uvm_test;
`uvm_component_utils(test)
uvm_analysis_port#(seq_item) ap;
driver drv;
fifo_sequencer#(seq_item) sqr;
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
ap = new("apb_ap", this);
sqr = fifo_sequencer#(seq_item) ::type_id::create("sequencer", this);
drv = driver ::type_id::create("driver", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap.connect(sqr.fifo.analysis_export);
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction: connect_phase
task main_phase(uvm_phase phase);
seq_item trans;
phase.raise_objection(this);
repeat(5) begin
trans = seq_item::type_id::create("inTrans");
assert(trans.randomize());
ap.write(trans);
end
phase.drop_objection(this);
endtask
endclass: test
endpackage
module top();
import uvm_pkg::*;
import t::*;
initial begin
run_test();
end
endmodule