Is it possible to define a package inside of a SystemVerilog Interface?
example:
interface my_ifc();
package a;
logic reset;
logic clk_usb;
endpackage
logic Rwn;
logic [7:0] Addr;
endinterface
No. A package must be declared outside of any other nested scope (at the compilation unit level)
Package is a way to share code between modules, interfaces and programs in SystemVerilog. In your case, you could create a package outside the interface and then just import whatever you wish inside the package, in order to be made visible. Like this:
import a::*;
But the package, written inside the interface, is of no usefulness.
Related
I have some modules that I want to print some wires from in a PRINTER module. I have two different testbenches, which wraps these modules slightly differently, see code below. Is it possible to use the same PRINTER to print print_me_a and print_me_b using hierarchical references?
I know all the hierarchical references in the testbenches, and I know I could expand the PRINTER to instead take inputs and then connect relative references there, but hierarchical references inside the PRINTER are easier to expand if I want to add a lot of new prints, then I only have to change in the PRINTER.
Given the structure below I can't really utilize bind to make it work in both testbenches. I tried to instead of instance references use MOD_A.print_me_a and MOD_B.print_me_b, and that worked when I use VCS, but not in Questa, and I would like for the solution to work in both.
Is there any way to provide an hierarchical reference or name, or some macro, to the PRINTER as a parameter maybe, so that I can have the same code inside PRINTER for printing the wires in both testbenches? Or can I utilize some parameter which tells me which testbench the instance is used in to generate some different macros like `define MOD_A_DEF known_name_wrap_a.known_name_a for later common usage in PRINTER?
module MOD_A();
wire print_me_a; // I want to print this
endmodule
module WRAP_A();
MOD_A known_name_a();
endmodule
module MOD_B();
wire print_me_b; // I want to print this
endmodule
module TOP_MOD();
WRAP_A known_name_wrap_a();
MOD_B known_name_b();
endmodule
module PRINTER();
// Pseudo code, can I access these with hierarchical ref?
$display(known_name_wrap_a.known_name_a.print_me_a) // Only works in TOP_TB
$display(known_name_a.print_me_a) // Only works in OTHER_TB
$display(known_name_b.print_me_b); // Happens to work fine in both
endmodule
module TOP_TB();
TOP_MOD top_mod();
bind top_mod
PRINTER top_tb_printer();
endmodule
module OTHER_TB();
MOD_A known_name_a();
MOD_B known_name_b();
PRINTER other_tb_printer();
endmodule
You could use ports in your PRINTER module and connect them with relative hierarchical references.
module PRINTER(input wire a,b);
initial $display(a);
initial $display(b);
endmodule
module TOP_TB();
TOP_MOD top_mod();
bind top_mod PRINTER top_tb_printer(
known_name_wrap_a.known_name_a.print_me_a,
known_name_b.print_me_b
);
endmodule
module OTHER_TB();
MOD_A known_name_a();
MOD_B known_name_b();
PRINTER other_tb_printer(
known_name_a.print_me_a
known_name_b.print_me_b);
endmodule
I could declare a package or import a package in Modelica models, but I am not sure if there is any difference between them, I tried the following code, both of them work fine.
My question is :
Is there anything I should pay attention to when using these two methods?
partial model A
package SI1=Modelica.SIunits;
import SI2=Modelica.SIunits;
SI1.Voltage u1;
SI2.Voltage u2;
end A;
You are doing two fundamentally different things here, which both work for this case:
package SI1=Modelica.SIunits; is called a short class definition.
You create a new package named SI1, which inherits everything from Modelica.SIunits.
Short class definitions are basically the same as writing
package SI1
extends Modelica.SIunits;
end SI1;
See chapter 4.5.1 Short Class Definitions in the Modelica spec for details.
import SI2=Modelica.SIunits on the other hand simply influences where the Modelica tool looks for class definitions - so no new class is defined here. The chapter 13.2.1.1 Lookup of Imported Names explains that in the Modelica spec.
If you just want to use the package, import it. That's what import was designed for. Declaring a new package only makes sense if you want to add functionality or change anything (which is very limited though, if you are using the short class definition).
Only the import clause seems to trigger the lookup on a package that is not already loaded. Using for example the Modelica_LinearSystems2 library:
import: it checks, and Modelica_LinearSystems2 is loaded
partial model A
import ls2=Modelica_LinearSystems2;
end A;
package: it checks, but Modelica_LinearSystems2 is not loaded
partial model B
package ls=Modelica_LinearSystems2;
end B;
I guess that can break your models if not all of their dependencies are loaded when trying to simulate.
It is nevertheless interesting to see how Dymola (or even Modelica, since pedantic check doesn't throw any error) does not seem to care much about the use of package instead of import, when it comes to packages already loaded. I wasn't expecting the following model to work:
model C
package SI1=Modelica.SIunits;
SI1.Voltage u1;
parameter SI1.Current R=1;
equation
u1=2*R;
end C;
It turns out that even auto-completion (Ctrl+Space) works:
I have to embed DV code inside an RTL module for verification purposes. There are many (1000s) of instances of this RTL module. How do I make it controllable on a per instance basis from the test? Testbench is in SystemVerilog UVM. I want to stay away from CDPI?
Any suggestions would be appreciated
-Hawki
You use the bind construct to insert a module or interface into your RTL module. Inside this bound module you construct a class with methods that interact with your RTL module. The class object is set into the uvm_config_db for each instance. Then your testbench gets these objects from the uvm_config_db and you can call those object methods from the testbench.
I wrote a DVCon 2012 paper The Missing Link: The Testbench to DUT Connection with a complete example for doing this.
As Dave described in his answer, bind statements are usually the best way to go.
Though there are other ways as well, which might be more convenient in some cases. They are based on parameterized modules.
1) direct instantiation with parameters
module rtl #(bit dvflag = 0) ();
...
if (dvflag)
dv_module dv_instance(...);
...
endmodule
module dut;
rtl rtl1();
rtl #(.dvflag(1)) rtl2();
...
endmodule
2) Overwriting instances with v2k config statements.
module dut;
rtl rtl1();
rtl rtl2();
endmodule
...
config dv_cfg;
instance dut.rtl2 use #(.dvflag(1));
...
endocnfig
I have a tool that produces .sv RAL files for use in a UVM testbench. The problem is that this file creates the register block as a package. My issue is that for my testbench, I want to import multiple .sv RAL files (representing different reg blocks).
To do this, I want to create a single package all_my_regs_pkg.sv and `include the other packages into this package. I get a compilation error and looking into it, it looks like there isn't support for nested packages in SystemVerilog.
So do I need to manually import each of the reg block packages when I want to use them? I suppose I could create a file with the imports and just `include it, but is this the only way?
SystemVerilog does not allow nesting of package declarations. The best thing for you do do is to define a file that is a list of package import statements and have users `include that file where needed.
The is another SV feature that allows you to chain package imports, but you have to explicitly export a symbol that you import into a package to be imported by the next package. See Section 26.6 Exporting imported names from packages in the 1800-2012 LRM
I'm a relative newbie to SystemVerilog.
I have a package with class A defined in it. This class uses a virtual interface, since
it's a driver (BFM) in a testbench. I'm using a package so I can use the same BFM in
other designs.
In my testbench, I import the A class and pass to it an instance of the virtual interface.
However, when a task in the class tries to assign a value to a signal in the interface, I'm getting a compilation error.
What am I doing wrong?
How can one package a BFM with a virtual interface?
Thanks,
Ran
SystemVerilog packages cannot include interfaces within the actual package. So your interface needs to be compiled along with you package source. The classes you define will reside in the package while the interface definition resides in the global scope where modules live.
Classes within packages can make references to virtual interfaces, but you need to make sure the interface is compiled and visible, apart from the package source.
Strictly according to the spec, I don't think this is possible since it adds an implicit external dependency:
Items within packages are generally type definitions, tasks, and
functions. Items within packages shall not have hierarchical
references to identifiers except those created within the package or
made visible by import of another package. A package shall not refer
to items defined in the compilation unit scope.
It doesn't say anything about the design element namespace, which is where interface declarations live, but accessing any member of an interface requires a hierarchical reference.
You should consider packages to be completely self-contained, other than pre-processor directives and import.
Generally the class declaration not present before its usage is resolved with the help of systemverilog typedef definition. For example "Class A uses Class B" and "Class B uses class A" then typedef is used to resolve the stalemate.
Now when you bring in the package with the above scenario then one needs to ensure both Class A and Class B have to be in same package. If they are not then the compile wont go through.
The reason being the SystemVerilog parser will need the definition of the classes indicated with the typedef at the end of the package parsing. This fails.
This issue needs to watched out that "typedef does not apply across package".