【问题标题】:Syntax for looping through lower dimension of multidimensional associative array in a constraint在约束中循环遍历多维关联数组的低维的语法
【发布时间】:2015-07-23 13:04:54
【问题描述】:
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. 在约束中,我使用了 (i%2),但它仍然显示此警告:

    警告:(vsim-3829) 不存在的关联数组条目。返回默认值。

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

【问题讨论】:

    标签: system-verilog questasim


    【解决方案1】:

    可以通过修改类 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
    

    【讨论】:

      【解决方案2】:

      在双关联数组上使用foreach 时,您需要包含所有重要索引。否则循环无法确定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 上的工作示例

      【讨论】:

      • 它可能在 eda 上运行良好,但我仍然在 QuestaSIM 中收到上述警告
      • @MaheshShah,我用.exists(i+1) 更新了我的答案,这应该可以解决警告。
      • 是的,这可能会解决警告,但我的问题是为什么我们需要使用 exists 方法,如果我们使用了 (i%2),它确保只引用存在的条目(如 i =0 然后 0, 1, i=2 然后 2, 3)??
      • 在当前循环中,QuestaSIM 只知道i 的条目存在。 i+1 可能不存在(不是给出的代码,而是在所有可能的范围内:未来扩展类、测试台、交互模式、dpi/vpi 等)。第 18.5.8.1 节中的 LRM 表示“无效或超出范围的数组索引不会自动消除;用户必须使用谓词明确排除这些索引。”因此,QuestaSIM 通过从无效索引中识别 潜在 设计缺陷来落后于规范。
      • 不幸的是,我仍然收到这些警告,尽管为 (i+1) 编写了存在方法
      猜你喜欢
      • 2014-06-01
      • 1970-01-01
      • 2012-05-26
      • 2013-04-01
      相关资源
      最近更新 更多