As an (unfortunately very) old hand at design and functional verification in VHDL, PSL, UVM/e, C ..... (yawn), and now a few months into SV UVM, I would appreciate people's opinions on coding guidelines. I've read and considered a lot of "macros are/aren't evil" arguments, naming convention "rulebooks" etc, and I'm not concerned with who's right or wrong (too long-toothed to believe there is one). I would, however, like to suck the brains of those of you with more experience and do my best to achieve the following, without endlessly revisiting code to do fiddly edits:
- fewest tool-compatibility issues down the line
- maximum ease of use for other people using/inheriting my code
To kick off, what's the thinking on:
- Implementing the standard do_compare, do_print etc. tasks as provided by the uvm_field_* macros.
- Not really interested in the macro/self-coded question, more about which UVCs should implement them and which not. Looking at various examples, sequence item UVCs generally seem to have them (makes sense since they're obvious candidates for copying and printing) but agents/drivers/monitors often don't. Is this just the usual coder-laziness syndrome (I include myself here) or is there actually good reason for not doing them? If they're not implemented, can it cause problems later?
- Use of m_ prefixes and _h suffixes.
- Some people use them, some don't. Coding guidelines seem to imply m_ is for local protected variables only, but most code uses it regardless of protectedness. Similarly, _h sometimes gets used for handle variables (e.g. an agent's pointer to it's config DB object) and sometimes not (virtual interface inside a driver). Again, rather than right or wrong, I'm more interested in how people think it affects "legibility" for code-inheritors if these (or others) are missed out or misused?
- Finally, when should interfaces (and other possible cross-UVC connections) be made?
- For example, driver UVCs connecting to the virtual DUT interface. Some code does it inside the connect_phase() of the driver, using the config_db to get the handle, and some does it by assigning to the interface field of the driver from the agent's connect_phase(). Both make sense to me, but I'd be interested to know any solid reasons for one over the other such as added flexibility or run-time issues.
James