In reply to MayurKubavat:
In reply to verif_learner:
I am used to adding interface signals only for testbench which will give state of testbench at any point in time.
Debugging using display statements is again a manual check. If you need debugging in RTL code, appropriate amount of checkers should do. Or else you want to debug testbench status, above method of using interface makes debugging testbench with waveforms easier.
To design self debugging testbench also come up with check points your testbench could break and write checks (e.g. timeout counters for a event, assert(STATE) at appropriate point to see if testbench/rtl reached certain state, etc.)
To debug a code with `uvm_info is something and to write a debug friendly code is something else, I think!
Interface signals can only help you to some extent. The instantaneous state of the interface can be very well checked using these. What happens when that interface carries a packet. Hard to debug traversing cycle by cycle trying to make sense from bytes of data.
Debugging is always a manual step. The only question is the abstraction level at which one wants to debug - signals, transactions, packets, messages. So, I don't understand what you mean by - Debugging using display statements is again a manual check.
The test bench is self checking (I don't know if self debugging test benches exist, yet).
The question here is, what happens when a check fails. How do you go from a known failure to the root cause. You will need a lot of information to keep tracing back to the point of failure.
This is the reason source level debuggers exist in both SW and HW discipline. But those debuggers should not be the first line of analysis, in my view, but should be the last resort.
anyway, these are just my views.