UVM 2020-2.0 early release is out and i thought it would be fun to deep dive into one of the differences and try to understand why that change was made.

I thought that was an interesting one!

< // we use a queue here only to avoid any problems on writing to variables
< // inside an always_comb/latch/ff in case those call UVM
< uvm_core_state m_uvm_core_state[$];
---
> uvm_core_state m_uvm_core_state = UVM_CORE_UNINITIALIZED;

So, what does this comment mean? Let’s start with uvm_core_state. well, that was easy.

typedef enum {
	UVM_CORE_UNINITIALIZED,
        UVM_CORE_PRE_INIT,
        UVM_CORE_INITIALIZING,
	UVM_CORE_INITIALIZED, // UVM_CORE_POST_INIT
	UVM_CORE_PRE_RUN,
	UVM_CORE_RUNNING,
	UVM_CORE_POST_RUN,
	UVM_CORE_FINISHED,
	UVM_CORE_PRE_ABORT,
	UVM_CORE_ABORTED
} uvm_core_state;

grepping through src

./base/uvm_object_globals.svh:uvm_core_state m_uvm_core_state[$];
./base/uvm_root.svh:          m_uvm_core_state.push_front(UVM_CORE_PRE_ABORT);
./base/uvm_root.svh:          m_uvm_core_state.push_front(UVM_CORE_ABORTED);
./base/uvm_root.svh:        m_uvm_core_state.push_front(UVM_CORE_PRE_RUN);
./base/uvm_root.svh:        m_uvm_core_state.push_front(UVM_CORE_POST_RUN);
./base/uvm_root.svh:        m_uvm_core_state.push_front(UVM_CORE_FINISHED);
./base/uvm_globals.svh:   if (m_uvm_core_state.size() == 0) return UVM_CORE_UNINITIALIZED;
./base/uvm_globals.svh:   else return m_uvm_core_state[0];
./base/uvm_globals.svh:  m_uvm_core_state.push_front(UVM_CORE_PRE_INIT);
./base/uvm_globals.svh:  m_uvm_core_state.push_front(UVM_CORE_INITIALIZING);
./base/uvm_globals.svh:  m_uvm_core_state.push_front(UVM_CORE_INITIALIZED);
./base/uvm_phase.svh:  m_uvm_core_state.push_front(UVM_CORE_RUNNING);

There is a getter in ./base/uvm_globals.svh which returns the first element in the queue

function uvm_core_state get_core_state();
   if (m_uvm_core_state.size() == 0) return UVM_CORE_UNINITIALIZED;
   else return m_uvm_core_state[0];
endfunction

Which is called from the following places

./base/uvm_root.svh:          if (get_core_state() inside {UVM_CORE_PRE_ABORT,UVM_CORE_ABORTED})
./base/uvm_globals.svh:  if(get_core_state()!=UVM_CORE_UNINITIALIZED) begin
./base/uvm_globals.svh:    if (get_core_state() == UVM_CORE_PRE_INIT) begin
./base/uvm_registry.svh:     if (uvm_pkg::get_core_state() != UVM_CORE_UNINITIALIZED) begin
./base/uvm_registry.svh:     if (uvm_pkg::get_core_state() == UVM_CORE_UNINITIALIZED) begin

From what i see, state gets pushed in several places but never pop’ed out. hmmmm! At this point, I am still baffled. The comment says

// we use a queue here only to avoid any problems on writing to variables
// inside an always_comb/latch/ff in case those call UVM

but who calls UVM inside always!???? Now i have to do part2.