zachjs / sv2v

SystemVerilog to Verilog conversion
BSD 3-Clause "New" or "Revised" License
498 stars 50 forks source link

Problem in translation of emitted variable in function #203

Closed jiegec closed 2 years ago

jiegec commented 2 years ago

SystemVerilog Code:

module test ();
  function automatic logic func(integer arg);
    for (int unsigned i = 0; i < 3; i++)
      if (arg[i])
        return 1'b1;
      return 1'b0;
  endfunction

  wire [3:0] test;
  assign test = func(123);

endmodule

Translated:

module test;
    function automatic func;
        input integer arg;
        reg [0:1] _sv2v_jump;
        begin
            _sv2v_jump = 2'b00;
            begin : sv2v_autoblock_1
                reg [31:0] i;
                for (i = 0; i < 3; i = i + 1)
                    if (_sv2v_jump < 2'b10) begin
                        _sv2v_jump = 2'b00;
                        if (arg[i]) begin
                            func = 1'b1;
                            _sv2v_jump = 2'b11;
                        end
                    end
                if (_sv2v_jump != 2'b11)
                    _sv2v_jump = 2'b00;
            end
            if (_sv2v_jump == 2'b00) begin
                func = 1'b0;
                _sv2v_jump = 2'b11;
            end
        end
    endfunction
    wire [3:0] test;
    assign test = func(123);
endmodule

Yosys output:

$ yosys -p 'read_verilog -sv test.v'
test.v:8: ERROR: Unsupported language construct in constant function
test.v:27: ... called from here.

Possible fix: move reg [31:0] i to the same level as _sv2v_jump:

module test;
    function automatic func;
        input integer arg;
        reg [0:1] _sv2v_jump;
        reg [31:0] i;
        begin
            _sv2v_jump = 2'b00;
            begin : sv2v_autoblock_1
                for (i = 0; i < 3; i = i + 1)
                    if (_sv2v_jump < 2'b10) begin
                        _sv2v_jump = 2'b00;
                        if (arg[i]) begin
                            func = 1'b1;
                            _sv2v_jump = 2'b11;
                        end
                    end
                if (_sv2v_jump != 2'b11)
                    _sv2v_jump = 2'b00;
            end
            if (_sv2v_jump == 2'b00) begin
                func = 1'b0;
                _sv2v_jump = 2'b11;
            end
        end
    endfunction
    wire [3:0] test;
    assign test = func(123);
endmodule
zachjs commented 2 years ago

What version of Yosys are you using? I believe this particular issue was fixed in https://github.com/YosysHQ/yosys/pull/2300.

jiegec commented 2 years ago

Thanks, it is fixed in yosys master. I was using yosys 0.9.