请务必了解我在尝试自定义sequence_library的“select_sequence”时遇到的一个问题。 所以我需要自定义“select_sequence”并使我的序列按照确切的顺序运行,这是在外部文件中编写的。 出于这个原因,我踩着所有已注册序列类型的容器:序列[$]。并做动态铸造。如果转换与我需要的序列匹配,我从select_sequence函数返回数字,即使库运行序列。
这是我的代码中的部分:
class cfgSeqncLib extends uvm_sequence_library #(seqItem_cfg);
`uvm_object_utils(cfgSeqncLib)
`uvm_sequence_library_utils(cfgSeqncLib)
rstSeqnc resetSequence;
function int unsigned select_sequence(int unsigned max);
static int unsigned counter;
select_sequence = counter;
counter++;
if (counter > max)
counter = 0;
foreach (sequences[i])
begin
if ($cast(resetSequence, sequences[i]) )
$display("%t: <><><>><>< ResetSeq: Casting IS Successfull", $time);
else
$display("%t: >>>>>>>>ResetSeq: Casting is NOT Successfull", $time);
end // foreach
endfunction
endclass
我使用以下命令在库中添加了重置序列:`uvm_add_to_seq_lib(rstSeqnc,cfgSeqncLib)命令。
问题是$ case永远不会返回1,即在模拟期间它始终打印 \&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; ResetSeq:投放不成功
即使我可以看到sequence_lib正在运行重置序列,但从不转换返回true。 你能解释一下原因吗?
如果使用UVM代码,我将select_sequence
函数更改为以下,而不是转换:
function int unsigned select_sequence(int unsigned max);
static int unsigned counter;
uvm_object_wrapper wrap;
uvm_object obj;
select_sequence = counter;
counter++;
if (counter > max)
counter = 0;
foreach (sequences[i])
begin
wrap = sequences[i];
obj = factory.create_object_by_type(wrap,get_full_name(),
$sformatf("%s:%0d",wrap.get_type_name(),sequences_executed+1));
if ($cast(resetSequence, obj) )
$display("%t: !!!!!!! ResetSeq: Casting IS Successfull", $time);
else
$display("%t: >>>>>>>>ResetSeq: Casting is NOT Successfull", $time);
end // foreach
endfunction
在Simulaiton期间,我得到了:
!!!!!!! ResetSeq: Casting IS Successfull
我无法理解为什么在select_sequence的第一个版本中进行投射不起作用,但在第二个案例中它可以正常工作。有人可以向我解释一下。
答案 0 :(得分:0)
使用宏uvm_add_to_seq_lib
将序列添加到库中[`uvm_add_to_seq_lib(rstSeqnc,cfgSeqncLib)]让我们觉得它将序列的实例添加到序列库和此实例中的数组中可以在以后的序列库中使用。
但事实并非如此,并且像uvm中常用的样式一样,宏正在添加uvm_object_registry
类型的对象。在uvm_object_utils
宏[uvm_object_registry#(T,"S
“)type_id;]中,每个类(静态地)创建一个该对象。
此工具在工厂类/机制中用于创建和使用对象的轻量级包装器(uvm_object_registry)。这确保了uvm框架在实际需要之前不会创建完整的类。该类的实例仅在调用type_id :: create函数(或其他工厂创建函数)时创建。
因此情况1中的$cast(resetSequence, sequences[i])
实际上是在尝试将resetSequence [uvm_object_registry#(resetSequence,“resetSequence”)]类型的object_wrap强制转换为失败的resetSequence。
resetSequence != uvm_object_registry#(resetSequence,"resetSequence")
检查宏本身,我们可以看到它没有添加TYPE(sequence)的实例,而是调用get_type函数,它返回一个对象包装器。
`define uvm_add_to_seq_lib(TYPE,LIBTYPE) \
static bit add_``TYPE``_to_seq_lib_``LIBTYPE =\
LIBTYPE::m_add_typewide_sequence(TYPE::get_type());
同样检查下面的代码(案例2)我们可以看到它使用工厂机制来创建类的实例。这样可以确保环境中的任何类型覆盖都能正常工作,然后序列库将使用序列库中已注册序列的新序列。在示例1中,这样的情况是不可能的,因为它试图直接使用类的实例[即使代码被修复]。案例2具有优势。
wrap = sequences[i];
obj = factory.create_object_by_type(wrap,get_full_name(),
$sformatf("%s:%0d",wrap.get_type_name(),sequences_executed+1));
if ($cast(resetSequence, obj) )