Синтаксис для перебора нижнего измерения многомерного ассоциативного массива в ограничении

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.

  1. #P2# <блочная цитата> #P3#
  2. Как перебрать нижнее измерение в двумерном ассоциативном массиве в ограничении? foreach(slba_previous[, i]) не работает.


person Karan Shah    schedule 12.05.2015    source источник


Ответы (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

person Greg    schedule 12.05.2015
comment
Это может нормально работать на eda, но я все еще получаю вышеупомянутые предупреждения в QuestaSIM. - person Karan Shah; 13.05.2015
comment
@MaheshShah, я обновил свой ответ проверкой .exists(i+1), которая должна устранить предупреждение. - person Greg; 13.05.2015
comment
Да, это может устранить предупреждение, но мой вопрос заключается в том, почему мы требуем использовать метод exists, если мы использовали (i%2), который гарантирует, что будут ссылаться только на существующие записи (например, i=0, затем 0, 1, i =2, затем 2, 3)?? - person Karan Shah; 13.05.2015
comment
В текущем цикле QuestaSIM знает только, что запись для i существует. Вполне возможно, что i+1 может не существовать (не с предоставленным кодом, а в рамках всего возможного: класс будущего расширения, тестовый стенд, интерактивный режим, dpi/vpi и т.д.). LRM в разделе 18.5.8.1 говорит "Недействительно или не соответствует требованиям". индексы массива за границами не удаляются автоматически; пользователи должны явно исключать эти индексы с помощью предикатов. Таким образом, QuestaSIM отстает от спецификации, идентифицируя потенциальный недостаток дизайна по недействительным индексам. - person Greg; 13.05.2015
comment
К сожалению, я все еще получаю эти предупреждения, несмотря на то, что написал существующий метод для (i+1) - person Karan Shah; 14.05.2015
comment
Эту проблему можно решить, взяв 2 разных ассоциативных массива. Так что в ограничениях появится только я. не я+1 . Большое спасибо за помощь. - person Karan Shah; 14.05.2015
comment
Нет, ранее я писал, что это может решить предупреждение, но на самом деле предупреждения все еще были. Но я получил ответ. Вы можете проверить мой ответ ниже. - person Karan Shah; 14.05.2015

Предупреждение можно устранить, изменив класс 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
person Karan Shah    schedule 14.05.2015