Difficulty: Easy · Puzzle 1 of 6 · Topic: UVM Phases and Objections
UVM 1.2. The hierarchy is uvm_test_top -> env -> agent -> drv (each created by its parent in build_phase). Every component derives from the logger below. Give the order of component names printed for build_phase, connect_phase, report_phase and final_phase.
class phase_logger extends uvm_component;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("PH", $sformatf("build %s", get_name()), UVM_LOW)
endfunction
function void connect_phase(uvm_phase phase);
`uvm_info("PH", $sformatf("connect %s", get_name()), UVM_LOW)
endfunction
function void report_phase(uvm_phase phase);
`uvm_info("PH", $sformatf("report %s", get_name()), UVM_LOW)
endfunction
function void final_phase(uvm_phase phase);
`uvm_info("PH", $sformatf("final %s", get_name()), UVM_LOW)
endfunction
endclassTwo of the four phases walk top-down and two walk bottom-up. Think about why build must be one of the top-down ones.
1) build_phase is top-down: a parent's build_phase must run first because that is where it creates its children. Order: uvm_test_top, env, agent, drv.
2) connect_phase is bottom-up (children before parents), so by the time a parent connects, its children's own internal connections are already made. Order: drv, agent, env, uvm_test_top.
3) report_phase is bottom-up like the other function phases of the post-run group (extract, check, report): drv, agent, env, uvm_test_top.
4) final_phase is top-down: uvm_test_top, env, agent, drv.Answer: build: test, env, agent, drv. connect: drv, agent, env, test. report: drv, agent, env, test. final: test, env, agent, drv.
Checked by running the code in Verilator 5; the printed output supports the answer above. Hand-written model of the documented UVM 1.2 behaviour in plain SystemVerilog (Verilator), not the UVM library: each phase walks a chain of four components top-down (parent first) or bottom-up (children first); the tree is prebuilt here, whereas UVM creates children inside the parent's build_phase.
Siblings are not ordered by creation: within one level the traversal follows the parent's child list (sorted by instance name), so never rely on one sibling's build or connect having run before another's.
Why can a parent's connect_phase safely call `agent.mon.ap.connect(sb.exp_imp)` while a parent's build_phase can not safely use `agent.mon`? Model answer: connect_phase is bottom-up, so the agent and monitor have already finished build AND their own connect before the env connects across them; build_phase is top-down, so when env.build_phase runs the agent has only just been created by it (or not at all) and its own build_phase has not run yet.