Build phase execution

Hello,

I have a few questions about how UVM starts the test execution.

uvm_root::run_test runs the phases by executing uvm_phase::m_run_phases()

  1. uvm_root is inherited from uvm_component. This means that uvm_test doesn’t have the run_test function.
    I thought that the simulation starts with run_test(), which is a part of the uvm_test, but this is not correct.
    How does it make sense?
  2. uvm_phase::m_run_phases() starts executing phases, but the only UVC, which it knows about, is the test itself.
    I believe that somehow, build_phase of the test is called (however, haven’t seen it in the code).
    build_phase of the test contains create functions of other UVCs.
    Does it mean that create function calls build phases of the created components?
    Otherwise, how are other build phases called?

Thanks,
Alex

In reply to Alex K.:

uvm_root is a singleton representing the top level component. Every uvm_component you create with a null parent constructor argument has this singleton set as it parent. That includes the top-level test use specify with +UVM_TESTNAME or the string name you pass to uvm_pkg::run_test(name).

uvm_pkg::run_test(name) is a wrapper that calls the uvm_root::run_test() method. It starts by executing the build_phase, which is traversed top-down. This means it picks a child component of the top-level uvm_root class and executes its build_phase, which is typically the uvm_test specified by +UVM_TESTNAME. As soon the build_phase return, it tries to execute the build_phase of a child of the component whose build_phase just returned. It does not matter that there were no children before the test build_phase started, it only checks for children after the build_phase returns.

The top-down build_phase recursively keep trying to execute the build_phase of the child it just created, until there are no more children. Then it looks to see if it has any siblings. If it does, it calls the build_phase of it sibling, which may create children of its own and the process is repeated. Once there are no more siblings, then it goes up a level and looks for more siblings. When this process completes (no siblings and no more levels to go up) the UVM will have completed a depth-first traversal of all the uvm components.

In reply to dave_59:

Than you, Dave.

One more question:
"
As soon the build_phase return, it tries to execute the build_phase of a child of the component whose build_phase just returned. It does not matter that there were no children before the test build_phase started, it only checks for children after the build_phase returns.
"
Is the children’s registration done by the macro: `uvm_component_utils_begin(my_env)?
And, in particular, this line inside the macro?
static bit m_registered_converter__ = m_uvm_resource_sprint_converter#(my_env)::register();

Thanks,
Alex

In reply to Alex K.:

No. That macros has little to do with phasing. You pass the parent component to the constructor of the child component, and that’s where the child is registered.

The
`uvm_component_utils_begin
macro does two things:

  • It makes the class usable by the factory by registering the type and a string name in a global database, and by declaring the necessary functions to do the factory create and overrides.
  • It adds a lot of code that makes the field automation macros work. The only thing related to the build_phase is when you call super.build_phase(), it executes code that calls uvm_config_db::get() for each field you have registered.

We strongly discourage the use of the field automation macros and prefer that you just use
`uvm_component_utils
instead. See MacroCostBenefit | Verification Academy

In reply to dave_59:

Thank you, Dave.

In reply to dave_59:

“As soon the build_phase return, it tries to execute the build_phase of a child of the component whose build_phase just returned. It does not matter that there were no children before the test build_phase started, it only checks for children after the build_phase returns.”

In what order does UVM execute the child build phases of a UVM component? Are the children chosen randomly? Are they executed in the order they are created in the parent build phase? Some other scheme, perhaps?

In reply to jmlemay:

I am not sure the UVM defines an ordering, but it seems the same order they are created.

See UVM component hierarchy and phase ordering - EDA Playground