On SystemVerilog Coding Conventions - Challenging the Status Quo

When I first started out I remember reading all of these nice naming conventions for SystemVerilog. For example, when developing a new verification component, we're supposed to choose a descriptive name for it, preferably as short as possible. To distinguish it from other VCs doing the same thing, we should add a prefix that's unique to our organization to the name we chose. If, for example, we would be developing an AHB VC, a recommended name for it would be vgm_ahb. For the name of the package that contains the code we should add the pkg suffix, hence it should be called vgm_ahb_pkg. Any classes we write for our VC should also contain vgm_ahb in their names. For example, our driver class would be called vgm_ahb_driver, our monitor would be called vgm_ahb_monitor, etc.

This is a companion discussion topic for the original entry at https://verificationgentleman.netlify.app/2015/04/05/on-sv-coding-conventions.html

Everything you said is truth! I have written this all down multiple times for multiple recipients, but never a public blog entry. So much cargo cult programming in the SV world. Thanks for taking care of it for me :slight_smile:

The filenames issue is a sticky one. My solution is to put the package prefix on the filenames, class driver is in the file vgm_ahb_driver.sv (note it’s not really a header file, so no h at the end). People get freaked out when the file doesn’t have the same name as the class defined inside of it. This wouldn’t be a problem if we could cleanly make the driver/monitor/scoreboard classes part of a package without doing a `include inside the package definition. To me that’s the real problem: relying on the preprocessor to populate our packages. Incidentally, that would solve the unnecessary include guard problem too.

I would have also preferred it if we could have defined what package a class/file belongs to by putting the package name in there as the first uncommented line (kind of like how namespace works in C++). On the other hand, packages are also meant for design code, so that’s why the language designer probably chose to make a package an own entity (instead of a cross cutting concern). This is another example of “the worst of both worlds” we get when we try to do too much in one single language.

I shared a video blog once on this very topic: Namespaces, Build Order, and Chickens | Synopsys - YouTube.
Came to roughly the same conclusions.

I wholeheartedly agree with your post, however I feel obliged to point out a logical error :wink:

You say “the jury’s still out on whether wildcard imports are good or bad” but then go on to outline a much tidier naming convention that requires non-wildcard imports. I think you have demonstrated precisely why wildcard imports are bad and thus settled the argument.

I’d even go one step further and claim that the standard advice to wildcard import everything is precisely what has led to the industry failing to use namespaces appropriately and thus duplicating names at every level of the hierarchy.

A namespace polluting wildcard import is considered bad in pretty much every software language[1][2] and I’'ve never understood why it’s acceptable in SystemVerilog. The only explanation I can find is that SV projects are simply smaller and less complex than large software projects that require disciplined namespace separation, therefore as an industry we’re slower to adopt best-practices that truly scale.

[1] http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
[2] http://stackoverflow.com/questions/2386714/why-is-import-bad

I must admit I am biased toward not using wildcard imports. As you pointed out, this is the main reason why we got into this whole prefixing mess., Structuring code like this won’t prevent anyone from using it, though, as it could still be the case that nothing collides.

After seeing Brians early video i am also convinced of the merits of a strong coding style, perhaps its my VHDL hardened back ground but it definitely helps to have most of my UVCs constructed inexactly the same way.

Although recently, I have came across a few UVM warnings from my simulator on this approach. I assume this is to do with the macros you mention above, can you confirm? E.g.

UVM_WARNING @ 0: reporter [TPRGED] Type name ‘agent_c’ already registered with factory. No string-based lookup support for multiple types with the same type name.

I am a little stumped on a way to resolve UVM’s grumbles.

The warning you get means that you can’t use ‘factory.set_type_override_by_name(“original_type_name”, “override_type_name”)’. I would anyway recommend you not use that at all as it isn’t compile time safe. Better would be to use ‘factory.set_type_override_by_type(original_type::get_type(), override_type::get_type())’ or as I like to do it lately ‘original_type::type_id::set_type_override(override_type::get_type())’. This is compile time safe as it makes sure that the types really exist and are registered with the factory using the macros (i.e. the ‘type_id’ member exists).

You can’t disable the warning, though, aside from maybe using a report handler.

Oddly i don’t use that call anywhere i know if in my test. Its thrown out by Questasim way before the show starts happening.

The only other strange effect i noticed happening was with my sequencers, somewhere along the way their types get confused: E.g.
In my tb i create sequencer handles so that the tests don’t need to dive down into UVC’s.

OCP_pkg::sequencer_c OCP_DMA_Patch_seqr;
SPI_pkg::GI_sequencer_c SPI_seqr ;

I needed to rename the type of sequencer_c for the SPI_pkg. Why? Well the simulator got confused and later on when i assigned the handle it thought that the SPI_seqr was of type OCP_pkg::sequencer_c.
Not sure why, i suspect its a simulator fault, but i wanted to check in the context of this thread that there wasn’t an implementation oversight.
Apologies for turning this into a debug session!

You don’t need to call ‘set_type_override_by_name(…)’ for the warning to appear. The factory will print it once you register a second type with the same name. I think registration happens when you try to create an object of that class (using ::type_id::create).

For the second issue, it does indeed sound like a simulator problem.

How did you handle the annoying TPRGED warning that comes whenever you have classes with the same name in different packages registered with the factory? I tried disabling it, but any code I try to add gets executed after the warnings get printed.

Found a way in the meantime. To get rid of the TPRGED warning, I qualify the type with the package:


This makes the prints nicer, because now I know exactly what type I have instantiated.

To get rid of the warnings, use “package::class” as the utils macro argument. Full article on the topic here:

Yep, you can see that in Brian’s video at 2:51.