UVM Phase Jumping

All,
I want to have a basic idea of UVM phase jumping and its basic functionailty.
Which functions/tasks(Eg.:jump/jump_all/get_domain) should I try and how?

Also,
Can anyone explain clear and easy difference between uvm_phase, uvm_schedule and uvm_domain?? And relation between them…

Thanx in advance…

Regards,.
Anamika

Phase jumping in UVM is not recommended. There are issues with respect to shutting down executing processes when you jump between phases and the VIP-TSC (a.k.a. “The UVM Committee”) is seriously considering major changes to this functionality.
Perhaps it would be better for you to explain what you’d like to do and then we can explore a way of doing it without phase jumping. A mix of virtual sequences, barriers and events is most likely sufficient for your needs.

In reply to tfitz:

Hi tfitz,
I want to know if I want to add user defined phase and then jump to that phase in run phase of testcase. How can I do that??

What is the way to add user defined phase??/

Hi Anamika,
Using user-defined phases is even less recommended than using the predefined phases. If you explain what you’re trying to do exactly, we can probably come up with an alternative approach.

In reply to tfitz:

Hi.
I have to try maximum experiments on phase jumping and its effects.
So, just want to kow what are the things I should try.

Also, can u explain difference between uvm_domain, uvm_schedule ??

Thanx,
Anamika

In reply to Anamika Sharma:

Since you shouldn’t use them, it would be a waste of your time to run experiments on user-defined phases and/or phase jumping.

However, to answer your question:
There is no such type as uvm_schedule. A “schedule” is typically of type uvm_phase and defines the before/with/after relationship of a set of uvm_phase objects. If you wanted to add your own user-defined phases, you’d have to create a schedule and add the phases to it.

The uvm_domain type is an extension of uvm_phase that defines the set of phases/schedules that get assigned to any particular uvm_component.

That said, I had to look it up and, even having been involved in the design of domains and schedules, I’m not sure that explanation is going to help you. Please just don’t use them.

In reply to tfitz:

Hi tfitz,
Thanx for the explanation.

One thing i want is that I have 2 agents in my testcase. Now all phase of both agents start synchronously. Like if I am having some delay in main_phase of driver_1, and no delay in main_phase of driver_2, still main_phase of driver_2 waits for completion of main_phase of driver_1 and then both go to their pre_shutdown_phase.

Now, first i want to implement like main_phase of driver_2 should not wait for completion of main_phase of driver_1.

Then , when I add domain synchronisation, then only main_phase of driver_2 should wait for completion of main_phase of driver_1.

I want to implement domain synchronisation myself.

In reply to Anamika Sharma:

We don’t recommend using main_phase at all, but especially not for drivers. The reason is that your driver should be written to use run_phase so that it can always respond (even with just an idle cycle) to traffic on the interface to which is is connected. Similarly for monitors.
The additional run-time phases were best suited to controlling stimulus, and it’s really just easier to use virtual sequences. Rather than delaying the operation of driver1, what you really want to do is delay the start of sequence1, which sends transactions to driver1.

Now, first i want to implement like main_phase of driver_2 should not wait for completion of main_phase of driver_1.

You need to ask yourself what you need to do in pre_shutdown_phase. Remember, eventually you’ll need both agents to complete main and shutdown so you can exit run_phase and move to extract_phase. Try something like this in your virtual sequence:

fork
  begin
    main_seq2.start(sequencer2); // sequencer2 is a pointer to env.agent2.sequencer
    shutdown_seq2.start(sequencer2);
  end
  begin
    main_seq1.start(sequencer1);
    shutdown_seq1.start(sequencer1);
  end
join

Notice how each branch of the fork/join allows two sets of stimulus to execute in parallel. In each branch, the main_seq will complete followed by the shutdown_seq, independent of the other branch. Once both branches have completed, you can drop the objection and proceed to extract_phase.

Then , when I add domain synchronisation, then only main_phase of driver_2 should wait for completion of main_phase of driver_1.

