I am confused with the relationship of run_phase and main_phase.
so I do a experiment. I used run_phase and main_phase in different component.
when I run the flowing code, I found the code of main_phase in sys_env do not execute. why?
when I add “phase.raise_objection(this);” “phase.drop_objection(this)” into main_phase of sys_env, then uvm prints “sys_env run over”. this result accords with my idea.
`timescale 1ns/1ps
module tb();
import uvm_pkg::*;
`include "uvm_macros.svh"
class sys_env extends uvm_env;
`uvm_component_utils(sys_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task main_phase(uvm_phase phase);
//phase.raise_objection(this);
#4ns;
`uvm_info("ENV", "sys_env run over!", UVM_LOW)
//phase.drop_objection(this);
endtask
endclass
class sys_test extends uvm_env;
`uvm_component_utils(sys_test)
sys_env m_env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
m_env = sys_env::type_id::create("m_env", this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
#20ns;
`uvm_info("TEST", "sys_test run over!", UVM_LOW)
phase.drop_objection(this);
endtask
endclass
initial begin
$timeformat(-9, 0, "ns", 5);
run_test("sys_test");
end
endmodule
Thanks for your reply, Dave.
I will follow your advice(raise an objection in any task-based phase) in my real project.
but I am really curious with the relationship of run_phase and main_phase(run time phase).
In many papers or UVM spec, they all told me that run_phase and run time phase execute concurrently.
but Compare the above code, why the following code run, uvm can print “TEST” and “ENV” message.
They don’t look like a simple parallel relationship.
`timescale 1ns/1ps
module tb();
import uvm_pkg::*;
`include "uvm_macros.svh"
class sys_env extends uvm_env;
`uvm_component_utils(sys_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task main_phase(uvm_phase phase);
phase.raise_objection(this);
#40ns;
`uvm_info("ENV", "sys_env run over!", UVM_LOW)
phase.drop_objection(this);
endtask
endclass
class sys_test extends uvm_env;
`uvm_component_utils(sys_test)
sys_env m_env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
m_env = sys_env::type_id::create("m_env", this);
endfunction
task run_phase(uvm_phase phase);
//phase.raise_objection(this);
#20ns;
`uvm_info("TEST", "sys_test run over!", UVM_LOW)
//phase.drop_objection(this);
endtask
endclass
initial begin
$timeformat(-9, 0, "ns", 5);
run_test("sys_test");
end
endmodule
Yes, it adds to the complexity. There is no standard definition of what goes in each phase, and that can make coordination with other VIP difficult. It’s easy to look at and maintain the flow of sequences in a test. The phases are there if you find it makes things easier, but the use is not widespread.