UVMF: parametrized hdl typdefs

My verification design follows structure introduced in examples of the UVMF (3.6f) library.
One of my interface uses struct signals. The struct depends on parameters, ie.


//my_interface_pkg_hdl.sv
typedef struct{
 logic [WIDTH_A-1 : 0] a;
 logic [WIDTH_B-1 : 0] b;
} MY_STRUCT_T;

and is defined in my_interface_hdl pacakge.

The both WIDTH_A and WIDTH_B parametrize my agent, interface, monitor_bfm and driver_bfm. The code will not compile, as WIDTH_A and WIDTH_B are not defined at the level my_interface_hdl pacakge. My workaround is to add extra include file with macro like:


//my_interface_pkg_hdl_macros.sv
`define MY_STRUCT_T \
typedef struct{ \
 logic [WIDTH_A-1 : 0] a; \
 logic [WIDTH_B-1 : 0] b; \
} MY_STRUCT_T;

and include it inside the interface, monitor_bfm and driver_bfm:


interface my_if;
  `include "my_interface_pkg_hdl_macros.sv"
  `MY_STRUCT_T
endinterface

This solution works, however, the “same” type is defined in three different places and IMHO is not elegant.
Is there any good design practice to overcome this problem?

In reply to adrianf0:

You should feine your parameters in a seperate package like this:

package my_param_pkg;
  parameter WIDTH_A = 16;
  parameter WIDTH_B = 32;
endpackage

Then you can import this package in any place you need these parameters, like in the interface, etc.
Take care to compile this package prior to any other code.

In reply to chr_sue:
It will not work, as, in my case, those parameters are defined at the level of hdl_top (test_bench). I don’t think it’s a good idea, if an interface from a VIP library depends on packages defined at the level of testbench.

In reply to adrianf0:

I do not know the details of your environment, but I believe it is quite common a VIP has a common package and is provided together with the VIP source code. Using this package in a system level is not forbidden.

In reply to chr_sue:

In reply to adrianf0:
I do not know the details of your environment, but I believe it is quite common a VIP has a common package and is provided together with the VIP source code. Using this package in a system level is not forbidden.

You are right that VIP can provide extra common packages.
However, in my case, the parameters are propagated top->bottom. During compilation of VIP packages, compilation will fail, as parameters are unknown yet (they are defined at the level of testbench). Basically, I would need parametrized packages which don’t exist in SystemVerilog.

In reply to adrianf0:

SV packages are always top to bottom. I guess your VIP is provoding a common package which is not RO. There you can make your settings regarding your system application.
Then you have to adopt your compile script with respect to your new structure. I do not see any problem.

In reply to chr_sue:

In reply to adrianf0:
SV packages are always top to bottom. I guess your VIP is provoding a common package which is not RO. There you can make your settings regarding your system application.
Then you have to adopt your compile script with respect to your new structure. I do not see any problem.

I think we have a misunderstanding.
I assume that VIP packages, in view of reusability, should be testbench agnostic. Thus, they should not make any assumptions that testbench will provide an extra package with parameters. This information, should come through actual parameters syntax (ie.

my_interface #(.WIDTH_A(5), .WIDTH_B(3) inter;

).

Moreover, let’s imagine that in the testbench we would like to have 2 interfaces of the same type but differently parametrized. Solution with an extra package with parameters would not work in such case.

In reply to adrianf0:

I don’t see really the benefit of your approach. In any way your VIP has to be configured with respect to certain parameters etc. This package prrovides certain actual parameters for a configuration
It is an elegant way to use a package for this.
What you are doing is simple Verilog style, not knowing about packages.
If your common VIP packages is RO we can use this to perfrom a systme level setup by exporting imported names of packages.

In reply to chr_sue:

With the solution you propose, how would you cover a case, where the same interface is used twice, with different parameters?

In reply to adrianf0:

package common_params_pkg;
  parameter WIDTH_A_1 = 4;
  parameter WIDTH_A_2 = 6;
  parameter WIDTH_B_1 = 12;
  parameter WIDTH_B_2 = 16;
endpackage

module top;

  import uvm_pkg::*;
  `include "uvm_macros.svh"
  import common_params_pkg::*;

  my_interface #(.WIDTH_A(WIDTH_A_1), .WIDTH_B(WIDTH_B_1) inter1;
  my_interface #(.WIDTH_A(WIDTH_A_2), .WIDTH_B(WIDTH_B_2) inter2;
.....

wndmodule

In reply to chr_sue:

No, this solution doesn’t address and solve my issue.
As I tried to explain in the first post, my problem was the fact, that a VIP provides an interface which uses structures (or array of structures), which are parametrized. The interface is connected to a DUT, which uses the same kind of ports (structures, or array of structures). As the same type must be shared between interface, monitor_bfm_interface and driver_bfm_interface one would define it, as @chr_sue rightly pointed, in a common package:


package my_interface_pkd_hdl;
//my_interface_pkg_hdl.sv
typedef struct{
 logic [WIDTH_A-1 : 0] a;
 logic [WIDTH_B-1 : 0] b;
} MY_STRUCT_T;
endinterface

Of course this package, thus the whole VIP, will not compile, as all types inside VIP’s packages must be fixed. During my_interface_pkd_hdl compilation WIDTH_A and WIDTH_B are undefined.

Eventually, I solved this issue by passing to the interfaces (if, monitor_bfm, driver_bfm) not WIDTH_* parameters which would define the structure, but the type of the structure itself:


interface my_if #(type MY_STRUCT_T)();
   tri MY_STRUCT_T my;
endinterface

interface my_monitor_bfm #(type MY_STRUCT_T)(my_if bus);
   tri MY_STRUCT_T my_i;
   assign my_i = bus.my;
endinterface

The type is defined in a package of the DUT and provided to the VIP interfaces in top level HDL module:


module hdl_top;
   my_if #(DUT_common_pkg::MY_STRUCT_T) if();
   my_monitor_bfm #(DUT_common_pkg::MY_STRUCT_T) monitor_bfm(if);
endmodule

In reply to adrianf0:

This code compiles and you can simulate:

package common_params_pkg;
   parameter WIDTH_A = 4;
   parameter WIDTH_B = 6;
endpackage

package my_interface_pkd_hdl;
 import common_params_pkg::*;
//my_interface_pkg_hdl.sv
typedef struct{
 logic [WIDTH_A-1 : 0] a;
 logic [WIDTH_B-1 : 0] b;
} MY_STRUCT_T;
endpackage

interface my_if #(type MY_STRUCT_T)();
   tri MY_STRUCT_T my;
endinterface

interface my_monitor_bfm #(type MY_STRUCT_T)(my_if bus);
   tri MY_STRUCT_T my_i;
   assign my_i = bus.my;
endinterface

module hdl_top;
   import  my_interface_pkd_hdl::*;
   my_if #(MY_STRUCT_T) inf();
   my_monitor_bfm #(MY_STRUCT_T) monitor_bfm(inf);
endmodule