有没有办法将 uvm_tlm_analysis_fifo 连接到 uvm_driver?
Is there a way to connect uvm_tlm_analysis_fifo to uvm_driver?
我需要将模块输出连接到由 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 连接到 master 的 seq_item_port
。有没有办法实施这样的计划?如果driver真的可以只从sequencer中获取item,如何手动将sequencer中的item写入seq_item_port
?
您需要 uvm_sequencer
和 seq_item_export
才能连接到 driver 的 seq_item_port
。你没有。
如果要使用fifo路径,需要在driver class.
中创建并连接一个通用端口
这是 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
的实现,其任务是在它们之间传递序列项。我认为你可以创建一个假的音序器来处理它(并且单独留下 driver)。
正如我所怀疑的,没有定序器我无法实现问题方案。所以结果方案如下:
----- ---------
| 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
我需要将模块输出连接到由 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 连接到 master 的 seq_item_port
。有没有办法实施这样的计划?如果driver真的可以只从sequencer中获取item,如何手动将sequencer中的item写入seq_item_port
?
您需要 uvm_sequencer
和 seq_item_export
才能连接到 driver 的 seq_item_port
。你没有。
如果要使用fifo路径,需要在driver class.
中创建并连接一个通用端口这是 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
的实现,其任务是在它们之间传递序列项。我认为你可以创建一个假的音序器来处理它(并且单独留下 driver)。
正如我所怀疑的,没有定序器我无法实现问题方案。所以结果方案如下:
----- ---------
| 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