Параметризованный элемент последовательности uvm для настройки размера - PullRequest
0 голосов
/ 13 марта 2019

У меня есть проблема, и у меня нет идей, как ее решить. У меня есть класс, который содержит массив с именем data. Этот динамический массив может иметь параметризованную упакованную ширину - например, 8, 16 или 32 бита.

class MyItem#(int WIDTH=8) extends uvm_sequence_item;

  bit[WIDTH-1:0] data[];

endclass

Проблема в том, что когда я хочу создать экземпляр объекта MyItem, мне нужно предоставить ему параметр. Параметр WIDTH, однако, зависит от некоторых других настроек, и для цели примера можно предположить, что он может генерироваться случайным образом в диапазоне от 8,16 до 32.

class MySequence extends uvm_sequence;

  rand int width;
  constraint c_width {width inside {8, 16, 32}; }

  task body();
    MyItem#(width) req = MyItem#(width)::type_id::create("item"); // <--- THIS IS NOT ALLOWED
  endtask

endclass

Так что мне пришлось придумать способ обойти это. Один из способов - создать дескриптор внутри MyItem для всех значений ширины, а затем использовать тот, который мне нужен. Что-то с эффектом:

class MyItem extends uvm_sequence_item;
  bit[ 7:0] data_08[];
  bit[15:0] data_16[];
  bit[23:0] data_24[];
endclass

Это позволило бы мне использовать ручку в зависимости от размера упаковки. Но это немного глупо, и я бы предпочел избегать этого, поскольку мне приходится постоянно проверять параметр WIDTH и обращаться к данным data_08, data_16 или data_24, которые раздувают код.

Другой вариант - просто использовать параметр MAX_WIDTH и дополнить биты.

class MyItem extends uvm_sequence_item;
  bit[MAX_WIDTH:0] data[];
endclass

Но для очень больших массивов это пустая трата памяти и неэффективно.

Последнее решение, которое я придумала, но не работает, - это создание базового класса с именем MyItemBase, и затем Item расширяется. Так что теперь я могу (или, скорее, должен иметь) доступ к данным как просто obj_handle.data

class MyItemBase extends uvm_sequence_item;
  bit data[];
endclass

class MyItem#(WIDTH) extends MyItemBase;
  bit[WIDTH-1:0] data[];
endclass

Это позволяет мне использовать следующий код в моей последовательности:

  rand int width;
  constraint c_width {width inside {8, 16, 32}; }

  task body();
    MyItemBase req
    case(width)
      8:  req = MyItem#(8)::type_id::create("item");
      16: req = MyItem#(8)::type_id::create("item");
      32: req = MyItem#(8)::type_id::create("item");
      default: //
    endcase

    // Now I should be able to use req.data
    req.data = new[32];
    foreach(req.data[i]) req.data[i] = $urandom();
    foreach(req.data[i]) $display("data[%0d] = %0x",  i, data[i]);
  endtask

endclass

Как вы уже догадались, это не сработало. Мой массив данных имеет ширину всего лишь один бит, и я предполагаю, что он получает его из базового класса, поэтому полиморфизм не работает для переменных так же, как для функций (если я не пропустил здесь что-то ключевое).

Теперь наличие однобитовой версии данных в классе MyItemBase вызывает ошибки компиляции, если я не приведу к производному типу. Это вызывает некоторую дополнительную сложность, и я чувствую, что перебиваю себе голову над простой проблемой.

Может кто-нибудь дать мне какие-нибудь предложения о том, как это структурировать? Спасибо

1 Ответ

2 голосов
/ 13 марта 2019

Я предлагаю создать двумерный динамический массив. Поскольку вы, кажется, работаете с шириной байтов, вы можете сделать:

bit[7:0] data[][];

Тогда второе измерение можно построить с помощью

   foreach(data[I]) data[I]= new[width/8];

Если вам нужно работать с упакованным массивом, вы можете объявить локальную переменную с максимальной шириной и передать байты данных из / в локальную переменную;

bit [MAX_WIDTH-1:0] temp;
...
temp = {<<{data[I]}};
...