User Guide: DSim Language Conformance Options
SystemVerilog is not rigorously defined, and it has evolved over the years. Unfortunately, a good many testbenches, including the reference implementation of UVM itself, will not compile on a strictly conforming SystemVerilog compiler. For this reason DSim provides switches to relax its interpretation of the SV-LRM.
Option | Description |
---|---|
-shared-unit-scope |
Use single compilation-unit scope shared by all compilation units |
-separate-unit-scopes |
Give each compilation unit its own compilation-unit scope |
-all-class-spec |
Create default specializations for all parameterized classes |
-all-pkgs |
Generate code for all packages, even those not referenced |
-allow-int-enum-assign |
Allow assignment from integral expression to enum without a cast |
-allow-string-int-assign |
Allow assignment between strings and integers without a cast |
-implicit-bitstream-assign |
Allow assignment between any bitstream types without a cast |
-int-time-literal |
Treat time literals as integers |
-allow-ext-vif |
Allow implicitly specialized virtual interfaces, with restrictions |
-allow-self-vif |
Allow use of bare interface identifier as self virtual interface reference |
-allow-fwd-pkg |
Allow references to items in packages declared later in the code |
Treatment of Compilation Unit Scope
Each file referenced on the dsim
or dvlcom
command line, together with everything the file transitively includes
is treated as a potential compilation unit. The "compilation unit scope" is a scope that surrounds the compilation unit.
Clause 3.12.1 of the SV-LRM requires that tools support both of the following options:
- A single compilation unit scope that encloses all files in the design. This option is selected with
-shared-unit-scope
and is the default. - A separate scope for each potential compilation unit. This option is selected with
-separate-unit-scopes
.
Treatment of Unreferenced Packages and Classes
By default, DSim will compile the code for a package into the final image only if the package is referenced by the rest of the design in some way - either through use of an identifier using pkg_name::id_name
syntax, or through a package import.
However, it is possible to define a package having a class that has a static initializer that calls some method:
package P; class C; static bit foo = other_pkg::other_class#(C)::do_something(); endclass endpackage
If nothing else references package P
then the package will not be compiled by default. However, some testbenches may expect P
to be compiled, and at run time, the static initializer calls do_something()
which may result in creation of an instance of C
. UVM tests work this way: when you write `uvm_component_utils(test) you are creating a static initializer that registers the class with the UVM factory, from where it can be instantiated if selected on the command line. In order to get this style to work, the -all-pkgs
option is provided, which will force all packages to be compiled.
Along similar lines:
class C#(type T = int); static bit foo = other_pkg::other_class#(C)::do_something(); endclass
By default, DSim will not create a default specialization for a parameterized class. Instead, it will create specializations only for what is actually referenced. Again, any static initializers in parameterized classes that are not instantiated will not get run. The option -all-class-spec
will override this behavior and force the creation of the default specialization.
Cast Permissiveness
The SV-LRM prohibits assignment of an integer to an enum without an explicit cast. Nevertheless, it appears that other tools do permit this, and legacy testbenches or third-party verification IP code may rely on this. The -allow-int-enum-assign
switch will suppress this check, making enums almost useless (you have the enum methods, but no type safety) but allowing broken code to compile.
Similarly, other tools seem to permit arbitrary assignment between integers and SystemVerilog strings without an explicit bitstream cast. We believe this to be extremely dangerous, as code errors will not be caught. More generally, some tools permit any bitstream type to be assigned to any other bitstream type without an explicit cast! The -allow-int-string-assign
will permit cast-free assignments between SystemVerilog strings and integers; -implicit-bitstream-assign
permits any bitstream cast without an explicit cast.
Integral Time Literals
The SV-LRM specifies that a time literal such as 1us
is a realtime
(floating point) value, scaled to the time unit currently in effect for the containing design element. Consequence: time literals cannot be used in constraints, as constraints must involve integral values only (at least for bidirectional solving). At least one tool seems to support real-valued constraints, and therefore allows time literals in constraints.
The -int-time-literal
switch causes time literals to be compiled as integral values, thereby permitting use in constraints. However, the user must ensure that the final scaled value of any such literal does not have a fractional portion, as the fraction will be lost.
Implicitly Specialized Virtual Interfaces
The SV-LRM prohibits any interface having interface ports, or hierarchical references that leave the scope of the interface, from being used as a virtual interface. DSim depends on this restriction to allow optimum code generation.
For best code generation, DSim compiles each specialization of a module or interface separately. For example, foo#(4)
is a completely
separate compiled entity from foo#(8)
. If the parameter is used to select the width of a data object then separate compilation permits
optimal code for each to be generated. This is straightforward, as the parameterization is explicit.
However, there are other conditions that cause specialized compilation. We refer to these as "implicit specialization" because no explicit parameters are involved.
Interface ports
interface foo(interface ii); initial $display(ii.x); endinterface module top; other_if oo(); other_if2 oo2(); foo u1(oo), u2(oo2);
This example shows an interface foo
having a generic interface port. There are two instantiations of foo
: one using
other_if
and the other using other_if2
. Clearly, if other_if
and other_if2
are two different interfaces, one cannot
efficiently use the same code for both instances of foo
.
External Hierarchical References
interface foo; initial $display(upward.x); endinterface
Another cause of implicit specialization: upward hierarchical references. Clearly, if there were two instances of foo
somewhere in the hierarchy, then upward.x
may refer to two completely different objects. Again, it is not reasonable
to have one body of compiled code for both cases.
Virtual Interfaces
In SystemVerilog, a virtual interface handle is a variable that can point to any compatible instance of the interface.
Variables and nets may be accessed. Tasks and functions may be called. However, an underlying assumption is that all instances of the interface that the handle can possibly point to are equivalent, compiled in exactly the same way. This is not true for implicitly specialized interfaces, justifying the SV-LRM restriction.
However, it turns out that other simulators do seem to allow this. The -allow-ext-vif
switch can be used to
recover some compatibility in this case. When DSim detects implicitly-specialized interfaces being used as a
virtual interface, it will generate alternate (but less efficient) code for task/function calls to allow these
calls to work. Direct access to any other object is still prohibited.
Virtual Interface Self-Reference
Some tools allow the use of a virtual interface identifier as a self-reference:
class registry#(type T = int); virtual void set(T item); ... endclass interface foo; initial registry#(virtual foo)::set(foo); // Register myself ... endinterface
This treatment breaks standard Verilog syntax in the case where an implicit wire would have the same name as its containing interface:
interface suba(wire clk); endinterface interface subb(wire clk); endinterface interface clk; suba u1(clk); subb u2(clk); endinterface
A classic SystemVerilog compiler would need to bind the references to clk
to an implicit wire.
Treating these references as interface self-references would break this function.
DSim supports interface self-references if -allow-self-vif
is given. This achieves compatibility with
vendor extensions for testbenches that require it, but breaks implicit wires. The default is to preserve
compatibility with implicit wires.
Seed Argument
The SV-LRM requires that the seed
argument to $random()
be an integer variable. DSim permits the passing of a constant.
However, behavior may differ compared to other simulators.
Static / Automatic Class Methods
The SV-LRM requires that all class methods have automatic lifetime. However, some user code appears to rely on support for static methods.
One point of clarification: the keyword static
is overloaded: it can be used to indicate a storage lifetime,
and it can also be used to indicate a method that can be invoked without an instance variable (i.e. no
value of this
). The order of declaration matters:
class C; // case (1): instance method whose arguments and local variables // have static lifetime task static foo(); // case (2): non-instance method whose variables // have automatic lifetime static task foo(); endclass
The SV-LRM prohibits case (1). DSim permits it. Note that pure
or virtual
methods must have automatic lifetime.
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article