有什么方法可以知道一个成员是否在 SV 的 class 中被声明为随机的
Is there any method to know whether a member is declared random or not in a class in SV
// Current Class
class x;
rand int a;
int b; // b is nonrandom as of now
function new();
endfunction
function abc;
// if a != ref.a, where ref is reference object of class x, declared somewhere else
a.rand_mode(0);
endfunciton
// Future Possible Class
class x;
rand int a;
rand int b; // b is also a random variable now
function new();
endfunction
function abc;
// if a != ref.a, where ref is reference object of class x, declared somewhere else
a.rand_mode(0);
// if b != ref.b, where ref is reference object of class x, declared somewhere else
b.rand_mode(0);
endfunciton
因此在函数 abc 中,根据 rand 成员值是否与引用 class 中该成员的值匹配或不匹配,rand 声明的 class x 成员应该相应地激活或不激活。
目的 - 我需要检查 rand 变量是否与引用 class 值匹配,然后只应将其随机化,否则不进行随机化。
我想概括方法 abc,用于所有可能的未来变化(因此我不需要修改它,如上例所示),而且我不知道,当 class 成员可能成为 rand 或非 rand 成员,是否有任何内置方法可以知道 class 的成员是否在 class 中声明为 rand?
这是不可能的,因为 SystemVerilog 不提供任何反射功能。您可能可以使用 VPI 解决这个问题,但我不确定 类.
的 VPI 实现有多完整
根据你想做的事情,我想说无论如何实现这样的查询是没有意义的,只是为了将来验证你的代码,以防某些字段有一天会变成 rand
。正如将 rand
修饰符添加到字段中一样,您也可以将其添加到应禁用随机化的字段列表中。两个代码位置都位于同一个文件中,因此很难错过。
某个模拟器在查询状态变量的 rand_mode()
时会 return -1
,但这是非标准的。 LRM 明确指出在非随机字段上调用 rand_mode()
是一个编译错误。
你可以稍微改变一下你对这个问题的看法。与其尝试禁用已声明字段的随机化 rand
,为什么不说当它们被随机化时,它们应该保持其值?
根据这个很好的 post,SV 2012 中有一个新的构造,const'(...)
可以在这种情况下使用。不幸的是,我认为没有很多供应商支持它。您的 randomize()
调用将如下所示:
if (!rand_obj.randomize() with {
const'(a) != ref_obj.a -> a == const'(a);
})
$fatal(0, "rand error");
让我们剖析这段代码。 const(a)
将在进行任何类型的随机化之前对 a
的值进行采样。如果 a
在随机化之前的值不等于参考值,那么我们有约束的第二部分说 a
应该保持它的值。我已经在两个模拟器上尝试过这段代码,但两者都不支持(尽管它应该是合法的 SV 2012 语法)。也许你很幸运有一个支持它的供应商。
您甚至可以为状态变量编写此类约束,因为它们仍然有效。
如果您无法在您的模拟器中使用 const
语法,那么同样的 post 会告诉您如何解决该问题。您可以将随机化之前的值存储在对象内并在约束中使用它们:
class some_class;
rand bit [2:0] a;
bit [2:0] b;
bit [2:0] pre_rand_a;
bit [2:0] pre_rand_b;
function void pre_randomize();
pre_rand_a = a;
pre_rand_b = b;
endfunction
endclass
当你想随机化时,你会添加以下约束:
if (!rand_obj.randomize() with {
pre_rand_a != ref_obj.a -> a == pre_rand_a;
pre_rand_b != ref_obj.b -> b == pre_rand_b;
})
$fatal(0, "rand error");
您可以在 EDAPlayground 上找到完整示例。
您提到执行随机化的函数是在对象外部定义的。因此,pre_rand_*
字段不能是 local/protected,这不是很好。您应该考虑使该函数成为 class 成员并将引用对象传递给它,以便您可以强制执行适当的封装。
// Current Class
class x;
rand int a;
int b; // b is nonrandom as of now
function new();
endfunction
function abc;
// if a != ref.a, where ref is reference object of class x, declared somewhere else
a.rand_mode(0);
endfunciton
// Future Possible Class
class x;
rand int a;
rand int b; // b is also a random variable now
function new();
endfunction
function abc;
// if a != ref.a, where ref is reference object of class x, declared somewhere else
a.rand_mode(0);
// if b != ref.b, where ref is reference object of class x, declared somewhere else
b.rand_mode(0);
endfunciton
因此在函数 abc 中,根据 rand 成员值是否与引用 class 中该成员的值匹配或不匹配,rand 声明的 class x 成员应该相应地激活或不激活。
目的 - 我需要检查 rand 变量是否与引用 class 值匹配,然后只应将其随机化,否则不进行随机化。
我想概括方法 abc,用于所有可能的未来变化(因此我不需要修改它,如上例所示),而且我不知道,当 class 成员可能成为 rand 或非 rand 成员,是否有任何内置方法可以知道 class 的成员是否在 class 中声明为 rand?
这是不可能的,因为 SystemVerilog 不提供任何反射功能。您可能可以使用 VPI 解决这个问题,但我不确定 类.
的 VPI 实现有多完整根据你想做的事情,我想说无论如何实现这样的查询是没有意义的,只是为了将来验证你的代码,以防某些字段有一天会变成 rand
。正如将 rand
修饰符添加到字段中一样,您也可以将其添加到应禁用随机化的字段列表中。两个代码位置都位于同一个文件中,因此很难错过。
某个模拟器在查询状态变量的 rand_mode()
时会 return -1
,但这是非标准的。 LRM 明确指出在非随机字段上调用 rand_mode()
是一个编译错误。
你可以稍微改变一下你对这个问题的看法。与其尝试禁用已声明字段的随机化 rand
,为什么不说当它们被随机化时,它们应该保持其值?
根据这个很好的 post,SV 2012 中有一个新的构造,const'(...)
可以在这种情况下使用。不幸的是,我认为没有很多供应商支持它。您的 randomize()
调用将如下所示:
if (!rand_obj.randomize() with {
const'(a) != ref_obj.a -> a == const'(a);
})
$fatal(0, "rand error");
让我们剖析这段代码。 const(a)
将在进行任何类型的随机化之前对 a
的值进行采样。如果 a
在随机化之前的值不等于参考值,那么我们有约束的第二部分说 a
应该保持它的值。我已经在两个模拟器上尝试过这段代码,但两者都不支持(尽管它应该是合法的 SV 2012 语法)。也许你很幸运有一个支持它的供应商。
您甚至可以为状态变量编写此类约束,因为它们仍然有效。
如果您无法在您的模拟器中使用 const
语法,那么同样的 post 会告诉您如何解决该问题。您可以将随机化之前的值存储在对象内并在约束中使用它们:
class some_class;
rand bit [2:0] a;
bit [2:0] b;
bit [2:0] pre_rand_a;
bit [2:0] pre_rand_b;
function void pre_randomize();
pre_rand_a = a;
pre_rand_b = b;
endfunction
endclass
当你想随机化时,你会添加以下约束:
if (!rand_obj.randomize() with {
pre_rand_a != ref_obj.a -> a == pre_rand_a;
pre_rand_b != ref_obj.b -> b == pre_rand_b;
})
$fatal(0, "rand error");
您可以在 EDAPlayground 上找到完整示例。
您提到执行随机化的函数是在对象外部定义的。因此,pre_rand_*
字段不能是 local/protected,这不是很好。您应该考虑使该函数成为 class 成员并将引用对象传递给它,以便您可以强制执行适当的封装。