zachjs / sv2v

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

Issue when converting CV32E40X #226

Closed mole99 closed 1 year ago

mole99 commented 1 year ago

Hello,

I am trying to convert the cv32e40x core to Verilog with the following command: sv2v -v rtl/include/cv32e40x_pkg.sv rtl/*.sv > processed.v

The command completes without error, but when I take a look at the output file I see that the toplevel module has been removed (together with some other modules):

// removed module with interface ports: cv32e40x_core

These modules make extensive use of modports.

Is there any way to solve this issue?

Thanks!

zachjs commented 1 year ago

Because cv32e40x_core has ports which are modports, sv2v must be able to observe and convert its instantiation. Modules with modport or interface ports which are uninstantiated cannot necessarily be represented with equivalent Verilog, so sv2v requires that the module and its instantiation be converted at the same time. Please try adding a wrapper or top-level module which instantiates the core.

mole99 commented 1 year ago

Thanks for your reply!

I added a wrapper cv32e40x_top around cv32e40x_core where the interface if_xif is instantiated and signals are assigned. The modports are then passed to the cv32e40x_core.

The conversion completes without error, and it seems to be a success!

Still the modules are removed:

// removed module with interface ports: cv32e40x_core

But the logic of cv32e40x_core is now contained inside cv32e40x_top.

The only catch: The tool did not remove/resolve some of the typedefs in cv32e40x_top, for example x_compressed_req_t on line 9330 in preprocessed.v.

Presumably because they were declared inside the interface if_xif.

I pushed my code to mole99/cv32e40x if you want to take a quick look at it. You can run the conversion with make preprocessed.v.

After adding these typedefs manually I could run synthesis on yosys. Your tool is really awesome!

zachjs commented 1 year ago

Thanks for sharing! I'm glad the flow seems to be working.

Within cv32e40x_top, x_compressed_req_t and the other unconverted typenames are defined within if_xif, and so are not in scope. If you need to use those types, I think the traditional solution would be to put the typedefs in a package that both the interface and the module can import.

SystemVerilog also has a concept called "interface based typedefs" which can be used (or abused) as a workaround. IEEE 1800-2017 Section 6.18 has the following simple example.

interface intf_i;
    typedef int data_t;
endinterface
module sub(intf_i p);
    typedef p.data_t my_data_t;
    my_data_t data;
    // type of 'data' will be int when connected to interface above
endmodule

In your specific case, you might do something like the below, where the interface based typedef refers to a type within an interface instance rather than a bound modport. Please note: the standard doesn't necessarily say that this should work. sv2v and at least one commercial toolchain support it, but many tools do not.

    if_xif my_if_xif();
    typedef my_if_xif.x_compressed_req_t x_compressed_req_t;
    x_compressed_req_t compressed_req;
mole99 commented 1 year ago

I have added all typedefs according to the interface.

The design is now converted from SystemVerilog to Verilog without manual intervention. This is exactly what I was looking for!

From my side this issue is resolved and can be closed. Thanks a lot @zachjs!

zachjs commented 1 year ago

I'm glad to hear that's it working for you! Please feel free to file a new issue or reopen this one if you run into problems.