从 SV 约束的动态范围中选择随机地址的方法

Way to pick random addresses from dynamic ranges in SV constraints

我需要从 Systemverilog 中的一组预定义范围中选择随机地址

program test;

int unsigned q[$], rSz;
typedef struct {
  int unsigned from, till;
} range_t;

initial begin
    range_t ranges[$];

    ranges.push_back('{from: 'h10, till: 'h1F});
    ranges.push_back('{from: 'h30, till: 'h3F});
    ranges.push_back('{from: 'h50, till: 'h5F});

    rSz = ranges.size();
    $displayh(rSz, ranges);

    repeat (10) begin
        std::randomize(q) with {
            q.size() inside {[4:8]};
            foreach (q[i]) {
                q[i] inside {[ranges[0].from: ranges[0].till]} ||
                q[i] inside {[ranges[1].from: ranges[1].till]} ||
                q[i] inside {[ranges[2].from: ranges[2].till]} ;
            }
        };
        $displayh(q);
    end
end

endprogram : test

如果我有固定数量的可以硬编码的范围,它就可以正常工作。 但是范围的数量本身是动态的,我不能像在 foreach 循环中那样对范围进行硬编码。

我不能使用 nested foreach,因为内部循环中的语句将被视为单独的约束并且由于范围不重叠而彼此失败。

我能想到的就是下面这样的东西,我按顺序使用范围,然后在最后洗牌。

program test;

int unsigned q[$], rSz;
typedef struct {
  int unsigned from, till;
} range_t;

initial begin
    range_t ranges[$];
    ranges.push_back('{from: 'h10, till: 'h1F});
    ranges.push_back('{from: 'h30, till: 'h3F});
    ranges.push_back('{from: 'h50, till: 'h5F});

    rSz = ranges.size();
    $displayh(rSz, ranges);

    repeat (10) begin
        std::randomize(q) with {
            q.size() inside {[4:8]};
            foreach (q[i]) {
                q[i] inside {[ranges[i % rSz].from: ranges[i % rSz].till]};
            }
        };
        q.shuffle();
        $displayh(q);
    end
end

endprogram : test

一般来说,有更好的方法吗?

我正在寻找类似 foreach-or 的东西,其中循环中的所有行都是 or-ed 而不是 and-ed - 如果这解释了要求。

大多数人都熟悉sum()数组缩减方法,但也有or()and()xor()缩减方法。

module test;
  int unsigned q[$], rSz;
  typedef struct {
    int unsigned from, till;
  } range_t;
  
  initial begin
    range_t ranges[$];

    ranges.push_back('{from: 'h10, till: 'h1F});
    ranges.push_back('{from: 'h30, till: 'h3F});
    ranges.push_back('{from: 'h50, till: 'h5F});

    rSz = ranges.size();
    $displayh(rSz,, ranges);

    repeat (10) begin
      assert(std::randomize(q) with {
        q.size() inside {[4:8]};
        foreach (q[i]) 
          ranges.or(range) with (q[i] inside {[range.from: range.till]});
      });
      $displayh(q);
    end
  end
endmodule: test

请参阅 IEEE 1800-2017 SystemVerilog LRM 中的 7.12.3 数组缩减方法 部分。