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.
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
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 wholeheartedly agree with your post, however I feel obliged to point out a logical error
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.
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.
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.