目录
5.7.1 An objection in the test component
5.7.2 An objection in the sequence
5.7.2.1 with set_starting_phase and get_starting_phase methods
5.7.2.2 with set_automatic_phase_objection method
uvm_objection类提供了一种机制来协调两个或多个组件(对象)之间的状态信息。uvm_objection类是从uvm_report_object扩展而来的。
class uvm_objection extends uvm_report_object
objection涉及raise和drop objection的概念,即内部计数器分别为递增和递减。每个参与的组件和对象可以异步raise或这drop objections。当所有objectons被drop时,计数器值将变为零。必须在开始任何流程/事务之前raise objection,并在流程/事务处理完成后drop。
task reset_phase( uvm_phase phase);
phase.raise_objection(this);
...
phase.drop_objection(this);
endtask
task run_phase(uvm_phase phase);
phase.raise_objection(this, "Raised Objection");
...
phase.drop_objection(this, "Dropped Objection");
endtask
注:
1. objections通常用在components和sequences。
2. 其他objects也可以使用objections,但是他们必须使用一个component或者sequence对象上下文。?
回调方法在从uvm_callback类派生的uvm_objection_callback类中定义。
所有objections之间的等待时间已被drop,调用all_dropped()回调函数称为drain time。【没明白】
在下面的示例中,没有建立完整的driver、sequence和sequencer之间的通信,因为其目的是为了讲清楚objections机制。
在执行run_phase之前调用raise_objection。一旦run_phase的活动完成,就会调用drop_objection。test的run_phase如下所述。
class seq_item extends uvm_sequence_item;
rand bit[15:0] addr;
rand bit[15:0] data;
`uvm_object_utils(seq_item)
function new(string name = "seq_item");
super.new(name);
endfunction
endclass
class base_seq extends uvm_sequence #(seq_item);
seq_item req;
`uvm_object_utils(base_seq)
function new (string name = "base_seq");
super.new(name);
endfunction
task body();
`uvm_info(get_type_name(), "Base seq: Body started", UVM_LOW);
req = seq_item::type_id::create("req");
// send to the driver
#20;
`uvm_info(get_type_name(), "Base seq: Body completed", UVM_LOW);
endtask
endclass
class base_test extends uvm_test;
base_seq bseq;
`uvm_component_utils(base_test)
function new(string name = "base_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this, "Raise Objection");
bseq = base_seq::type_id::create("bseq");
bseq.start(null);
phase.drop_objection(this, "Drop Objection");
endtask
endclass
module tb_top;
initial begin
run_test("base_test");
end
endmodule
Output:
?
UVM_INFO testbench.sv(17) @ 0: reporter@@bseq [base_seq] Base seq: Body started
UVM_INFO testbench.sv(21) @ 20: reporter@@bseq [base_seq] Base seq: Body completed
可以在body task或pre_body/post_body task中raise(提起)和drop(撤销)objection。
class base_seq extends uvm_sequence #(seq_item);
...
task pre_body();
if(starting_phase != null) starting_phase.raise_objection(this);
endtask
task body();
req = seq_item::type_id::create("req");
// send to the driver
#20;
...
endtask
task post_body();
if(starting_phase != null) starting_phase.drop_objection(this);
endtask
endclass
建议不要将上述代码与uvm1.2一起使用,因为作starting_phase()方法来自uvm_sequence_base在uvm1.2中已被弃用。
sequence中的objection机制可以与以下两种方法一起使用。
两种新方法set_starting_phase and get_starting_phase作为替换被添加。
顾名思义set_starting_phase and get_starting_phase用于设置和检索phase。
注:如果get_starting_phase返回null,那么sequence将不会raise和drop(提起和撤销)objection。
class seq_item extends uvm_sequence_item;
rand bit[15:0] addr;
rand bit[15:0] data;
`uvm_object_utils(seq_item)
function new(string name = "seq_item");
super.new(name);
endfunction
endclass
class base_seq extends uvm_sequence #(seq_item);
seq_item req;
uvm_phase phase;
`uvm_object_utils(base_seq)
function new (string name = "base_seq");
super.new(name);
endfunction
task pre_body();
`uvm_info(get_type_name(), "Inside pre_body", UVM_LOW);
phase = get_starting_phase; // Retrieve phase information
if (phase != null) phase.raise_objection(this);
endtask
task body();
`uvm_info(get_type_name(), "Base seq: Body started", UVM_LOW);
req = seq_item::type_id::create("req");
// send to the driver
#20;
`uvm_info(get_type_name(), "Base seq: Body completed", UVM_LOW);
endtask
task post_body();
`uvm_info(get_type_name(), "Inside post_body", UVM_LOW);
if (phase != null) phase.drop_objection(this);
endtask
endclass
class base_test extends uvm_test;
base_seq bseq;
`uvm_component_utils(base_test)
function new(string name = "base_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
bseq = base_seq::type_id::create("bseq");
bseq.set_starting_phase(phase); // Set starting phase
bseq.start(null);
endtask
endclass
module tb_top;
initial begin
run_test("base_test");
end
endmodule
Output:?
UVM_INFO testbench.sv(18) @ 0: reporter@@bseq [base_seq] Inside pre_body
UVM_INFO testbench.sv(24) @ 0: reporter@@bseq [base_seq] Base seq: Body started
UVM_INFO testbench.sv(28) @ 20: reporter@@bseq [base_seq] Base seq: Body completed
UVM_INFO testbench.sv(32) @ 20: reporter@@bseq [base_seq] Inside post_body
uvm1.2还添加了set_automatic_phase_objection自动raise和drop当前sequence的objection。相应的,在执行sequence之前无需调用raise_objection,sequence执行结束之前无需调用drop_objection。
相反,设置set_automatic_phase_objection(1)?在sequence的new()?函数中或者在sequence start之前。
class seq_item extends uvm_sequence_item;
rand bit[15:0] addr;
rand bit[15:0] data;
`uvm_object_utils(seq_item)
function new(string name = "seq_item");
super.new(name);
endfunction
endclass
class base_seq extends uvm_sequence #(seq_item);
seq_item req;
uvm_phase phase;
`uvm_object_utils(base_seq)
function new (string name = "base_seq");
super.new(name);
endfunction
task pre_body();
`uvm_info(get_type_name(), "Inside pre_body", UVM_LOW);
endtask
task body();
`uvm_info(get_type_name(), "Base seq: Body started", UVM_LOW);
req = seq_item::type_id::create("req");
// send to the driver
#20;
`uvm_info(get_type_name(), "Base seq: Body completed", UVM_LOW);
endtask
task post_body();
`uvm_info(get_type_name(), "Inside post_body", UVM_LOW);
endtask
endclass
class base_test extends uvm_test;
base_seq bseq;
`uvm_component_utils(base_test)
function new(string name = "base_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
bseq = base_seq::type_id::create("bseq");
bseq.set_starting_phase(phase);
bseq.set_automatic_phase_objection(1);
bseq.start(null);
endtask
endclass
module tb_top;
initial begin
run_test("base_test");
end
endmodule
Output:
UVM_INFO testbench.sv(18) @ 0: reporter@@bseq [base_seq] Inside pre_body
UVM_INFO testbench.sv(22) @ 0: reporter@@bseq [base_seq] Base seq: Body started
UVM_INFO testbench.sv(26) @ 20: reporter@@bseq [base_seq] Base seq: Body completed
UVM_INFO testbench.sv(30) @ 20: reporter@@bseq [base_seq] Inside post_body
注:如果sequence的body里有一个forever循环请不要设置set_automatic_phase_objection(1),因为objections将永远不会被drop。