Why don’t you set_drain_time(…) again in your write function? And you may need to get uvm_phase from write method. You can refer the following code:
uvm_domain common = uvm_domain::get_common_domain();
/* Get run_phase if you want to set drain_time for run_phase */
uvm_phase phase = common.find(uvm_run_phase::get());
if (phase != null) begin
phase.phase_done.set_drain_time(...);
end
That’s my idea, you can try it and let me know the result.
Sorry, my proposal code will not work. I just checked the drain_time in UVM: Once drain_time is being started, it can’t be restarted. Please look the following implementation code in UVM:
task m_forked_drain (uvm_object obj,
uvm_object source_obj,
string description="",
int count=1,
int in_top_thread=0);
int diff_count;
if (m_drain_time.exists(obj))
`uvm_delay(m_drain_time[obj])
UVM uses `uvm_delay for m_drain_time and we can’t reset the drain_time.
Therefore, the only one solution is “phase ready to end” in my first comment.
One way to reset is to use raise_objection then use Delay and drop_objection as workaround for set new drain_time. But in UVM-12 the uvm_test_done and it’s class type is deprecated, and not recommended to raise/drop objection inside of function. Then what is the best way to handle it in uvm_analsys_imp.write() method?
The drain_time only comes into play after all objections are dropped. Since objections should only be raised and dropped in the test, and the objection in the test should only be dropped after all of the test sequences have been completed, why would you need to dynamically change the drain_time? It may need to be adjusted to allow all of your sequence_items to be processed by the DUT, but the phase_ready_to_end() function can account for this.