zachjs / sv2v

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

ifndef and define behavior not compatible with Verilog #250

Closed stitchlibar closed 11 months ago

stitchlibar commented 11 months ago

Verilog treats define as local if the define is inside a module. But sv2v seems to take it as global. So it fails on ifndef/define coding in some verilog header file. global.vh has content:

ifndef INCLUDE_MSB_ define INCLUDEMSB localparam MSB = 2; `endif

The above header file is included in two modules top and submod shown as below. When the RTL is processed by sv2v, localparameter MSB won't show up in the second module 'submod'. Since sv2v assumes INCLUDE_MSB already defined. The verilog code runs fine with other commercial EDA tools.

module top(/AUTOARG/ // Outputs dout, // Inputs clk, rst, din ); include "global.vh" input clk, rst; input [MSB:0] din; output [MSB:0] dout; always @(posedge clk or negedge rst) begin if(!rst) dout[0] <= 1'b0; else dout[0] <= din[0] ^ din[1] ^ obit; end assign dout[1] = dout[0]; assign dout[MSB] = dout[1]; submod submod(/*AUTOINST*/ // Outputs .obit (obit), // Inputs .din (din[2:0])); endmodule module submod(/*AUTOARG*/ // Outputs obit, // Inputs din ); include "global.vh" input [MSB:0] din; output obit; assign obit = &din; endmodule

stitchlibar commented 11 months ago

Sorry. The code was messed up because of Verilog syntax tick symbol. Please check the tar gz file ifdef.tar.gz

zachjs commented 11 months ago

Per Section 22.5.1 of IEEE 1800-2017:

Once a text macro name has been defined, it can be used anywhere in the compilation unit where it is defined. There are no other scope restrictions once inside the compilation unit.

Per Section 3.12.1 of IEEE 1800-2017, a "compilation unit" is:

A collection of one or more SystemVerilog source files compiled together.

As such, Verilog does not scope preprocessor macros within modules. For example, with the following two files:

// foo.sv
module top1;
    localparam S = 100;
    initial $display("hello 1");
    `include "bar.sv"
    `include "bar.sv"
endmodule
module top2;
    localparam S = 200;
    initial $display("hello 2");
    `include "bar.sv"
    `include "bar.sv"
endmodule
// bar.sv
`ifndef X
`define X
initial $display("%0d", S);
`endif

I get the following output in every simulator I have access to, commercial or otherwise:

hello 1
100
hello 2

If you have a counterexample for the above, can you share the exact files, tool versions, and command line invocation? This would be very helpful.

Verilog does scope preprocessor macros to files but only if each file is in its own compilation unit. This is not the default behavior in any tool AFAIK. sv2v treats each input file as its own compilation unit only when run with the --siloed flag. iverilog uses the -u flag to enable this behavior.

stitchlibar commented 11 months ago

You are right. ifndef/define is not the root cause. The initial issue was with other weird behavior. Now we isolate it to a very simple example. It complains sv2v.exe: declarations output [32 - 1:0] data and reg [31:0] data are incompatible due to different packed dimensions

module top(/AUTOARG/ // Outputs data, // Inputs clk, rst, din ); input clk, rst; input [2:0] din; output [32-1:0] data; reg [31:0] data; always @(posedge clk) begin data <= 32'h0; //{32{din[0]}}; end endmodule

stitchlibar commented 11 months ago

Sorry, the display is messed up again. It's actually complaining the following two are not compatible. output [32-1:0] data; reg [31:0] data;

stitchlibar commented 11 months ago

It can be closed. A new issue has been filed as #252