steveicarus / iverilog

Icarus Verilog
https://steveicarus.github.io/iverilog/
GNU General Public License v2.0
2.87k stars 531 forks source link

vvp 12.0 Aborts With Assertion failure in delay.cc:667 #1184

Open timeye opened 1 week ago

timeye commented 1 week ago

using iverilog v12.0 and Linux RHEL 7

Compiling VVP ... ... VVP file version 12.0 (stable) Compile cleanup... ... 9733 functors (net_fun pool=786432 bytes) 3442 logic 89 bufif 4 resolv 2133 signals ... 7026 filters (net_fil pool=1048576 bytes) ... 183719 opcodes (4423680 bytes) ... 7403 nets ... 9764 vvp_nets (1048544 bytes) ... 0 arrays (0 words) ... 17 memories 12 logic (111000 words) 5 real (90 words) ... 1096 scopes ... 0.355774 seconds, 82188.0/24008.0/2716.0 KBytes size/rss/shared Running ... ...execute EndOfCompile callbacks ...propagate initialization events

vvp12: delay.cc:667: virtual void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t, const vvp_vector4_t&, vvp_context_t): Assertion `tmp == use_delay' failed. Abort (core dumped)

martinwhitaker commented 1 week ago

Please provide a small code example that allows us to reproduce this failure.

timeye commented 1 week ago

Hello @martinwhitaker Would a .vvp file work for you ? This is a chip level simulation w/ lotsa modules... when the abend occurs, there is really no information about what register(s) are getting processed / asserted. Are there any runtime options that would display a little more information about what signal(s) are looked at ? I looked at the iverilog source code in the file delay.cc (line 667)... that small proc has some interesting comments about needing a fix... thx

timeye commented 1 week ago

Is appears as if you have a multi-bit register and the Rise time is different from the Fall time, the assert will trigger...

Refer to the file vpp\delay.cc, starting at line 652:

    /* Given the scheduled output time, create an output event. */
      vvp_time64_t use_delay = delay_from_edge(cur_vec4_.value(0),
                           bit.value(0),
                           out_at);

    /* FIXME: This bases the edge delay on only the least
       bit. This is WRONG! I need to find all the possible delays,
       and schedule an event for each partial change. Hard! */
      for (unsigned idx = 1 ;  idx < bit.size() ;  idx += 1) {
        vvp_time64_t tmp = delay_from_edge(cur_vec4_.value(idx),
                           bit.value(idx),
                           out_at);
          /* If the current and new bit values match then no delay
           * is needed for this bit. */
        if (cur_vec4_.value(idx) == bit.value(idx)) continue;
        assert(tmp == use_delay);
      }

      cur_vec4_ = bit;
      schedule_generic(this, use_delay, false);