参数化 uvm 序列项调整大小

Parametrized uvm sequence item to adjust size

我有一个问题,我不知道如何解决它。我有一个 class,其中包含一个名为 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 的基 class,然后 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

您可能已经猜到了,这没有用。我的数据数组只有一点宽,我猜它是从基数 class 中获取的,因此多态性对变量的作用与对函数的作用不同(除非我在这里遗漏了一些关键信息)。

现在在 MyItemBase class 中拥有单位版本的数据会导致编译错误,除非我强制转换为派生类型。这会导致一些额外的复杂性,我觉得我在解决一个简单的问题时难以理解。

任何人都可以给我任何关于如何构建它的建议吗? 谢谢

我的建议是创建一个二维动态数组。由于您似乎正在使用字节宽度,您可以这样做:

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

那么可以构造第二个维度

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

如果您需要使用压缩数组,您可以声明一个具有最大宽度的局部变量,并将数据字节流式传输到局部变量from/to;

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