有什么方法可以知道一个成员是否在 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 成员并将引用对象传递给它,以便您可以强制执行适当的封装。