Ridiculously short phase timeout

Since updating to OVM-1.1 I have been getting problems with unexpected timeout messages:

OVM_ERROR @ 1099511627.8 ps [TIMOUT] Watchdog timeout of ‘1099511627.8 ps’ expired.

This seems to be the default timeout and at just over 1ms it is rather short :)
However I have not been able to override it - my previously OK timeout settings don’t seem to be heeded. I’ve tried the following in the run task of my test:

set_global_timeout(0);                               //   attempt to disable the timer
      set_global_timeout(50000us);                    //   desired timeout value
      set_global_timeout(64'hFFFFFFFFFFFF);  //   ie default*256 (approx)

but none of them prevents the timeout. Has something changed in the way timeouts should be applied for OVM-1.1?

Neil

Do you have any threaded run() tasks that block, or otherwise never return? If so, then what I suspect is happening is that when you get to a point where no more stimulus is being generated, and you have tasks that are blocking, waiting for input, then the simulator advances time to the next scheduled event, which is the timeout event.

I had this situation come up when I switched to 1.1, and I solved it by adding a call to ovm_top.stop_request() at the end of the run() task in my environment.

-Kurt

HI Kurt,

Thanks for the suggestion but I don’t think it’s the problem - there’s plenty more stimulus left as I haven’t reached my coverage goal yet.
I have worked round it by “adjusting” the timeout in the OVM code as I couldn’t find a way to override it, but this isn’t a good way for the future :) The simulation then runs to completion.

So there seems to be a couple of problems:

  • the default timeout appears to be `OVM_DEFAULT_TIMEOUT times the simulator resolution so will change when the resolution changes rather than being a fixed time
  • the set_global_timeout method does not adjust the setting

Neil

Some more experiments have given a little enlightenment and a working system. However there are still some questions.

I was calling the set_global_timeout from the run phase of the test. Obviously (with hindsight :) ) if you want to time out the run phase the timeout must be set before entering that phase. Moving it to the build or start_of_simulation phases works as expected.

During experiments I moved the set_global_timeout to an initial block in the tb module. Settings from here were accepted in time for the test run phase, but the values were wrong. If I set a 5s timeout I got 5us. I don’t know why this happens. The module runs with timeunit 1ns; timeprecision 1ns;

It’s still not clear why the default value for the timeout is so short (1.09ms) - I wonder if this also dividing the expected value by 1,000,000 ?

Neil

From where exactly does the watchdog timeout in ovm_root.svh derive its setup of timeunit ? I added an ovm_report_info block ( in RED below) to the run_global_phase task as follows ( look for “tick at” ). I intended to see a display line every 1000 nSecs since in my testbench, I have a timeunit 1ns; directive. Instead, I get a display line every picosecond ( 1000 femtoseconds ). We’ve seen other issues with scaling on the watchdog timer scaling that are confusing as well, and are very similar to what is describe in earlier entries in this thread, “ridiculously short . . .”. How/Where should we be specifying the timeunit in our environment? We are running ovm_1.1 on Questa 6.4a presently.

task ovm_root::run_global_phase(ovm_phase phase=null);

time timeout;

if (m_curr_phase != null) begin
ovm_report_fatal(“PHSSTR”, “Global phasing has already started.”);
#0; // forces shutdown because $finish is forked
return;
end

// If we weren’t given a specific phase, run through them all.
if (phase == null) begin
phase = m_last_phase;
end

if (!m_phase_q.exists(phase)) begin
ovm_report_fatal(“PHNTFD”, {“Phase %0s not registered.”,phase.get_name()});
return;
end

if (m_curr_phase == phase || phase.is_done()) begin
ovm_report_warning(“PHDONE”, $psprintf(
“Phase ‘%0s’ already executed. Current phase is ‘%0s’.”,
phase.get_name(), m_curr_phase.get_name()));
return;
end

// MAIN LOOP: Executes all phases from the current phase
// through the phase given in the argument.
while (m_curr_phase != phase) begin

if (m_curr_phase == null)
  m_curr_phase = m_first_phase;
else
  m_curr_phase = m_phase_q[m_curr_phase];

// Trigger phase's in_progress event.
// The #0 allows any waiting processes to resume before we continue.
m_curr_phase.m_set_in_progress();
#0;

ovm_report_info("STARTPH",
  $psprintf("STARTING PHASE %0s",m_curr_phase.get_name()),10001);

// TASK-based phase
if (m_curr_phase.is_task()) begin

  event wait_forever;

  timeout = (phase_timeout==0) ?  `OVM_DEFAULT_TIMEOUT : phase_timeout;

  `ifdef INCA

    // IUS does not support disabling named fork blocks, so we isolate the
    // inner fork block so we can kill it using disable fork
    fork // guard process
    begin

    fork

      // Start an independent process that kills the phase, else the killing
      // stops prematurely at the component that issued the request.
      begin
        m_stop_process();
      end

      begin // guard process
        fork
          begin
            #0; // ensures stop_process active before potential stop_request
            m_do_phase_all(this,m_curr_phase);
            @wait_forever; // wait for stop or timeout
          end
          begin
            #timeout;
            ovm_report_error("TIMOUT",
                  $psprintf("Watchdog timeout of '%0t' expired.", timeout));
          end
        join_any
        disable fork;
      end // end guard process

    join_any
    disable fork;

    end
    join // end guard process

  `else // QUESTA

    fork : task_based_phase

forever begin
#0; // ensures stop_process active before potential stop_request
#1000
ovm_report_info(“ovm_root”,“tick at 1000 units”,0);
end

m_stop_process();
begin
m_do_phase_all(this,m_curr_phase);
wait fork;
end
#timeout ovm_report_error(“TIMOUT”,
$psprintf(“Watchdog timeout of ‘%0t’ expired.”, timeout));
join_any
disable task_based_phase;

  `endif // INCA-QUESTA

end // if (is_task)

Sample logfile snippet:

OVM_INFO @ 0.00ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.00ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.00ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.00ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.01ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.02ns [ovm_root] tick at 1000 units

OVM_INFO @ 0.03ns [ovm_root] tick at 1000 units

Thanks for any input here.