我遇到了一个问题,但对解决该问题没有任何想法。我有一个包含名为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
这将允许我根据包装尺寸使用手柄。但这有点hacky,我宁愿避免这种情况,因为我必须继续检查WIDTH参数并分别访问data_08,data_16或data_24,这会使代码the肿。
另一种选择是只使用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类中的数据只有一位版本会导致编译错误。这会带来一些额外的复杂性,我觉得我在解决一个简单的问题上不知所措。
任何人都可以给我有关如何构建此结构的建议吗? 谢谢
答案 0 :(得分:2)
我建议创建一个二维动态数组。由于您似乎正在使用字节宽度,因此可以:
bit[7:0] data[][];
那么第二维可以用
构造 foreach(data[I]) data[I]= new[width/8];
如果需要使用压缩数组,则可以声明一个最大宽度的局部变量,然后将数据字节从该局部变量传输到该局部变量;
bit [MAX_WIDTH-1:0] temp;
...
temp = {<<{data[I]}};