fork
  begin
    sync_event.wait_trigger();
    main_seq2.start(sequencer2); // sequencer2 is a pointer to env.agent2.sequencer
    shutdown_seq2.start(sequencer2);
  end
  begin
    main_seq1.start(sequencer1);
    sync_event.trigger();
    shutdown_seq1.start(sequencer1);
  end
join

Using a combination of fork/join, begin/end, events and objections, you should be able to get whatever synchronization you require.

In reply to tfitz:

Hi,
Actually I have not run any sequence . Just waitung for 2 edges of clock in run_phase of driver_1 and only displaying a message in run_phase of driver_2. So, run_phase of driver_2 should complete first since it is not waiting for any event. like :

run_phase of driver_1 start
//

run_phase of driver_2 start
//

run_phase of driver_2 ends
//

shutdown_phase of driver_2 start
//
shutdown_phase of driver_2 ends
//

run_phase of driver_1 ends
//

shutdown_phase of driver_1 starts
//

shutdown_phase of driver_1 ends
//

Like this i want. Driver_2 should enter into its shutdown_phase even before completion of run_phase of driver_1… can it be done???

In reply to Anamika Sharma:

First of all, even if you were to use main_phase and shutdown_phase, the recommendation would still be only to implement run_phase in your drivers. The reset/config/main/shutdown phases are only intended to be used for stimulus control, if at all.
I’m guessing that in your last post, you meant “main_phase” where you wrote “run_phase” since I’m sure you know that main_phase()-shutdown_phase() run in parallel with run_phase(). Therefore shutdown_phase() cannot execute after run_phase().
Assuming that’s the case, using run_phase, your drivers would look something like this:

