The one thing that verification engineers spend most of their time on is debug. The most traditional way of debugging any problem is by sifting through logfiles to understand exactly what went wrong in a simulation. A lot of things can cause the testbench to break and the test to fail, and the logfiles can only help if you put intelligent display messages in them.
What I like about the register layer in UVM is that it provides a very convenient interface to program registers in a design with minimal trouble. I said minimal because I feel that it is still under the process of evolvement to provide the user with a complete set of API, and hence might require a little work-around here and there - or well, it could be that I haven't found the right solution yet. So, I am going to describe an out of the way approach I used recently to randomize registers to my whims and selectively write certain registers.
UVM factory mechanism makes the testbench more flexible and re-usable by allowing components to be overriden via the
type_id::create() method. The idea is that at run-time, an object of the overridden data-type will be returned instead of the original. However, it might give a compilation error when a member of the new sub-class component is being accessed in the new environment unless properly casted. This post will describe the scenario and how to overcome the error by casting.
UVM sequence macros are a great way of reducing code and hiding away some details.
`uvm_do macros enable a sequence item to be created, randomized and executed on a sequencer all from a single line of code.
`uvm_create is another macro which simply creates an object of a sequence item so that it can be handled later on. Let's see what the name of an object created by
`uvm_create would look like. Unlike a typical
type_id::create() method where you get to specify a required name,
`uvm_create does not have any, not that it matters, but just for trivia.