我试图基于其他一些对象来约束整个对象(而不仅仅是对象的字段)。这是我的生产代码的精简版:
我有以下课程:
class some_class;
bit[7:0] some_field;
bit[3:0] some_other_field;
// this function would do some complex procedural
// operations on the fields of the object
function void do_some_op();
bit[3:0] tmp = some_field[3:0];
some_field[3:0] = some_other_field;
some_other_field = some_field[7:4];
some_field[7:4] = tmp;
endfunction
function some_class some_function(bit some_param);
some_function = new this;
$display("foo"); // this print here to see that method is executed
if (some_param)
some_function.do_some_op();
endfunction
function void print();
$display("some_field = %x", some_field);
$display("some_other_field = %x", some_other_field);
endfunction
endclass // some_class
此类包含一些整数字段。它还有一个方法,可以在该类的字段上执行一些复杂的过程。在示例中,我简化了它。我还有另一个类,它返回一个已在其上执行操作的新对象。
我有另一个用some_class
个实例操作的类。根据Dave的输入,我首先创建了对象(因为randomize()
不创建对象)。
class some_shuffler;
rand bit params[];
rand some_class objects[];
constraint size_c {
params.size() == objects.size() - 1;
params.size() <= 10;
};
constraint shuffle_c {
// not allowed by standard
// foreach (params[i])
// objects[i+1].some_field == objects[i].some_function(params[i]);
foreach (params[i])
objects[i+1].some_field ==
objects[i].some_function(params[i]).some_field &&
objects[i+1].some_other_field ==
objects[i].some_function(params[i]).some_other_field;
};
function new();
objects = new[10]; // create more objects than needed
foreach (objects[i])
objects[i] = new();
// initialize first object
objects[0].some_field = 8'hA5;
endfunction // new
function void post_randomize();
foreach (objects[i]) begin
$display("objects[%0d]:", i);
objects[i].print();
$display("");
end
endfunction
endclass
这个类有两个数组,一个是执行的操作,另一个是中间状态。有一个初始对象。在这一个上,执行some_function
并导致下一个对象。
这就是我想测试它的方式:
module top;
import some_pkg::*;
initial begin
static some_shuffler shuffler = new();
bit rand_ok;
rand_ok = shuffler.randomize() with {
params.size() == 1;
};
assert (rand_ok);
end
endmodule
当试图直接约束对象时,我立即得到约束违规。模拟器似乎试图让2个手柄相等。这是标准禁止的,我不再这样做了(虽然编译失败本来不错)。我已经解开了Dave和Greg建议的约束(我认为做some_function().some_field
是非标准的,但它在Questa中编译)。
即使是现在,foo
打印也没有出现在命令行上(some_function()
未执行)。我看到objects[1]
包含初始值(两个字段都为0)。
我不能只生成参数列表,然后在程序上随机化每个迭代的对象,因为我希望能够将最后一个对象约束为具有某个值 - 基本上给出约束求解器的开始和结束点,并让它找到实现目标的方法。
答案 0 :(得分:4)
SystemVerilog中不允许使用对象约束,因为它们不是整数类型。见IEEE Std 1800-2012§18.3:
- 约束可以是包含变量和整数类型常量的任何SystemVerilog表达式(例如
bit
,reg
,logic
,integer
,enum
,{ {1}})。
如果组件是packed struct
(ex rand
),则可以约束类对象的整数组件。
约束允许使用函数,但存在限制。有关详细信息,请参阅IEEE Std 1800-2012§18.5.12约束中的函数。限制包括:
obj[1].value == obj[0].value+1;
或output
参数ref
推断x<=F(y)
)更新
看起来真正被随机化的唯一事情是solve y before x
。 params
和some_other_field some_field
post_randomize`函数的值。
are calculations. So it makes more sense to move the loop for shuffling into the
当至少有一个解决方案时,SystemVerilog的随机约束求解器将起作用。但是,当解决方案空间很小且难以确定或长链时,模拟器性能会下降。对于这些情况,最好将一对一顺序计算移动到constraint size_c {
params.size() == objects.size() - 1;
params.size() <= 10;
};
function void postrand_shuffle();
foreach (params[i])
objects[i+1] = objects[i].some_function(params[i]);
endfunction
function void post_randomize();
postrand_shuffle();
// ... your other post_rand code...
endfunction
。
答案 1 :(得分:3)
您的示例代码存在一些问题。
randomize()
之前必须先构造对象。如果
你知道调用随机化之前的确切大小(比如你的
例如),只需new[n]
构造每个对象的动态数组
元素首先,并删除大小约束。如果大小将是
随机,你需要一个大小的上限约束。构建最大值
调用randomize()之前的对象数,并且在随机化数组之后,将消除未使用的对象。objects[i+1].some_field == objects[i].some_field
但解算器无法操作类句柄。