参数化 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]}};
我有一个问题,我不知道如何解决它。我有一个 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]}};