限制数组元素总数小于预定值

Constrain total number of array elements less than predetermined value

我正在尝试创建一个数组,该数组的数组元素总数小于给定值。比如我想生成一个随机数组,其中小于4的元素总数不超过6,我的实现方式是:

function automatic int get_small_vals(input bit [3 : 0] bit_vector [64]);
    automatic bit [3 : 0] q [$];
    q = bit_vector.find(x) with (x < 4'd4);
    return q.size();
endfunction

class InputData;
    rand bit [3 : 0] abs_vals [64];
    constraint no_more_than_p_small_values {
        get_small_vals(abs_vals) < 6;
    }
    function void display();
        foreach (abs_vals[i]) $write("%1h", abs_vals[i]);
        $write("\n");
    endfunction
endclass

initial begin
    InputData rels;
    rels = new();
    rels.randomize();
    rels.display();
    #100;
    $stop;
end

我在控制台(Vivado 2018.3 64bit)看到有超过6个值小于4:

WARNING: File: C:/my_path/unit_tb.sv Line: 69 : randomize failed to meet constraint.
902ed8fb3af155c14a5402c092709a999d7f0b2adbd6e7d6d698a7d5c2b5baa7

我不明白这是什么问题。它适用于 'equal',但不适用于 'less than':

function automatic int get_small_vals(input bit [3 : 0] bit_vector [64]);
    automatic bit [3 : 0] q [$];
    q = bit_vector.find(x) with (x == 4'd4);
    return q.size();
endfunction

一种方法是使用随机索引变量,遍历数组,然后 shuffle post_randomize 函数中的数组。

module tb;

class InputData;
    rand bit [3:0] abs_vals [64];
    rand int unsigned idx;
    localparam THRESH = 4;
    constraint no_more_than_p_small_values {
        idx < 6;
        foreach (abs_vals[i]) {
            if (i < idx) 
                abs_vals[i] < THRESH;
            else
                abs_vals[i] >= THRESH;
        }
    }
    function void display();
        foreach (abs_vals[i]) $write("%1h", abs_vals[i]);
        foreach (abs_vals[i]) if (abs_vals[i]<THRESH) $write(" %1h", abs_vals[i]);
        $display;
    endfunction
    function void post_randomize;
        abs_vals.shuffle();
    endfunction 
endclass

initial begin
    InputData rels;
    rels = new();
    repeat (15) begin
        rels.randomize();
        rels.display();
    end
end

endmodule

在 Cadence 模拟器上的一次试验 运行 的输出:

fe8b85589a6b5ac8f7ee8e48c5b4fba89e7ffb94baf8e8905dba7bf9675af698 0
26ebf35865cc6c096e05ccb76a746e546fcfc8e8d5da784b86e94dfecdfd98b3 2 3 0 0 3
78cc6c7e450f9e5857a2dea77ade849d7e847369d698accdc27a4d8fcccc5d8b 0 2 3 2
896cff444cfdf6fadc094716bc4a68ba34e9defc84e554abbea7e8e9885afa80 0 1 3 0
f7869fb6c7b8ae4cf58fae67f9b7f77c76caf8c8a84eea65de664d668e65eb75
ea167f8f1caf8b9f9cfa74f3da86a5c486dcf9c9c5fb9b98e6b5a5fd46b56c9c 1 1 3
5cb785a59cc69a79fe9b57c6e00837b68c7f857dea91bd76eb7c4cb87c46a868 0 0 3 1
7c9fe7884855df5b484ef4baf4eb5465c8ca8738888b82af74d6c97a9ab56698 3 2
ac6c7aa95b5cac69d7faabe8c6ade8f69458173eae4acddcb9672ba418e7fbb5 1 3 2 1
c6eccbc0dfadeb9ba8656eea896f4dffeeccecdfd7d96e988ac84dfd88cacad8 0
ec9bafeb9069e8cbd5ab89459487aa9fbe0686fc25c68af89eef94bcfa79b4bf 0 0 2
a4b8ee7d68cefe087ea85b57aafbe79689c7a9faa98b8826c69758bc74eaeafa 0 2
fee6fff69e3ba495edb15ee5b79d95e54cc88f49e64998952effffdc74f4b69a 3 1 2
a5ed75bfbc548dcfd67d186d74e8657d4a8cd644a28ddaffda97bc8beaf68b97 1 2
56e6f799b45fc6af696479fd67aacd62d2ec4f67bb5e25b1b8ab97455695aaab 2 2 2 1

在约束中调用用户定义的函数会产生问题,因为输入参数(在本例中为 abs_vals)的值在调用函数 之前被选取,并且函数的输出被视为非随机状态值。这意味着如果为 abs_vals 选择的值不满足约束 no_more_than_p_small_values,对 randomize 的调用将失败,并且不会尝试找到另一组值来满足约束。前几次调用它可能不会失败,这只是运气问题。

你应该做的是尝试像 array.sum() 这样的内置迭代方法,它不会遇到这个排序问题。

class InputData;
    rand bit [3 : 0] abs_vals [64];
    constraint no_more_than_p_small_values {
        abs_vals.sum() with (int'(item<4)) <= 6;
    }
    function void display();
        foreach (abs_vals[i]) $write("%1h", abs_vals[i]);
        $write("\n");
    endfunction
endclass