task driver2::run_phase(uvm_phase phase);
  `uvm_info("Driver2","display message",UVM_INFO)
  shutdown_driver2();
endtask

task driver1::run_phase(uvm_phase phase);
  repeat(2) @posedge(vif.clk);
  shutdown_driver1();
endtask

The real question you need to answer for yourself is what behavior you need to “shutdown” each driver. In reality, even if you were to use main_phase and shutdown_phase, as I said earlier, your driver would still just implement run_phase, so your drivers would really just be in a get_next_item()/item_done loop interacting with the sequences. “Shutdown” is usually just to allow the bus traffic to “drain” - allowing the drivers to complete the last transactions to get the bus back to a quiescent state. Since building any kind of communication between the drivers would lessen their reusability, you’re better off controlling them via sequences. The transactions you send could include tags like “do_bus_transaction” or “do_shutdown”.

In reply to tfitz:

In class my_driver, I have following objects and function:

uvm_domain driver_domain = uvm_domain::get_uvm_domain(); // to be set to my_driver class
uvm_domain get_driver_domain; // handle to get the assigned domain
string driver_domain_name; // string to display domain assigned
uvm_domain driver_domains[string]; // to display all available domains of my_driver

function void my_driver:: build_phase( uvm_phase phase );
super.build_phase( phase );
uvm_report_info(get_full_name()," my_driver:: build_phase()",UVM_NONE);
define_domain(driver_domain);
this.set_domain(driver_domain,1);
driver_domain_name = phase.get_domain_name();

uvm_domain:: get_domains(driver_domains);
$display(" number of available domains is %d",driver_domains.size());
$display(“driver is in domain: %s” ,driver_domain_name);
endfunction : build_phase

What I am trying to do is set a domain (other than uvm_domain and uvm_common_domain) to build_phase of my_driver. So available domains for this phase should be 3. And this phase should be in driver_domain.

But it is displaying as if available domains for this are 2. And this phase is in common domain.

I am trying to set different domains to different components(my_diver and my_monitor). Now i am having one agent only.

In reply to Anamika Sharma:

With all due respect, I’ve just shown you how to make the two agents/drivers do different things at different times without requiring domains. I’m not sure why you’re so hung up on using domains.

In reply to tfitz:

Hi,
Actually I have to implement phase jumping. Thats why hung up in it only.

I have written following to set_domain .

class my_driver extends uvm_driver;

uvm_domain driver_domain;
uvm_domain get_driver_domain;
string driver_domain_name; // string to display domain assigned
uvm_domain driver_domains[string]; // to display all available domains of my_driver



endclass : my_driver

function void my_driver:: build_phase( uvm_phase phase );
super.build_phase( phase );
ap = new(“ap”, this);
uvm_report_info(get_full_name()," my_driver:: build_phase()",UVM_NONE);
driver_domain = new(“uvm_domain_driver”);
//define_domain(driver_domain);
this.set_domain(driver_domain,1);
driver_domain_name = phase.get_domain_name();
get_driver_domain = get_domain();
uvm_domain:: get_domains(driver_domains);
$display(“driver is in domain: %s” ,driver_domain_name);

endfunction : build_phase

class my_monitor extends uvm_monitor;

uvm_domain monitor_domain;
uvm_domain get_monitor_domain;
string monitor_domain_name; // string to display domain assigned
uvm_domain monitor_domains[string]; // to display all available domains of my_monitor



endclass : my_monitor

function void my_monitor:: build_phase( uvm_phase phase );
super.build_phase( phase );
ap = new(“ap”, this);
uvm_report_info(get_full_name()," my_monitor:: build_phase()",UVM_NONE);
monitor_domain = new(“uvm_domain_monitor”);
//define_domain(monitor_domain);
this.set_domain(monitor_domain,1);
monitor_domain_name = phase.get_domain_name();
get_monitor_domain = get_domain();
uvm_domain:: get_domains(monitor_domains);
$display(“monitor is in domain: %s” ,monitor_domain_name);

endfunction : build_phase

When I am creating a new object of uvm_domain as driver_domain then, then number of domains available to phase are increased by 1.But, set_domain command is not setting the domain to the assigned domain_type.
After using get_domain_name , I am getting the default domain value for that phase.

As per my understanding, set_domain() itself calls define_domain().

Do, I need to edit define_domain() ??

Also I am trying to unsynchronise both these domains using :

monitor_domain.unsync(.target(monitor_domains[driver_domain]));

Is it correct???
Where and how should I write this line to unsynchronise.

Hi,

I have written following line for synchronising uvm_pre_shutdown_phase of user defined domain domain0 and domain1:

domain0.sync(.target(domain1.get_domain())
.phase(uvm_pre_shutdown_phase::get()));

But I am getting the following error :

add_user_defined_domain.sv
.phase(uvm_pre_shutdown_phase::get()));
|
ncvlog: *E,EXPRPA (add_user_defined_domain.sv,336|15): expecting a right parenthesis (‘)’) [10.2.2(IEEE)].
.phase(uvm_pre_shutdown_phase::get()));
|
ncvlog: *E,EXPSMC (add_user_defined_domain.sv,336|52): expecting a semicolon (‘;’) [10.2.2][10.2(IEEE)].

Can anybody help?

In reply to tfitz:

Hello tfitz,

I am new to UVM and experimenting with various concepts.

After almost 3 years of this post’s inception, I would like to know if this thread and your answers are still valid!?

Is there any consensus on using/not-using the new run-time uvm phases and phase jumping? If still not usable/recommendable, why aren’t they deprecated yet?

Any reference to the latest article on this topic would be helpful too.

Sincerely looking forward to hearing from you.

Thanks,
harsh2020

In reply to harsh2020:

Hi Harsh,
I see lot of customer actively using these “active” phases (for active components within a UVC). I personally believe this is of great value to end users. I know my friends at Mentor differ - with some great counter-arguments, but that’s the beauty of having great people around - they offer opinions and let you - the real users choose! Also recall that for decades we have been using similar “active/run-time phases” with eRM, VMM etc. So it is not a crazy concept - rather proven to work for many chip designs for many years!

Our code generator for UVM (DVC_UVM) generates these phases with right (optimal) objections instantly. So I believe the concerns of potential mis-use are diminishing I hope.

See my DVCon US tutorial to see some of the jumping case studies.

Regards
Srini
www.verifworks.com