Test requirement is like,
1) When polling for more than one interrupts by
continuously reading different registers in parallel and based on some
indication move to next phase of UVM
2) Waiting for some timer to be expired and then
moving to next phase of UVM
Let’s take one scenario where,
Driver is raising objection but never dropping objection and requirement
is to move to next phase (extract_phase) after #50 timeunit. But because all
the objection are not dropped in run_phase, simulation is not going to
extract_phase.
Let’s go through example.
-------------------------------------------------------------------------
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class my_seq_item extends uvm_sequence_item; | |
rand bit [31:0] data; | |
rand bit [7:0] addr; | |
`uvm_object_utils_begin(my_seq_item) | |
`uvm_field_int(addr, UVM_DEFAULT | UVM_HEX) | |
`uvm_field_int(data, UVM_DEFAULT | UVM_HEX) | |
`uvm_object_utils_end | |
function new (string name = "my_seq_item"); | |
super.new(name); | |
endfunction : new | |
function string convert2string(); | |
convert2string = $sformatf("addr:0x%h, data:0x%h", addr, data); | |
return convert2string; | |
endfunction : convert2string | |
endclass : my_seq_item | |
class my_seq extends uvm_sequence#(my_seq_item); | |
`uvm_object_utils(my_seq) | |
function new (string name = "my_seq"); | |
super.new(name); | |
endfunction : new | |
task body(); | |
`uvm_create(req) | |
start_item(req); | |
if (!req.randomize()) begin | |
`uvm_fatal(get_name(), $sformatf("Randomization of %s failed", req.get_type_name())) | |
end | |
finish_item(req); | |
endtask : body | |
endclass : my_seq | |
class my_seqr extends uvm_sequencer#(my_seq_item); | |
`uvm_component_utils(my_seqr) | |
function new (string name = "my_seqr", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
endclass : my_seqr | |
class my_driver extends uvm_driver#(my_seq_item); | |
`uvm_component_utils(my_driver) | |
function new (string name = "my_driver", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
endfunction : build_phase | |
task run_phase(uvm_phase phase); | |
forever begin | |
seq_item_port.get_next_item(req); | |
drive(phase); | |
seq_item_port.item_done(); | |
end | |
endtask : run_phase | |
task drive(uvm_phase phase); | |
phase.raise_objection(this); | |
#5; | |
`uvm_info(get_name(), $sformatf("in drive method req:\n%s", req.convert2string()), UVM_LOW) | |
// Objection is not dropped | |
//phase.drop_objection(this); | |
endtask : drive | |
endclass : my_driver | |
class my_agent extends uvm_agent; | |
my_seqr seqr; | |
my_driver drv; | |
`uvm_component_utils(my_agent) | |
function new (string name = "my_agent", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
seqr = my_seqr :: type_id :: create ("seqr", this); | |
drv = my_driver :: type_id :: create ("drv", this); | |
endfunction : build_phase | |
function void connect_phase (uvm_phase phase); | |
super.connect_phase(phase); | |
drv.seq_item_port.connect(seqr.seq_item_export); | |
endfunction : connect_phase | |
endclass : my_agent | |
class my_test extends uvm_test; | |
my_agent agent; | |
`uvm_component_utils(my_test) | |
function new (string name = "my_test", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
agent = my_agent :: type_id :: create ("agent", this); | |
endfunction : build_phase | |
task run_phase(uvm_phase phase); | |
my_seq seq; | |
seq = my_seq :: type_id :: create("seq"); | |
phase.raise_objection(this); | |
seq.start(agent.seqr); | |
phase.drop_objection(this); | |
endtask : run_phase | |
endclass : my_test | |
module top(); | |
initial begin | |
run_test("my_test"); | |
end | |
endmodule : top | |
//Output: | |
// UVM_INFO @ 0: reporter [RNTST] Running test my_test... | |
// UVM_INFO no_objection_drop.sv(67) @ 5: uvm_test_top.agent.drv [drv] in drive method req: | |
// addr:0x82, data:0x5455120d | |
// UVM_FATAL /opt/uvm-1.2/src/base/uvm_phase.svh(1489) @ 9200000000000: reporter [PH_TIMEOUT] Default timeout of 9200000000000 hit, indicating a probable testbench issue |
-------------------------------------------------------------------------
Now let’s take another scenario,
Here driver is dropping objection after #105 timeunit. So simulation
will move to next phase after #105. But the requirement is to move to next
phase which is extract_phase after #50.
Let’s go through example.
-------------------------------------------------------------------------
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class my_seq_item extends uvm_sequence_item; | |
rand bit [31:0] data; | |
rand bit [7:0] addr; | |
`uvm_object_utils_begin(my_seq_item) | |
`uvm_field_int(addr, UVM_DEFAULT | UVM_HEX) | |
`uvm_field_int(data, UVM_DEFAULT | UVM_HEX) | |
`uvm_object_utils_end | |
function new (string name = "my_seq_item"); | |
super.new(name); | |
endfunction : new | |
function string convert2string(); | |
convert2string = $sformatf("addr:0x%h, data:0x%h", addr, data); | |
return convert2string; | |
endfunction : convert2string | |
endclass : my_seq_item | |
class my_seq extends uvm_sequence#(my_seq_item); | |
`uvm_object_utils(my_seq) | |
function new (string name = "my_seq"); | |
super.new(name); | |
endfunction : new | |
task body(); | |
`uvm_create(req) | |
start_item(req); | |
if (!req.randomize()) begin | |
`uvm_fatal(get_name(), $sformatf("Randomization of %s failed", req.get_type_name())) | |
end | |
finish_item(req); | |
endtask : body | |
endclass : my_seq | |
class my_seqr extends uvm_sequencer#(my_seq_item); | |
`uvm_component_utils(my_seqr) | |
function new (string name = "my_seqr", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
endclass : my_seqr | |
class my_driver extends uvm_driver#(my_seq_item); | |
`uvm_component_utils(my_driver) | |
function new (string name = "my_driver", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
endfunction : build_phase | |
task run_phase(uvm_phase phase); | |
forever begin | |
seq_item_port.get_next_item(req); | |
drive(phase); | |
seq_item_port.item_done(); | |
end | |
endtask : run_phase | |
task drive(uvm_phase phase); | |
phase.raise_objection(this); | |
#5; | |
`uvm_info(get_name(), $sformatf("in drive method req:\n%s", req.convert2string()), UVM_LOW) | |
//Dropping objection from driver after #105 timeunit | |
fork | |
begin | |
#100; | |
`uvm_info(get_name(), $sformatf("in drive, dropping objection"), UVM_LOW) | |
phase.drop_objection(this); | |
end | |
join_none | |
endtask : drive | |
endclass : my_driver | |
class my_agent extends uvm_agent; | |
my_seqr seqr; | |
my_driver drv; | |
`uvm_component_utils(my_agent) | |
function new (string name = "my_agent", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
seqr = my_seqr :: type_id :: create ("seqr", this); | |
drv = my_driver :: type_id :: create ("drv", this); | |
endfunction : build_phase | |
function void connect_phase (uvm_phase phase); | |
super.connect_phase(phase); | |
drv.seq_item_port.connect(seqr.seq_item_export); | |
endfunction : connect_phase | |
endclass : my_agent | |
class my_test extends uvm_test; | |
my_agent agent; | |
`uvm_component_utils(my_test) | |
function new (string name = "my_test", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
agent = my_agent :: type_id :: create ("agent", this); | |
endfunction : build_phase | |
task run_phase(uvm_phase phase); | |
my_seq seq; | |
fork | |
begin | |
#50; //Timer | |
// After #50 timeunit wants to move to next phase (extract_phase) | |
end | |
join_none | |
seq = my_seq :: type_id :: create("seq"); | |
phase.raise_objection(this); | |
seq.start(agent.seqr); | |
phase.drop_objection(this); | |
endtask : run_phase | |
function void extract_phase(uvm_phase phase); | |
// Expecting to execute at timeunit #50, but executing at #105 | |
`uvm_info(get_name(), $sformatf("Executing extract_phase"), UVM_LOW) | |
endfunction : extract_phase | |
endclass : my_test | |
module top(); | |
initial begin | |
run_test("my_test"); | |
end | |
endmodule : top | |
//Output: | |
// UVM_INFO @ 0: reporter [RNTST] Running test my_test... | |
// UVM_INFO objection_dropped_after_timeout.sv(67) @ 5: uvm_test_top.agent.drv [drv] in drive method req: | |
// addr:0x82, data:0x5455120d | |
// UVM_INFO objection_dropped_after_timeout.sv(73) @ 105: uvm_test_top.agent.drv [drv] in drive, dropping objection | |
// UVM_INFO /opt/uvm-1.2/src/base/uvm_objection.svh(1270) @ 105: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase | |
// UVM_INFO objection_dropped_after_timeout.sv(132) @ 105: uvm_test_top [uvm_test_top] Executing extract_phase |
-------------------------------------------------------------------------
To fulfill the requirement we need to any how drop the pending objection
after #50 to move to next phase after #50.
We can do this by getting list of all uvm_components (through
get_objector method of uvm_objection class) who raised objection and then we
can manually drop the objection after #50 timeunit.
Let’s go through example.
-------------------------------------------------------------------------
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class my_seq_item extends uvm_sequence_item; | |
rand bit [31:0] data; | |
rand bit [7:0] addr; | |
`uvm_object_utils_begin(my_seq_item) | |
`uvm_field_int(addr, UVM_DEFAULT | UVM_HEX) | |
`uvm_field_int(data, UVM_DEFAULT | UVM_HEX) | |
`uvm_object_utils_end | |
function new (string name = "my_seq_item"); | |
super.new(name); | |
endfunction : new | |
function string convert2string(); | |
convert2string = $sformatf("addr:0x%h, data:0x%h", addr, data); | |
return convert2string; | |
endfunction : convert2string | |
endclass : my_seq_item | |
class my_seq extends uvm_sequence#(my_seq_item); | |
`uvm_object_utils(my_seq) | |
function new (string name = "my_seq"); | |
super.new(name); | |
endfunction : new | |
task body(); | |
`uvm_create(req) | |
start_item(req); | |
if (!req.randomize()) begin | |
`uvm_fatal(get_name(), $sformatf("Randomization of %s failed", req.get_type_name())) | |
end | |
finish_item(req); | |
endtask : body | |
endclass : my_seq | |
class my_seqr extends uvm_sequencer#(my_seq_item); | |
`uvm_component_utils(my_seqr) | |
function new (string name = "my_seqr", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
endclass : my_seqr | |
class my_driver extends uvm_driver#(my_seq_item); | |
`uvm_component_utils(my_driver) | |
function new (string name = "my_driver", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
endfunction : build_phase | |
task run_phase(uvm_phase phase); | |
forever begin | |
seq_item_port.get_next_item(req); | |
drive(phase); | |
seq_item_port.item_done(); | |
end | |
endtask : run_phase | |
task drive(uvm_phase phase); | |
phase.raise_objection(this); | |
#5; | |
`uvm_info(get_name(), $sformatf("in drive method req:\n%s", req.convert2string()), UVM_LOW) | |
// Objection is not dropped | |
//phase.drop_objection(this); | |
endtask : drive | |
endclass : my_driver | |
class my_agent extends uvm_agent; | |
my_seqr seqr; | |
my_driver drv; | |
`uvm_component_utils(my_agent) | |
function new (string name = "my_agent", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
seqr = my_seqr :: type_id :: create ("seqr", this); | |
drv = my_driver :: type_id :: create ("drv", this); | |
endfunction : build_phase | |
function void connect_phase (uvm_phase phase); | |
super.connect_phase(phase); | |
drv.seq_item_port.connect(seqr.seq_item_export); | |
endfunction : connect_phase | |
endclass : my_agent | |
class my_test extends uvm_test; | |
my_agent agent; | |
`uvm_component_utils(my_test) | |
function new (string name = "my_test", uvm_component parent = null); | |
super.new(name, parent); | |
endfunction : new | |
function void build_phase(uvm_phase phase); | |
super.build_phase(phase); | |
agent = my_agent :: type_id :: create ("agent", this); | |
endfunction : build_phase | |
task run_phase(uvm_phase phase); | |
my_seq seq; | |
fork | |
begin | |
#50; //Timer | |
drop_all_objection(phase); | |
end | |
join_none | |
seq = my_seq :: type_id :: create("seq"); | |
phase.raise_objection(this); | |
seq.start(agent.seqr); | |
phase.drop_objection(this); | |
endtask : run_phase | |
function void drop_all_objection(uvm_phase phase); | |
uvm_objection objection; | |
uvm_object object_q[$]; | |
// Get objection handle for current phase | |
objection = phase.get_objection(); | |
// Get list of the uvm_components which doesn't drop the objection | |
objection.get_objectors(object_q); | |
// Dropping all the objection from all the objectors | |
foreach(object_q[i]) begin | |
while (objection.get_objection_count(object_q[i]) > 0) begin | |
`uvm_info(get_type_name(),$sformatf("Dropping objection:%0d for object:%s", i, object_q[i].get_full_name()), UVM_LOW) | |
objection.drop_objection(object_q[i]); | |
end | |
end | |
endfunction : drop_all_objection | |
endclass : my_test | |
module top(); | |
initial begin | |
run_test("my_test"); | |
end | |
endmodule : top | |
//Output: | |
// UVM_INFO @ 0: reporter [RNTST] Running test my_test... | |
// UVM_INFO drop_all_objection.sv(67) @ 5: uvm_test_top.agent.drv [drv] in drive method req: | |
// addr:0x82, data:0x5455120d | |
// UVM_INFO drop_all_objection.sv(137) @ 50: uvm_test_top [my_test] Dropping objection:1 for object:uvm_test_top.agent.drv | |
// UVM_INFO /opt/uvm-1.2/src/base/uvm_objection.svh(1270) @ 50: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase |
-------------------------------------------------------------------------
with
ReplyDeleteobjection.get_objectors(object_q);
will we get component names only where the objection is not dropped or we'll get all the component name where either objection is raised or dropped or both.
You will get all the component names.
ReplyDeleteThis is an awesome post.Really very informative and creative contents. These concept is a good way to enhance the knowledge.I like it and help me to development very well.Thank you for this brief explanation and very nice information.Well, got a good knowledge.
ReplyDeletePhp projects with source code
Online examination system in php
Student management system in php
Php projects for students
Free source code for academic
Academic projects provider in nashik
Academic project free download
Amazing Blog, Thanks for shraring this informative post with us.
ReplyDeleteHipla is an all-in-one-workplace automation platform making your workplace smarter, safer & secure. We are one of the leading service providers of Visitor Management Systems Software.
For more information:
Call us: +918527718300
Email: info@hipla.io