-
Notifications
You must be signed in to change notification settings - Fork 250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Regression Bug in AXI-Stream slave when upgrading from v4.0.8 #573
Comments
FTR, other changes to AXI-Stream a few days before #429, introduced another partial regression as explained in #494. Does GitHub allow to easily compare v4.0.8 and v4.2.0 of subdir https://github.com/VUnit/vunit/tree/master/vunit/vhdl/verification_components/src only? |
We've hit something similar some time ago. That was different, probably before the merge you mentioned. But the process structure in the slave was changed. |
I created a synthetic example in https://github.com/eine/vunit/tree/axis/synthetic/examples/vhdl/array_axis_vcs/src/test, in an attempt to better understand this issue. According to previous comments here and in #673, the blocking behaviour is produced by In #673, @FranzForstmayr proposed using a queue (https://github.com/VUnit/vunit/pull/673/files#diff-f2d4d6a3240eda80ddc8a14823d070f532d73aa493d7680a449d846445014477R113-R121), which implies using On the one hand, I am concerned about the apparent inconsistency between On the other hand, constant master_axi_stream : axi_stream_master_t := new_axi_stream_master (data_length => data_width, actor => new_actor(inbox_size => 64, outbox_size => 64));
constant slave_axi_stream : axi_stream_slave_t := new_axi_stream_slave (data_length => data_width, actor => new_actor(inbox_size => 64, outbox_size => 64)); Therefore, using an external queue for using /cc @LarsAsplund |
I'm not sure I fully understand the issue. The changes (if I remember correctly) at that time were made to align to the clock input of the VC. Before the changes it could occur that the VC became asynchronous when using a wait for time message i think. The queue being outside of the vc, was already the case I think in the original version. |
The issue is the different behaviour of
My understanding is that the two
But the three So, the question is whether the different behaviour of |
Ok I get it.. |
Sorry for mixing in again here, but this looks really interesting. I am pretty sure that we did not have this behaviour here. |
I'm using Modelsim PE 10.7b.
note that the check on time will fail, since the blocking pop will consume time.. |
Can you please try the array_axis_vcs example? The following waveform was generated with GHDL ( Note: that waveform also shows 5% stalls for both the master and the slave. The modification in https://github.com/VUnit/vunit/pull/673/files#diff-f2d4d6a3240eda80ddc8a14823d070f532d73aa493d7680a449d846445014477 shows that the UUT can handle back-to-back transfers. However, the current example using a single for loop does introduce dead cycles.
Maybe this is a different behaviour between ModelSim and GHDL? So, where ModelSim is showing a glitch, GHDL shows a cycle? Or is it because of https://github.com/VUnit/vunit/blob/master/examples/vhdl/array_axis_vcs/src/test/tb_axis_loop.vhd#L122 ? |
I tried to run the same test as @olafvandenberg in questasim 2019.2_2. The result is obviously 50%-DC: This starts to be scary... |
... on the other hand: If the result is 100% or 50% DC depends on the loop exit in axi_stream_slave. It exits if the queue is empty - and then it waits for the next clock edge, causing 50% DC. |
I pulled the branch axis/synthetic from eine's fork, and ran the array_vcs example tb_axis_loop. I wonder if it might have something to do with delta cycles. update: @eschmidscs I didn't see your latest reply, but indeed I think you are correct. |
FTR, as commented in ghdl/ghdl#752, it seems that this clock alignment issue might have further effects than the glitch or additional cycle. The workaround in #494 (comment) should provide control over the sizes of the buffers, but it seems not to work. Unfortunately, I did not get to understand what's going on... |
I have also run into this issue. I am seeing different behavior even between simulators from the same vendor (Mentor). Using several different versions of Modelsim (e.g. Modelsim AE 2020.1), I see the 100% duty cycle behavior (ignoring a single idle cycle near the start, which is not a problem in my case): Using Questa FE 2021.2, I see the 50% duty cycle behavior (which is a problem in my case): This is causing quite a headache. Has anyone found a workaround? I tried inserting large numbers of delta cycles here and there, but I wasn't able to change the behavior. |
The workaround: In a first loop, you pop as many references as you expect transactions with the corresponding pop_axi_stream procedure and store them to a queue. This does not require simulation time. |
@eschmidscs that approach will solve the 50% duty cycle behavior by providing 100% instead. But I am more concerned with the fact that different simulators have different behavior (modelsim vs ghdl/questa). If we clearly state that for 100% throttle, one should use the unblocking This way the behavior of the blocking |
@tasgomes There seem to be two different questions. I tried to answer the question about the workaround @hcommin was asking for. If you look at #477, the blocking nature is assumed to be the standard case. From that point of view, I agree with your statement that TREADY should always go low after one transaction. Personally, I would prefer to have a pop function that does not always cause a stall. But this does not work with the current VC architecture. |
@eschmidscs Thanks for the reply. I think we are in sync. Ideally the pop function should allow 100% throttle, but if that is not possible, I would then force TREADY low for a complete clock cycle in the axi stream component just to make it consistent across simulators. |
I would like to find a proper fix for this issue. edit: would like to hear your view(s) on this.. |
@olafvandenberg without doing any proper code study: what happens if you add a "wait for 0ps;" before pulling TREADY low, but then check again for pop transactions before stalling? |
@eschmidscs I think that would give consistent 50% behavior, so always >= 1 low cycle. (as mentioned in one of my earlier posts) |
@olafvandenberg That is what I intended: A forced delta cycle by the wait, but then another check of the queue. Did your test above with the wait already check the queue after the test? |
@eschmidscs I believe so, as the forced delta would be inside the while loop on 'not is_empty(message_queue)'. If there would be prior knowledge that a new pop message will come, we can wait for that instead of waiting on a clk'event and a non-empty queue. |
The problem with prior knowledge is always that it is not readily available. The workaround of poping references and then waiting for them is kind of generating exactly this prior knowledge: You tell the vc how many transactions to expect. |
@olafvandenberg Just for the record: My idea with "wait for 0ps" cannot work because the same statement is probably used in the message passing (didn't check). So it won't help to push out the decision until "all" message passing has been done... |
@eschmidscs yeah, I checked and I'm able to fix the issue by adding two consecutive 'wait for 0 ps;' statements right after the reply() call. |
I pushed a possible fix to a branch on my fork. |
Interesting thought... But is that different from "wait for 0 ps"? I think both will just add some delta cycles - and if the message passing requires more, it will be later and the stall will happen. |
@olafvandenberg I am hoping to find time to look into this properly today. If I understand correctly, my rough expectations should be:
I suspect my current use case falls into the awkward gap (I need 100% duty cycle and it is very difficult to calculate in advance how many data beats will be received)... but I'll look into it. |
The possible fix should give 100% no matter the usage. (perhaps somebody with more experience in the way simulators schedule can say if the fix will always work though) |
I found some time to test the fix proposed by @olafvandenberg. I have a for beat in 0 to 19 loop
push_axi_stream(net, AxiStreamMaster_c, m_tdata_v, m_tlast_v, m_tkeep_v,
m_tstrb_v, m_tid_v, m_tdest_v, m_tuser_v);
end loop;
for beat in 0 to 19 loop
pop_axi_stream(net, AxiStreamSlave_c, s_tdata_v, s_tlast_v, s_tkeep_v,
s_tstrb_v, s_tid_v, s_tdest_v, s_tuser_v);
end loop; Before the fixModelsim: 100% duty-cycle but there are glitches. Questa: 50% duty-cycle with no glitches. After the fixModelsim: 100% duty-cycle with no glitches. Questa: 100% duty-cycle with no glitches. I think the fix works fine. We get 100% duty-cycle, no glitches at all and the same behavior across different simulators. |
kul! |
@tasgomes, could you please confirm with GHDL as well? As reported above, there have been inconsistency issues between GHDL and ModelSim. |
ouch! I don't have gtkwave installed to quickly look at the waveforms. Anyway, I generated the VCD file with GHDL, converted the VCD file to WLV file and then I opened the waveform with modelsim. Unfortunately, seems like with GHDL we still have 50% duty-cycle. After the fix |
Hi,
I triggered a regression bug when upgrading VUnit to v4.2.0 from v4.0.8.
With git bisect I found the offinding commit 3e098f5, merged in #429 .
When using the axi-stream slave, the ready signal starts toggling.
![image](https://user-images.githubusercontent.com/9936788/67392591-1c02dc00-f5a1-11e9-97a2-e3dd542be956.png)
Same issue is in the axi_stream_slave, although the tests are passing, just need approximately twice as long. The offending line is https://github.com/VUnit/vunit/blob/master/vunit/vhdl/verification_components/src/axi_stream_slave.vhd#L95, however I haven't digged deep enough to find out why this change was made.
The text was updated successfully, but these errors were encountered: