使用 类 和虚拟接口时导致 'interface resolution' 编译错误的原因
What causes 'interface resolution' compilation error when working with classes and virtual 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
并且在一个包中 classes 使用这些接口:
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
我在测试台上把所有东西粘在一起,只使用包中的 clock_generator class:
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
现在,当我尝试编译这样的示例时,它失败了 Virtual interface resolution cannot find a matching instance for 'virtual t_bst.producer'
我花了很长时间才发现,如果我在 testbench 模块中也实例化 t_bst 接口(取消注释上面代码中的 t_bst 行),一切都会顺利进行,没有编译错误,测试台照常通过。
我不明白为什么必须实例化t_bst接口,因为它根本没有在代码中使用。确实,我正在导入整个 clspkg 包,但是当我通过 import clspkg::clock_generator
.
仅导入 clock_generator 来挑选时,没有任何变化
怎么了?我正在使用 Mentor Modelsim
来自 SV LRM(25.9 虚拟接口):
- 虚拟接口是一个代表接口实例的变量。
- 在引用虚拟接口的组件之前,应先初始化虚拟接口; 它在初始化之前的值为null。尝试使用空虚拟接口将导致致命的 运行 时间错误.
我希望它能回答你的问题。
首先关于使用包:
一旦您 import
设计中 package
中的一个标识符或每个标识符,整个 package
存在于您的设计中 。这意味着所有静态变量都得到分配和初始化,以及任务和函数的所有代码都得到生成。如果静态变量初始化调用 class 构造函数之类的函数,则意味着在不直接引用它的情况下执行过程代码。 (对于那些熟悉 factory design pattern and UVM 的人来说,这正是工厂注册的工作方式。)
接下来关于使用接口:
与 module
一样,interface
是一个包含许多不同事物定义的设计元素。它们可以定义变量、例程、导入其他包并具有端口连接。但是在其他设计单元实例化它之前,接口 不存在 或在设计中生成任何代码,或者在模块的情况下,被建立为顶级实例。
现在关于使用虚拟接口:
虚拟接口是用于桥接基于动态 class 测试台世界的 two kingdoms 与基于静态实例的设计世界的主要方法。虚拟接口的行为很像 class 类型,除了在代码中使用它之前没有规则必须看到接口的定义。分层引用还具有引用在编译时不存在但必须在编译的细化阶段稍后解决的内容的能力。
总而言之,编译器一旦看到对它的引用,就会为虚拟接口生成代码,无论您是否真的认为自己正在使用它。我会尝试将包与它们关联的特定接口对齐。
我在设计文件中声明了以下接口:
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
并且在一个包中 classes 使用这些接口:
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
我在测试台上把所有东西粘在一起,只使用包中的 clock_generator class:
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
现在,当我尝试编译这样的示例时,它失败了 Virtual interface resolution cannot find a matching instance for 'virtual t_bst.producer'
我花了很长时间才发现,如果我在 testbench 模块中也实例化 t_bst 接口(取消注释上面代码中的 t_bst 行),一切都会顺利进行,没有编译错误,测试台照常通过。
我不明白为什么必须实例化t_bst接口,因为它根本没有在代码中使用。确实,我正在导入整个 clspkg 包,但是当我通过 import clspkg::clock_generator
.
怎么了?我正在使用 Mentor Modelsim
来自 SV LRM(25.9 虚拟接口):
- 虚拟接口是一个代表接口实例的变量。
- 在引用虚拟接口的组件之前,应先初始化虚拟接口; 它在初始化之前的值为null。尝试使用空虚拟接口将导致致命的 运行 时间错误.
我希望它能回答你的问题。
首先关于使用包:
一旦您 import
设计中 package
中的一个标识符或每个标识符,整个 package
存在于您的设计中 。这意味着所有静态变量都得到分配和初始化,以及任务和函数的所有代码都得到生成。如果静态变量初始化调用 class 构造函数之类的函数,则意味着在不直接引用它的情况下执行过程代码。 (对于那些熟悉 factory design pattern and UVM 的人来说,这正是工厂注册的工作方式。)
接下来关于使用接口:
与 module
一样,interface
是一个包含许多不同事物定义的设计元素。它们可以定义变量、例程、导入其他包并具有端口连接。但是在其他设计单元实例化它之前,接口 不存在 或在设计中生成任何代码,或者在模块的情况下,被建立为顶级实例。
现在关于使用虚拟接口:
虚拟接口是用于桥接基于动态 class 测试台世界的 two kingdoms 与基于静态实例的设计世界的主要方法。虚拟接口的行为很像 class 类型,除了在代码中使用它之前没有规则必须看到接口的定义。分层引用还具有引用在编译时不存在但必须在编译的细化阶段稍后解决的内容的能力。
总而言之,编译器一旦看到对它的引用,就会为虚拟接口生成代码,无论您是否真的认为自己正在使用它。我会尝试将包与它们关联的特定接口对齐。