In SystemVerilog, is it allowed to read a parameter from an interface - system-verilog

I am a bit confused as to if it is legal, from a standards stand point, to read a parameter from an interface.
Like so
interface foo_if #(parameter BAR=5)();
...
logic [BAR-1:0] data;
modport slave(input data, ...);
endinterface
module foobar(foo_if.slave s);
...
logic [s.BAR-1:0] bar;
logic [$bits(s.data)-1:0] m_data;
...
endmodule
I have a problem where a major synthesis tool vendor can not even handle this. And they explicitly tell you in the help message that it is not allowed to use $bits() with a interface member.
However a simulation tool from another vendor handles this perfectly as does another synthesis tool I have.
However in SystemVerilog for Design by S. Sutherland et al. it is stated:
Because the design hierarchy may not be yet fully resolved during
elaboration, it is illegal to assign a parameter, specparam, or
localparam constants a value that is derived from elsewhere in the
design hierarchy
However if I am not allowed to use parameters from interfaces, it really cripples the usefulness of interfaces.
The SystemVerilog 1800-2012 Standard on the other hand states:
25.10 Access to interface objects
Access to objects declared in an interface shall be available by
hierarchical name reference, regardless of whether the interface is
also accessed through a port connection or through a virtual
interface, and regardless of the existence of any declared modports in
that interface. A modport may be used to restrict access to objects
declared in an interface that are referenced through a port connection
or virtual interface by explicitly listing the accessible objects in
the modport. However, objects that are not permissible to be listed in
a modport shall remain accessible.

The issue here is not about access, but what is allowed in places that require constant expressions. The LRM is not very clear that interface port references are not considered hierarchical references. But the tool is not complaining about s.BAR, it is complaining about s.data, which is a variable, not a parameter. Normally, you can't use variables in constant expressions, but the LRM 20.6.2 says
The $bits function can be used as an elaboration time constant when
used on fixed-size data types; hence, it can be used in the
declaration of other data types, variables, or nets.
So $bits(s.data) should have been treated like a parameter expression.
BTW, you should be using the latest freely available IEEE 1800-2012 LRM.

Related

Is There A Technical Reason SystemVerilog Cannot Pass Module Name as Parameter?

I want to do something like this:
module BusinessLogicVersion_1(clk, rst, d, q);
// Erudite business logic goes here
endmodule
module BusinessLogicVersion_2(clk, rst, d, q);
// Different implementation of same interface.
endmodule
// Then, when instantiating the module that requires an implementation of whatever interface,
// I want to do something like this:
ModuleXyz #(
.business_logic(BusinessLogicVersion_2) // <--- Pass an implementation of an interface as parameter
) (.clk(clk), .rst(rst), ...);
I have tried to find ways to do this, and from what I've read SV does not allow it.
My question is:
Is there a technical reason why this shouldn't be possible?
Technically, nothing is technically impossible in software given enough time, space and money! StackOverflow is not the forum for why kinds of questions.
SystemVerilog has a different approaches that implements what you are looking for. One way is called a configuration (See section 33. Configuring the contents of a design in the IEEE 1800-2017 SystemVerilog LRM).
For your case, what you would do is compile different versions of same module name ModuleXyz into different libraries and then use either command line options or a config block that selects which version to be selected for different instances. I would look at the LRM for examples.
The other method is using a _generate construct to select different modules you want instantiated. See section 27. Generate constructs. This is simpler, but less flexible since you have to know upfront which versions are available.
case(VERSION):
1: BusinessLogicVersion_1 inst (clk, rst, d, q);
2: BusinessLogicVersion_2 inst (clk, rst, d, q);
default: $error("Version does not exist");
endcase
I assume you're trying to do some kind of dependency injection, where the modules you're passing in are supposed to be different strategies. Also, I see from your profile that you're familiar with C++, so I'll try to map what you're trying to do onto that language. (Beware of gross simplifications or not-so-accurate analogies.)
A SystemVerilog module is akin to a C++ class. By passing a module name to you ModuleXyz, you're trying to do something like pass a class as a function argument in C++. This isn't possible in that language either. You generally pass instances of classes.
In order to pass an instance of a class, you'd need to first construct it. This would mean passing it your desired constructor arguments. Your module has ports, which are conceptually similar to a class's constructor arguments. When you instantiate a module, you connect its ports.
In your example, I'm guessing you would like to pass in the type of module that ModuleXyz should instantiate inside. In C++ you would generally pass a factory object, which knows how to construct the object you need, with the constructor arguments you want. This pattern isn't possible with modules, as only "direct" instantiation is allowed.
As #dave_59 pointed out, switching out module types is done using configurations. It's sort of like doing dynamic loading of different shared libraries, to switch out the implementations.
If your simulator doesn't support configurations (as language constructs), it will usually provide compile switches that allow you to implement something similar. It will compile different versions of the module, but you will be able to choose which one gets "linked".
If you really, really need to use dependency injection, I'd suggest you try to migrate your code from trying to pass modules, to passing interfaces. It is possible to pass instances of those around. Just remember, that you'll be passing already constructed instances, not types.

Differences b/w "internal" and "externa" in systemRDL register component property

