UVM: Drop All Objections

In continuation with my previous post about Tests without sequence, today I would like to share another situational post about UVM that I came across recently.

The test requirement is framed like this: Whenever a timer (let’s say interrupt timer) gets expired, move out from run_phase and proceed with remaining phases like extract_phase, report_phase etc. In short, whenever timer expires, the sequence should stop execution and simulation should continue to next phases. Something like follows:

// In test
task run_phase(uvm_phase phase);
phase.raise_objection(this);
some_seq.start(some_sequencer);
phase.drop_objection(this);
endtask

// In test extract_phase
function extract_phase(uvm_phase phase);
// Check packets, if timer is not expired.
// Else, check whether expiry of timer was valid or not.
endfunction

// In some other component
task run_phase(uvm_phase phase);
interrupt_timer(); // interrupt timer based on clock pulse count
endtask

// In driver
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(tx);
//
seq_item_port.item_done(tx);
end
endtask

As usual, I have raised UVM objections from sequences (some specific sequences) and testcase. Now if the timer (interrupt timer) expired and sequence was still on-going, then due to not dropping of the objection, the simulation won’t move out from run_phase ever. And my expectations never meets.

Somehow I need to stop the sequence. Or, I can just move forward/jump in phase. UVM also provides the functionality of jumping between phases, but there can be other ways too.

What if some how I kill all the raised objection or kill run_phase whenever I see timeout occurring. But for that, I can’t find any command to kill all the raised objection in a single shot.

Let’s have a dip into UVM source code for uvm_objection class.

class uvm_objection extends uvm_report_object;
//
protected int m_source_count[uvm_object];
protected int m_total_count [uvm_object];
virtual function void raise_objection (uvm_object obj=null, string description=””, int count=1);
if(obj == null)
obj = m_top;
m_cleared = 0;
m_raise (obj, obj, description, count);
endfunction

// When objection is raised, m_raise internal method
function void m_raise (uvm_object obj,
uvm_object source_obj, string description=””, int count=1);
if (m_total_count.exists(obj))                   // for total hierarchical count
m_total_count[obj] += count;                  // if raised previously, increment
else
m_total_count[obj] = count;                    // if not raised previously, assign count
if (source_obj==obj) begin                          // will go here when called from raise_objection method
if (m_source_count.exists(obj))            // if current obj has raised an objection previously
m_source_count[obj] += count;          // increment count
else
m_source_count[obj] = count;
end
//
endfunction

As we can see, objection is nothing but an associative array with counter. In order to drop objections, we require to make count value of all entries of m_source_count to zero. This can be done by dropping objections.

virtual function void drop_objection (uvm_object obj=null,
string description=””,
int count=1);
if(obj == null)
obj = m_top;
m_drop (obj, obj, description, count, 0);
endfunction
// When objection is dropped, m_drop internal method
function void m_drop (uvm_object obj,
uvm_object source_obj,
string description=””,
int count=1,
int in_top_thread=0);
//
if (obj == source_obj) begin
//
m_source_count[obj] -= count;        // decrements count
//
m_total_count[obj] -= count;           // total hier count decrements
endfunction

Now, in order to drop objections, we need to have handle of every component. The handles are indices/keys of associative array m_source_count.

As always, UVM provides a good solution to this scenario (dropping all objections). There is a method known as get_objectors in the same class. This method gives handles to all the objects/components which are actively participating in objection mechanism. Following is get_objectors function and its explanation in class reference:

get_objectors

function void get_objectors( ref uvm_object list[$] )
Returns the current list of objecting objects (objects that raised an objection but have not dropped it).

function void get_objectors(ref uvm_object list[$]);
list.delete();
foreach (m_source_count[obj]) list.push_back(obj);
endfunction

The function pushes handle of each objecting entity into queue and the queue is referenced. This seems to tackle my scenario.

Just get the objection handle for current phase. Then get handle of every objector (using get_objectors) and call drop_objection for each one of them.

// In some other component
task run_phase(uvm_phase phase);
interrupt_timer();                                            // interrupt timer based on clock pulse count
kill_objections(phase);
endtask

task kill_objections(uvm_phase phase);
uvm_objection objection;                             // for getting class handle
uvm_object object_list[$];

// Fetching the objection from current phase
objection = phase.get_objection();           // current phase uvm_objection handle

// Collecting all the objects which doesn’t drop the objection
objection.get_objectors(object_list);

// Dropping the objection forcefully
foreach(object_list[i]) begin
`uvm_info(get_type_name(),$sformatf(“Dropping objection for object : %0s”,object_list[i].get_name()),UVM_LOW);
// Drop objections till count value is 0.
// Useful in case of multiple objections raised by a single object.
while(objection.get_objection_count(object_list[i]) != 0) begin
objection.drop_objection(object_list[i]);
    end
  end
endtask

Now, each time the timer expires, all the objections are dropped explicitly. And the simulation gracefully proceeds to next phase. This technique of dropping all the objections can be useful in many other scenarios also.

I just took reference from uvm_objection.svh Source Code file for this post. Moreover, there is a full example code available at drop_all_objections (Just copy-paste the code in your sv file and run the code).

– Sharvil

profile for sharvil111 at Stack Overflow, Q&A for professional and enthusiast programmers

4 responses

  1. What if objections are not raised from sequence ?
    In general is it a good idea to raise/drop objection from sequence ?

    Why cant we just raise/drop objection from test itself.

    Like

    1. Yes, correct. There is no reason to raise/drop objections in sequence, if your test does it for you and the sequence blocks until it is done. The scenario depicted here is for unblocking/interrupting an on-going sequence and moving to next simulation phase. The scenario depicts that when a particular framework hits (interrupt timer in this case), we just want to stop the current interface traffic and move to check packet integrity (check_phase).

      Liked by 1 person

  2. Good day! I simply want to give you a big thumbs up for the excellent information you’ve got here on this post. I will be coming back to your blog for more soon.

    Like

  3. Hi,
    I have a question to ask to you regarding UVM.
    How should i reach u by email?

    Thanks,
    Ashish

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: