循环遍历约束中多维关联数组的较低维度的语法

Syntax for looping through lower dimension of multidimensional associative array in a constraint

class ns_data_struct;
  rand bit [63:0] ns_size = 64'h0000_0000_0000_0800;
endclass : ns_data_struct

class conf;
  ns_data_struct ns_data[];

  function new();
    ns_data = new[5];
    foreach (ns_data[i])
      ns_data[i] = new();
  endfunction
endclass : conf

class x;
  randc bit [63:0] slba;
  randc bit [63:0] nlb;
  bit [63:0] slba_previous [bit [31:0]][bit [63:0]];
  conf cfg;
  bit [31:0] nsid = 'h1;
  bit [63:0] num [bit [31:0]];

  constraint slba_nlb_inside_ns_c
  {
    slba inside {[1:cfg.ns_data[nsid-1].ns_size]};
    nlb inside {[0:(cfg.ns_data[nsid-1].ns_size - slba)]};
  }

  constraint slba_nlb_non_overlapping_c
  {
    foreach(slba_previous[nsid, i])
    {
      if(!(i%2))
      {
        slba < slba_previous[nsid][i] -> (slba + nlb) < slba_previous[nsid]  [i];
        slba > slba_previous[nsid][i] -> slba > slba_previous[nsid][i+1]; //  <-- Warning Here
        slba > slba_previous[nsid][i+1] -> (slba + nlb) >   slba_previous[nsid][i+1]; //  <-- Warning Here
        slba < slba_previous[nsid][i+1] -> slba < slba_previous[nsid][i]; //  <-- Warning Here
      }
    }
  }

  function void post_randomize();
    num[nsid] = (num.exists(nsid))?(num[nsid]):0;

    slba_previous[nsid][num[nsid]++] = slba;
    slba_previous[nsid][num[nsid]++] = (slba + nlb);

    $display("\nslba_previous - %p\n", slba_previous);
  endfunction

  function new (input conf _cfg);
    this.cfg = _cfg;
  endfunction: new
endclass : x

program p1;
  conf c;
  x t;

  initial
  begin
    c = new;
    t = new(c);
    t.nsid = 3;
    for(int i=0; i<15; i++)
    begin
      if(!t.randomize())
        $display("ERROR : Starting LBA & NLB Provider Randomization  Failed");
      $display("@%0t : KARAN, Starting LBA - %0h %0d", $time, t.slba, t.slba);
      $display("@%0t : KARAN, Number of LBA - %0h %0d", $time, t.nlb,  t.nlb);
    end
  end
endprogram

在这段代码中,我在 QuestaSIM 中遇到了 2 个问题。

  1. 在constraint中,我用了(i%2),还是显示这个警告:

    Warning : (vsim-3829) Non-existent associative array entry. Returning default value.

  2. 如何在约束中遍历二维关联数组的低维? foreach(slba_previous[, i]) 不工作。

在双关联数组上使用 foreach 时,您需要包括所有重要索引。否则循环无法确定要循环多少次for i。模拟器还需要处理 slba_previous[nsid] 不存在并且没有 i 索引的情况。

您需要遍历整个 slba_previous[id,i] 然后检查是否 id==nsid.

警告是针对 i+1 条件的。使用 .exists() 内置函数来确保存在现有的数组条目。设计可能总是有偶数个条目,但看起来 QuestaSIM 的约束求解器更悲观,想要考虑所有可能性。

constraint slba_nlb_non_overlapping_c
{
  foreach(slba_previous[id,i])
  {
    if(id==nsid && (i%2)==0)
    {
      slba < slba_previous[id][i] -> (slba + nlb) < slba_previous[id][i];
      if (slba_previous[id].exists(i+1))
      {
        slba > slba_previous[id][i] -> slba > slba_previous[id][i+1];
        slba > slba_previous[id][i+1] -> (slba + nlb) > slba_previous[id][i+1];
        slba < slba_previous[id][i+1] -> slba < slba_previous[id][i];
      }
    }
  }
}

EDA Playground

上的工作示例

警告可以通过修改class x来解决,如下,其中关联数组被拆分为2个数组。

class x;
  randc bit [63:0] slba;
  randc bit [63:0] nlb;
  bit [63:0] slba_previous_low [bit [31:0]][bit [63:0]];
  bit [63:0] slba_previous_high [bit [31:0]][bit [63:0]];
  conf cfg;
  bit [31:0] nsid = 'h1;
  bit [63:0] num [bit [31:0]];

  constraint slba_nlb_inside_ns_c
  {
    slba inside {[1:cfg.ns_data[nsid-1].ns_size]};
    nlb inside {[0:(cfg.ns_data[nsid-1].ns_size - slba)]};
  }

  constraint slba_nlb_non_overlapping_c
  {
    foreach(slba_previous_low[id, i])
    {
      if(id == nsid)
      {
        slba < slba_previous_low[id][i] -> (slba + nlb) < slba_previous_low[id]  [i];
        slba > slba_previous_low[id][i] -> slba > slba_previous_high[id][i];
        slba > slba_previous_high[id][i] -> (slba + nlb) >   slba_previous_high[id][i];
        slba < slba_previous_high[id][i] -> slba < slba_previous_low[id][i];
      }
    }
  }

  function void post_randomize();
    num[nsid] = (num.exists(nsid))?(num[nsid]):0;

    slba_previous_low[nsid][num[nsid]] = slba;
    slba_previous_high[nsid][num[nsid]] = (slba + nlb);

    num[nsid]++;

    $display("\nslba_previous_low - %p\n", slba_previous_low);
    $display("\nslba_previous_high - %p\n", slba_previous_high);
  endfunction

  function new (input conf _cfg);
    this.cfg = _cfg;
  endfunction: new
endclass : x