Virtual Interface in Config class - system-verilog

How do I point out an interface in TB_top from my configuration class using virtual interface without using uvm_config_db?

This question tests your knowledge of uvm_config_db, which is just a database of global variables inside the uvm_pkg. All your have to do is create a virtual interface variable inside the package where you define your configuration class, then set it before calling run_test()
package my_config_pkg;
virtual my_interface vif;
class my_configuration;
...
endclass
endpackage
module TB_top;
my_interface ifinst();
initial begin
my_config_pkg::vif = ifinst;
run_test("my_test");
end
endmodule

Related

Understanding virtual interfaces with classes

I am studying SystemVerilog for verification purposes and stumbled upon virtual interfaces and classes. I am trying to set up an example where I define a virtual interface attribute in a class to be initialized through a method. It looks like this:
class myclass;
virtual interface my_intf val;
...
function void configure(virtual interface my_intf input_intf);
val = input_intf;
endfunction
...
endclass
An object of this class is instantiated in a testbench that has the interface I intend to pass on to the object as an input.
module mytb(my_intf bus);
...
myclass c1;
initial
begin
c1 = new;
c1.configure(bus);
...
endmodule
What I am encountering is a warning at elaboration time that says [related to c1.configure(bus)] formal and actual do not have assignment compatible data types (expecting datatype compatible with 'virtual interface my_intf' but found 'my_intf' instance instead. Nevertheless, the simulation ends with success, and I made sure to follow the code presented in the course I am attending. Is there anything I am still missing or can I neglect this warning?
Thanks!
I have looked more into my code and found out that it had to do with the fact that the testbench uses a specific configuration of the interface defined through a modport and I had to make sure that I extended that to the class too. In short, the testbench receives a my_intf.intf1 bus interface and this caused the tool to complain as it was expecting my_intf but got my_intf.intf1 instead.
Thanks everyone
You missing a lot of code, so it it difficult to figure out what is going one.
However, for references the following code works:
class myclass;
virtual interface my_intf val;
function void configure(virtual interface my_intf input_intf);
val = input_intf;
endfunction
endclass
module mytb(my_intf bus);
myclass c1;
initial
begin
c1 = new;
c1.configure(bus);
end
endmodule
interface my_intf;
endinterface
module top;
my_intf intf();
mytb mytb(intf);
endmodule
Few rules of thumb:
an interface must be defined as intercface..endinterface and it must be visible in all parts of compilation (can be declared after it is used, similarly to moduels). See code example.
the interface must be instantiated in a module, e.g. in module top of the example.
Note, similar issues as you described can happen if you incorrectly use compilation units.
I'm not familiar with SystemVerilog, but I've just RFTM around and the right syntax is:
virtual interface_name instance_name;
So maybe you should try something like this:
virtual my_intf val;
function void configure(virtual my_intf val);
this.val = val;
endfunction
...
endclass
See https://verificationguide.com/systemverilog/systemverilog-virtual-interface/#What_is_the_need_for_a_virtual_interface_in_SystemVerilog

What causes 'interface resolution' compilation error when working with classes and virtual interfaces

I have declared in a design file following interfaces:
interface t_clocks;
ckrs_t ClkRs125MHz_ix;
ckrs_t ClkRs160MHz_ix;
ckrs_t [3:0] ClkRsLink_ixb;
ckrs_t ClkRsLinkx2_ixb;
logic tdclk_sampling;
modport producer(output ClkRs125MHz_ix,
output ClkRs160MHz_ix,
output ClkRsLink_ixb,
output tdclk_sampling);
modport consumer(input ClkRs125MHz_ix,
input ClkRs160MHz_ix,
input ClkRsLink_ixb,
input tdclk_sampling);
endinterface // clocks
interface t_bst(input ckrs_t ClkRs_ix);
tb_t mark;
modport consumer(input ClkRs_ix, input mark);
modport producer(output ClkRs_ix, output mark);
endinterface // t_bst
and in a package classes working with those interfaces:
package clspkg;
import DefinitionsPkg::*;
class bst_generator;
virtual t_bst.producer bst_master;
....
endclass // bst_generator
class clock_generator;
virtual t_clocks.producer clk_tree;
....
endclass // clock_generator
endpackage // clspkg
I have glued all together in the testbench, using only clock_generator class from the package:
module tb_turn_emulator;
import clspkg::*;
t_clocks clk_tree();
clock_generator cgen;
// ???????????????
//t_bst blast_radius(clk_tree.ClkRs160MHz_ix);
default clocking cb #(posedge clk_tree.ClkRs160MHz_ix.clk); endclocking
`TEST_SUITE begin
`TEST_SUITE_SETUP begin
cgen = new;
cgen.clk_tree = clk_tree;
cgen.run();
##10;
end
....
endmodule
Now, when I try to compile such example, it FAILS with Virtual interface resolution cannot find a matching instance for 'virtual t_bst.producer'
It took me quite some time to find out, that if I instantiate as well the t_bst interface in the testbench module (uncommenting the t_bst line in the code above), everything goes smoothly, no compilation error and the testbench passes as usual.
I don't understand why the t_bst interface has to be instantiated as it is not at all used in code. It is true that I am importing the entire clspkg package, but nothing changes when I cherry pick by importing only the clock_generator by import clspkg::clock_generator.
What is wrong? I'm using Mentor Modelsim
First about using packages:
Once you import one identifier or every identifier from a package in a design, the entire package exists in your design. That means all the static variables get allocated and initialized, as well as all the code for tasks and functions get generated. If static variable initializations call functions like class constructors, that implies executing procedural code without ever referencing it directly. (For those of you familiar with the factory design pattern and UVM, this is exactly how factory registration works.)
Next about using interfaces:
Like a module, an interface is a design element containing definitions of lots of different things. They can define variables, routines, import other packages, and have port connections. But nothing inside an interface exists or generates any code in a design until other design unit instantiates it, or in the case of a module, gets established as a top-level instance.
Now about using virtual interfaces:
Virtual interface are the primary method used to bridge the two kingdoms of the dynamic class based testbench world with the static instance based design world. Virtual interfaces behave much like a class type, except that there is no rule to have seen a definition of the interface before using it in your code. Hierarchical reference also have this capability of referencing something that does not exist at the point of compilation, but must be resolved later in the elaboration phase of compilation.
To summarize, the compiler generates code for a virtual interface once it sees a reference to it whether you actually think you are using it or not. I would try to align packages with specific interfaces they are associated with.
From SV LRM (25.9 Virtual interfaces):
A virtual interface is a variable that represents an interface instance.
A virtual interface shall be initialized before referencing a component of the virtual interface; it has the value null before it is initialized. Attempting to use a null virtual interface shall result in a fatal run-time error.
I hope it answers to your question.

One IMP_PORT connected to multiple EXPORTS

I am creating a scoreboard which has a single implication port. I want to connect multiple exports from a parent class to the same imp port of the scoreboard class I am writing. Essentially (in pseudo-code):
class parent_class extends uvm_scoreboard;
uvm_analysis_export #(my_type) export0;
uvm_analysis_export #(my_type) export1;
uvm_analysis_export #(my_type) export2;
uvm_analysis_export #(my_type) export3;
my_scoreboard m_scb;
function void connect_phase(uvm_phase phase);
export0.connect(m_scb.my_imp);
export1.connect(m_scb.my_imp);
export2.connect(m_scb.my_imp);
export3.connect(m_scb.my_imp);
endfunction
endclass
class my_scoreboard extends uvm_scoreboard;
uvm_analysis_imp#(my_type) my_imp;
function void write (my_type);
// do something here
endfunction
endclass
This works fine but I am wondering now, if we get 2 or 3 or 4 transactions broadcasted from their ports on the same clock cycle, will the write function be called twice/thrice/4times? This is the behaviour I would want.
I don't have a dependency on the order in which they are called but don't want to miss a broadcast because of my setup.
Yes, you can have multiple write()s called in an indeterminate order. If the scoreboard needs to know which port it came from, you will have to put that information in the transaction.

Can I #define a constant solutionwide within c# code without project settings?

I know this was aksed and answered a a couple of times e.g.
Solution-wide #define, Is There anyway to #define Constant on a Solution Basis? and How to define a constant globally in C# (like DEBUG).
But in my case I can not use any of the suggested methods:
I'm writing on different "modules" (or plugins if you want so) for UnityProjects (kind of a package providing a certain functionality). The idea is that a developer can load a certain "module" to use in his project by importing a UnityPackage with all scripts and resources in it.
But some of these modules themselves depend on other modules. So what I tried so far was having a class Constants in each module with seperated namespaces and preprocessor definitions.
Module A
#if !MODULE_A
#define MODULE_A // BUT I WOULD NEED THIS GLOBAL NOT ONLY HERE
#endif
namespace Module_A
{
public static class Constants
{
// some constants for this namespace here
}
}
Module B
#if !MODULE_B
#define MODULE_B // BUT I WOULD NEED THIS GLOBAL NOT ONLY HERE
#endif
#if !MODULE_A // WILL BE NOT DEFINED OFCOURSE SINCE #define IS NOT GLOBAL
#error Module A missing!
#else
namespace Module_B
{
public static class Constants
{
// some constants for this namespace here
}
// and other code that might require Module A
}
#endif
But ofcourse this cannot work like this since #defines are not global but only in the current file.
Problem
For this whole idea of modules and a simple "load your modules" I can not ask the user to first make changes to the project or solution settings how e.g. suggested by this answer but instead have to use only the (c#) resources that come imported with the UnityPackage (at least with my current know-how).
Is there any way to somehow set/define those constants for the entire Unity-Project by only importing the module's UnityPackage?
Edit:
I could find a solution for 1 definition in Unity using Assets/msc.rsp. But this still wouldn't work for multiple modules since they would have to write into the same file.
After a lot of searches I've finally been able to put together a surprisingly simple solution I'ld like to share with you:
InitializeOnLoad
Unity has an attribute [InitializeOnLoad]. It tells Unity to initialize according class as soon as
Unity is launched
After any re-compiling of scripts => also after importing a new unitypackage with scripts
static Constructor
In their Running Editor Code On Launch example, they show, how to combine this with a static constructor.
From static-constructors:
A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
While usually you still would have to create an instance of the class, the static constructor is "instanciated/executed" instantly when the class is initliazed, which we force using the [InitializeOnLoad] attribute.
Scripting Define Symbols
Further Unity actually has project wide defines in the PlayerSettings.
And the good part is: We also have access to them via scripting API:
PlayerSettings.GetScriptingDefineSymbolsForGroup
PlayerSettings.SetScriptingDefineSymbolsForGroup.
So what I did now is the following
Module A
This module has no dependencies but just defines a "global define" in the PlayerSettings. I placed this script somewhere e.g. in Assets/ModuleA/Editor (important is the last folder's name).
using System.Linq;
using UnityEditor;
namespace ModuleA
{
// Will be initialized on load or recompiling
[InitializeOnLoad]
public static class Startup
{
// static constructor is called as soon as class is initialized
static Startup()
{
#region Add Compiler Define
// Get the current defines
// returns a string like "DEFINE_1;DEFINE_2;DEFINE_3"
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
// split into list just to check if my define is already there
var define = defines.Split(';').ToList();
if (!define.Contains("MODULE_A")
{
// if not there already add my define
defines += ";MODULE_A";
}
// and write back the new defines
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
#endregion
}
}
}
Module B
This module depends on Module A. So itself defines a "global define" (so later Modules can check their dependecies on Module B) but additionally it checks first, if Module A is imported. If Module A is missing, it prints an error to the Debug Console.
(You could as well throw a compiler error using #error SOME TEXT, but for some reason this is not capable of printing out the URL correctly so I decided for the Debug.LogError)
I placed this script somewhere e.g. in Assets/ModuleB/Editor
#if MODULE_A
using System.Linq;
#endif
using UnityEditor;
#if !MODULE_A
using UnityEngine;
#endif
namespace ModuleB
{
// Will be initialized on load or recompiling
[InitializeOnLoad]
public static class Startup
{
// static constructor is called as soon as class is initialized
static Startup()
{
#if !MODULE_A
Debug.LogErrorFormat("! Missing Module Dependency !" +
"\nThe module {0} depends on the module {1}." +
"\n\nDownload it from {2} \n",
"MODULE_B",
"MODULE_A",
"https://Some.page.where./to.find.it/MyModules/ModuleA.unitypackage"
);
#else
// Add Compiler Define
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
var define = defines.Split(';').ToList();
if (!define.Contains("MODULE_B"))
{
defines += ";MODULE_B";
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
#endif
}
}
}
So later in other scripts of Module B I have two options (both do basically the same)
I can either check everywhere #if MODULE_A to check exactly the module this script relies on
or I can instead check #if MODULE_B to rather check with one line if all dependecies are fulfilled since otherwise I don't define MODULE_B.
On this way I can completely check all dependencies between certain modules which is awesome. The only two flaws I saw until now are:
We have to know how the define (e.g. MODULE_A) looks like for every module and if it is changed in the future it has to be changed in all depending modules as well
The "global define" isn't getting removed in case the module is deleted from the project
But well - which solution is perfect?
In general, the way I would solve this problem in C# is by defining a common set of interfaces that all your modules would contain. I think you can do this with Unity by placing the files from each module in the same location, thus allowing later installations to overwrite those same files (with, obviously, the same content). You would then put editor controls that expose properties to hold instances of those interfaces and then wire them up in the UI. You would test those properties for a value of null to determine which ones are missing.
Common.cs:
public interface IModuleA {}
public interface IModuleB {}
ModuleA.cs
public class ModuleA : IModuleA {}
ModuleB.cs
public class ModuleB : IModuleB
{
public IModuleA ModuleAInstance {get; set;}
private bool IsModuleAPresent()
{
return !ModuleAInstance == null;
}
}
The ideal way to solve it would be with a package manager and proper dependency injection, but doing that with Unity is not straightforward.

How to handle the interface with package in systemverilog

I am creating a simple uvm tb these days and I meet an issue with interface usage. Here is my code.
in the /my_proj/tb_uvm/intf/my_if.svh file: (interface definition)
interface my_if (
input iCLK,
input iRSTb,
inout data
);
clocking monitor_cb #(posedge iCLK);
input iRSTb;
input data;
endclocking
modport monitor_mp(
clocking monitor_cb
);
endinterface : my_if
and I need to instance this interface in the /my_proj/tb_uvm/agent/my_driver.svh file :
class my_driver extends uvm_driver;
`uvm_component_utils(my_driver)
virtual my_if m_vif;
...
endclass
I tried to define a package file(named my_agt_pkg.sv) under /my_proj/tb_uvm/agent/ because there are several driver/monitor files in this directory including the my_driver.svh I mentioned above.
package my_agt_pkg;
import uvm_pkg::*;
`include "my_driver.svh"
`include "../intf/my_if.svh"
....
endpackage
but I failed to compile because of below error. Could anyone kindly give me a help on this issue ?
Found 'interface' inside package before 'endpackage'. 'interface' inside 'package' is not allowed.
The error message means what is says: you are not allowed to declare an interface inside a package.
A virtual interface is a peculiar concept. It behaves like a class variable, but an interface gets defined and instantiated like a module.
Just move your interface declaration outside the package