-
Notifications
You must be signed in to change notification settings - Fork 57
Description
Hello!
I'm creating a regblock that we'll be using for both VCS and Verilator. With the axi4-lite cpuif, there is an issue on the Verilator side of things. I get this error output when trying to compile it with Verilator v5.044:
%Error-BLKLOOPINIT: regs.sv:175:65: Unsupported: Non-blocking assignment to array with compound element type inside loop
175 | axil_resp_buffer[axil_resp_wptr[0:0]].is_wr <= '0;
| ^~
... For error description see https://verilator.org/warn/BLKLOOPINIT?v=5.044
%Error-BLKLOOPINIT: regs.sv:176:63: Unsupported: Non-blocking assignment to array with compound element type inside loop
176 | axil_resp_buffer[axil_resp_wptr[0:0]].err <= cpuif_rd_err;
| ^~
%Error-BLKLOOPINIT: regs.sv:177:65: Unsupported: Non-blocking assignment to array with compound element type inside loop
177 | axil_resp_buffer[axil_resp_wptr[0:0]].rdata <= cpuif_rd_data;
| ^~
%Error-BLKLOOPINIT: regs.sv:180:65: Unsupported: Non-blocking assignment to array with compound element type inside loop
180 | axil_resp_buffer[axil_resp_wptr[0:0]].is_wr <= '1;
| ^~
%Error-BLKLOOPINIT: regs.sv:181:63: Unsupported: Non-blocking assignment to array with compound element type inside loop
181 | axil_resp_buffer[axil_resp_wptr[0:0]].err <= cpuif_wr_err;
| ^~
%Error-BLKLOOPINIT: regs.sv:165:43: Unsupported: Non-blocking assignment to array with compound element type inside loop
165 | axil_resp_buffer[i].is_wr <= '0;
| ^~
%Error-BLKLOOPINIT: regs.sv:166:41: Unsupported: Non-blocking assignment to array with compound element type inside loop
166 | axil_resp_buffer[i].err <= '0;
| ^~
%Error-BLKLOOPINIT: regs.sv:167:43: Unsupported: Non-blocking assignment to array with compound element type inside loop
167 | axil_resp_buffer[i].rdata <= '0;
| ^~The command I used to produce the verilog file is:
peakrdl regblock test_registers.rdl top.rdl -o verilog --cpuif axi4-lite-flat --peakrdl-cfg peakrdl.toml
I'm running a virtual environment with the following requirements.txt:
antlr4-python3-runtime==4.13.2
colorama==0.4.6
git-me-the-url==2.2.0
gitdb==4.0.12
GitPython==3.1.46
Jinja2==3.1.6
Markdown==3.10.2
MarkupSafe==3.0.3
peakrdl==1.5.0
peakrdl-cheader==1.0.0
peakrdl-html==2.12.1
peakrdl-ipxact==3.5.0
peakrdl-python==2.3.0
peakrdl-regblock==1.2.0
peakrdl-systemrdl==1.0.1
peakrdl-uvm==2.4.0
peakrdl_markdown==1.0.3
py-markdown-table==1.3.0
Pygments==2.19.2
python-markdown-math==0.9
smmap==5.0.2
systemrdl-compiler==1.32.1
The culprit is this section of code in cpuif/axi4lite/axi4lite_tmpl.sv:
struct {
logic is_wr;
logic err;
logic [{{cpuif.data_width-1}}:0] rdata;
} axil_resp_buffer[{{roundup_pow2(cpuif.resp_buffer_size)}}];
{%- if not is_pow2(cpuif.resp_buffer_size) %}
// axil_resp_buffer is intentionally padded to the next power of two despite
// only requiring {{cpuif.resp_buffer_size}} entries.
// This is to avoid quirks in some tools that cannot handle indexing into a non-power-of-2 array.
// Unused entries are expected to be optimized away
{% endif %}
logic [{{clog2(cpuif.resp_buffer_size)}}:0] axil_resp_wptr;
logic [{{clog2(cpuif.resp_buffer_size)}}:0] axil_resp_rptr;
always_ff {{get_always_ff_event(cpuif.reset)}} begin
if({{get_resetsignal(cpuif.reset)}}) begin
for(int i=0; i<{{cpuif.resp_buffer_size}}; i++) begin
axil_resp_buffer[i].is_wr <= '0;
axil_resp_buffer[i].err <= '0;
axil_resp_buffer[i].rdata <= '0;
end
axil_resp_wptr <= '0;
axil_resp_rptr <= '0;
end else begin
// Store responses in buffer until AXI response channel accepts them
if(cpuif_rd_ack || cpuif_wr_ack) begin
if(cpuif_rd_ack) begin
axil_resp_buffer[axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0]].is_wr <= '0;
axil_resp_buffer[axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0]].err <= cpuif_rd_err;
axil_resp_buffer[axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0]].rdata <= cpuif_rd_data;
end else if(cpuif_wr_ack) begin
axil_resp_buffer[axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0]].is_wr <= '1;
axil_resp_buffer[axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0]].err <= cpuif_wr_err;
end
{%- if is_pow2(cpuif.resp_buffer_size) %}
axil_resp_wptr <= axil_resp_wptr + 1'b1;
{%- else %}
if(axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] == {{cpuif.resp_buffer_size-1}}) begin
axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] <= '0;
axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)}}] <= ~axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)}}];
end else begin
axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] <= axil_resp_wptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] + 1'b1;
end
{%- endif %}
end
// Advance read pointer when acknowledged
if(axil_resp_acked) begin
{%- if is_pow2(cpuif.resp_buffer_size) %}
axil_resp_rptr <= axil_resp_rptr + 1'b1;
{%- else %}
if(axil_resp_rptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] == {{cpuif.resp_buffer_size-1}}) begin
axil_resp_rptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] <= '0;
axil_resp_rptr[{{clog2(cpuif.resp_buffer_size)}}] <= ~axil_resp_rptr[{{clog2(cpuif.resp_buffer_size)}}];
end else begin
axil_resp_rptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] <= axil_resp_rptr[{{clog2(cpuif.resp_buffer_size)-1}}:0] + 1'b1;
end
{%- endif %}
end
end
endI did look at the cpuif.resp_buffer_size == 1 section of the jinja template, and it did manage to run without any issue using that. I also modified the output file to remove the struct and just make it plain registers, and that also seems to work. So, the main issue Verilator has with this code is that it's using a struct.
I'll see about creating a pull request with the struct fixed.
Thanks!