I am confused about "internal" and "external" in systemRDL register component property usage. from SystemRDL 2.0 reference manual, it says:
Registers can be instantiated in three forms.
— **internal** implies all register logic is created **by the SystemRDL compiler** for the instantiation (the default form).
— **external** signifies the register/memory is implemented by the designer and the interface is inferred from instantiation.
how to understand them? I understand this property will impact RTL module generation from an RD file
my confused point is "systemRDL compiler" statement in "internal" part description. if we say systemRDL compiler is to interpret rd file and put all related properties into a plain database, user can define customized generator base on these plain database, so seems like these "internal" and "external" keyword will be only used when we write generator for RTL register module part, is my understanding correct?
any guidance to define "internal" and "external" for register in RD file?
Thanks
Your understanding is correct. The internal and internal component modifiers are there to influence the output of the RTL generator.
By default, registers, regfiles, and fields are internal, so they would be included in the output of a RTL generator.
If you mark a component as external, you are signalling to the compiler that you want to define the implementation of the register/field/etc yourself. The compiler would then provide some form of interface for you to implement the component externally, but still have it be part of the address space of the parent being exported to RTL.
Worth mentioning that addrmap components are implicitly external by default since they are intended to describe a physical boundary between RTL components.

What is the occasion when we have to use the 'net' data type in systemverilog?

As I know, nowadays the 'reg' type in systemverilog can used in assign statement.
In old fashion, the assign statement does use the only the 'net' type.
So I want to know that what kind of the signals are should have to be the 'net' type in systemverilog?
Update1
From here, http://www.testbench.in/IF_01_INTERFACE.html
I can find a interface declaration.
interface intf #(parameter BW = 8)(input clk); 
logic read, enable; 
logic [BW -1 :0] addr,data; 
endinterface :intf 
At this here, I want to know that why the read and enable and addr and data signal are clared logic data type? Is there any reason? Why not used reg or wire?
A net is used when there are multiple drivers on a signal, usually in conjunction with a bi-directional port, and for designs at the switch level that require strength to operate. See http://go.mentor.com/wire-vs-reg for more details.
Regarding the usage of net Dave's answer pretty much covers it.
From the IEEE Std 1800-2012,
The keyword reg does not always accurately describe user intent, as it
could be perceived to imply a hardware register. The keyword logic is
a more descriptive term. logic and reg denote the same type.
More info on the usage of logic can be found in below links.
1) Morgans answer
2) Greg's answer

What does the 'I' in IObservable<T> or IObserver<T> mean?

I'm trying to learn/understand Rx, specifically RxJS, and keep seeing references to IObservable, IObserver, etc.
Can anyone tell me what the leading I means and/or where it comes from?
From my searching, it looks like the <T> is for the type. If this is wrong or naive, I'd appreciate some clarification on this as well.
Thanks!
In ye olden days of MFC for C++, Microsoft had Hungarian notation down to a very irritating artform, where all concrete classes were prefixed with C and their COM interfaces with I, this does help avoid the conflict where a COM interface and class might share the same name and so muddy your project.
Part of this notation carried over into .NET, except only interfaces kept the I prefix, but classes and other types dropped their Cs. This does make non-interface-heavy code easier to look at, but can cause ambiguity if you begin a class name with a 2-letter acronym beginning with I (as two-letter acronyms must be completely capitalised according to the the .NET style guidelines), but this is rare.
(I note that generic type name placeholders are prefixed with T too, e.g. TKey and TValue in Dictionary).
An example of why this is necessary is when dealing with collections in .NET, if you're building a reusable library and don't want to expose implementation details (e.g. if you use List<T> or T[] as an underlying collection field type), you can use IList<T> or IReadOnlyList<T> which are interfaces. If the interface was simply called List<T> it would conflict with the actual type List<T>, and ReadOnlyList<T> (an interface) might get confused with ReadOnlyCollection<T> (a class).
You might argue that this wouldn't be a problem if classes and interfaces had a different namespace. C does this: struct types and scalars exist in different namespaces, which unfortunately means that every time a struct type name is used, its usage must be prefixed with struct (e.g. a declaration: struct Foo foo). People workaround this by using typedef with anonymous structs, but I feel the end-result is messy (and the Linux kernel coding guidelines prohibit this too).
In Java, however, interfaces are not prefixed with I but instead have class-like names. Whether this is "correct" or "better" is entirely up for debate. C++ does not have interface types, just pure-abstract classes and multiple-inheritance, so the I prefix isn't typically seen at all outside of COM.

What is the purpose of WinRT's IStorageFolder interface?

Since WinRT exposes both the IStorageFolder interface and the StorageFolder class, my reflex was to use the interface throughout my code. I reasoned that IStorageFolder could be used as an abstraction to support non-filesystem folders like those in compressed archives. However, looking at the IStorageFolder interface, every method is declared to return concrete StorageFolder instances. As such, it would not be possible to implement a virtual filesystem based on this interface.
So how is IStorageFolder a useful abstraction? Or does its existence have a technical justification?
It is an interface because there are two implementations of IStorageFolder: One is StorageFolder, and another is FolderInformation. Since there are two implementations, the common behavior uses an interface so that you can write a function that operates on either StorageFolder or FolderInformation.