我有 Systemverilog 宏,用于对解压数据进行字节顺序感知解析:
此宏的目的是从字节数组中的 BYTE_OFFSET 偏移量中获取任何 BYTE_WIDTH 字节,并将它们打包到向量中。
我一直在运行较旧的 Modelsim 版本,没有出现任何问题。 最近,我将模拟器更新为 Questa Base 的更新版本,并开始收到此警告(对于调用该宏的文件),尽管功能是正确的。
是否有正确的方法将其编写为宏?
example.sv
):`define PARSE_LITTLE_ENDIAN(TARGET, SOURCE, BYTE_OFFSET, BYTE_WIDTH) \
TARGET = $size(TARGET)'({<<8{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}})
`define PARSE_BIG_ENDIAN(TARGET, SOURCE, BYTE_OFFSET, BYTE_WIDTH) \
TARGET = $size(TARGET)'({>>8{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}})
class my_parser;
bit [64-1:0] body_len;
logic[8-1:0] frame_buffer[];
function void call_macro();
this.frame_buffer = new[10];
for (int byte_idx = 0; byte_idx < this.frame_buffer.size(); byte_idx++)
begin
this.frame_buffer[byte_idx] = $urandom();
end
`PARSE_LITTLE_ENDIAN(this.body_len, this.frame_buffer, 2, 8);
`PARSE_BIG_ENDIAN(this.body_len, this.frame_buffer, 2, 8);
endfunction
endclass
vlog -sv example.sv
Questa Base Edition-64 vlog 2024.1 Compiler 2024.02 Feb 1 2024
Start time: 11:26:42 on Apr 10,2024
vlog -sv example.sv
-- Compiling package example_sv_unit
** Warning: example.sv(21): (vlog-2960) Streaming concatenation shall not be used as an operand in an expression without first casting it to a bit-stream type.
** Warning: example.sv(22): (vlog-2960) Streaming concatenation shall not be used as an operand in an expression without first casting it to a bit-stream type.
Top level modules:
--none--
End time: 11:26:42 on Apr 10,2024, Elapsed time: 0:00:00
Errors: 0, Warnings: 2
$cast(TARGET,{<<BYTE{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}})
给出相同的警告。
还有
TARGET = $size(TARGET)'($type(TARGET)'({<<BYTE{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}}))
或
TARGET = $type(TARGET)'($size(TARGET)'({<<BYTE{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}}))
出错。
我不确定您为什么会收到错误消息,但是您显示的代码不需要强制转换为大小,并且删除它可以消除警告消息。
这就是我所说的完整可运行示例的含义:
`define PARSE_LITTLE_ENDIAN(TARGET, SOURCE, BYTE_OFFSET, BYTE_WIDTH) \
TARGET = {<<8{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}}
`define PARSE_BIG_ENDIAN(TARGET, SOURCE, BYTE_OFFSET, BYTE_WIDTH) \
TARGET = {>>8{SOURCE[BYTE_OFFSET +: BYTE_WIDTH]}}
class my_parser;
bit [64-1:0] body_len;
logic[8-1:0] frame_buffer[];
function void call_macro();
this.frame_buffer = new[10];
void'(randomize(frame_buffer));
$displayh("%p",frame_buffer);
`PARSE_LITTLE_ENDIAN(this.body_len, this.frame_buffer, 2, 8);
$displayh(body_len);
`PARSE_BIG_ENDIAN(this.body_len, this.frame_buffer, 2, 8);
$displayh(body_len);
endfunction
endclass
module top;
my_parser p = new;
initial p.call_macro();
endmodule