SystemVerilog测试平台:创建运行时确定位宽的logic数组
解决SystemVerilog运行时动态位宽数据类的队列存储问题
由于SystemVerilog的类参数必须在编译时确定,无法直接在运行时根据变量值实例化参数化类,我们可以通过基类多态+子类参数化封装的方式实现需求,既保留子类内部的packed logic类型,又能统一存储到队列中。
核心思路
- 定义抽象基类,包含位宽元数据和纯虚方法,屏蔽具体位宽的操作细节;
- 参数化子类继承基类,内部维护固定位宽的packed logic数组,实现基类的虚方法来完成数据的读写、转换;
- 队列存储基类句柄,运行时通过虚方法自动适配不同位宽的子类实现。
代码实现
1. 定义抽象基类
基类仅声明必要的元数据和接口,不涉及具体数据存储:
class MyBaseData; int bit_depth; metadata_type_t some_info_about_thedata; // 纯虚方法:写入指定索引的数据(bit数组格式) pure virtual function void set_data(int index, bit[] data_bits); // 纯虚方法:读取指定索引的数据(返回bit数组) pure virtual function bit[] get_data(int index); // 纯虚方法:打印指定索引的数据(调试用) pure virtual function void print_data(int index); endclass
2. 实现参数化子类
子类根据编译时确定的位宽,维护packed logic数组,并实现基类的虚方法,完成bit数组与packed类型的转换:
class #(parameter BIT_DEPTH) MyData extends MyBaseData; logic [BIT_DEPTH-1:0] thedata []; function new(metadata_type_t md); super.bit_depth = BIT_DEPTH; super.some_info_about_thedata = md; this.thedata = new[md.thedatasize]; // 初始化动态数组长度 endfunction virtual function void set_data(int index, bit[] data_bits); if(data_bits.size() != BIT_DEPTH) begin $error("[MyData#%0d] Data width mismatch: expected %0d bits, got %0d", BIT_DEPTH, BIT_DEPTH, data_bits.size()); return; end // 将bit数组赋值给packed logic变量 for(int i=0; i<BIT_DEPTH; i++) begin thedata[index][i] = data_bits[i]; end endfunction virtual function bit[] get_data(int index); bit[] data_bits = new[BIT_DEPTH]; // 将packed logic变量转换为bit数组 for(int i=0; i<BIT_DEPTH; i++) begin data_bits[i] = thedata[index][i]; end return data_bits; endfunction virtual function void print_data(int index); $display("[MyData#%0d] Index %0d: %0b", BIT_DEPTH, index, thedata[index]); endfunction endclass
3. 队列存储与使用
队列存储基类句柄,运行时无需关心具体子类的位宽,直接通过虚方法操作数据:
// 定义存储基类句柄的队列 MyBaseData data_queue[$]; // 实例化不同位宽的子类并加入队列(编译时确定每个子类的BIT_DEPTH) metadata_type_t md_8bit = '{thedatasize: 4}; // 假设元数据包含数组长度 metadata_type_t md_16bit = '{thedatasize: 2}; metadata_type_t md_24bit = '{thedatasize: 3}; data_queue.push_back(new MyData#(8)(md_8bit)); data_queue.push_back(new MyData#(16)(md_16bit)); data_queue.push_back(new MyData#(24)(md_24bit)); // 遍历队列操作数据 while(data_queue.size() > 0) begin MyBaseData mbd = data_queue.pop_front(); // 读取并打印数据 mbd.print_data(0); // 构造新数据并写入 bit[] new_data = new[mbd.bit_depth]; foreach(new_data[i]) new_data[i] = $random(); // 生成随机bit数据 mbd.set_data(0, new_data); // 打印修改后的数据 mbd.print_data(0); end
方案优势
- 子类内部保留了
logic [BIT_DEPTH-1:0]的packed类型,符合原始需求; - 基类多态实现了位宽无关的操作,队列存储无需关注具体位宽;
- 所有位宽相关的逻辑被封装在子类中,代码模块化且易维护;
- 完全适配测试平台场景,无需考虑可综合性。
内容的提问来源于stack exchange,提问作者John M
相关产品推荐
相关产品推荐

