diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index e17531be2..023c4dbcc 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -206,6 +206,7 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m { std::map defines_map(pre_defines_map); int ifdef_fail_level = 0; + bool in_elseif = false; output_code.clear(); input_buffer.clear(); @@ -222,17 +223,29 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m if (tok == "`endif") { if (ifdef_fail_level > 0) ifdef_fail_level--; + if (ifdef_fail_level == 0) + in_elseif = false; continue; } if (tok == "`else") { if (ifdef_fail_level == 0) ifdef_fail_level = 1; - else if (ifdef_fail_level == 1) + else if (ifdef_fail_level == 1 && !in_elseif) ifdef_fail_level = 0; continue; } + if (tok == "`elsif") { + skip_spaces(); + std::string name = next_token(true); + if (ifdef_fail_level == 0) + ifdef_fail_level = 1, in_elseif = true; + else if (ifdef_fail_level == 1 && defines_map.count(name) != 0) + ifdef_fail_level = 0, in_elseif = true; + continue; + } + if (tok == "`ifdef") { skip_spaces(); std::string name = next_token(true); diff --git a/tests/simple/macros.v b/tests/simple/macros.v index e2025717f..cda46cb48 100644 --- a/tests/simple/macros.v +++ b/tests/simple/macros.v @@ -1,9 +1,237 @@ -module test(a, y); + +module test_def(a, y); + `define MSB_LSB_SEP : `define get_msb(off, len) ((off)+(len)-1) `define get_lsb(off, len) (off) `define sel_bits(offset, len) `get_msb(offset, len) `MSB_LSB_SEP `get_lsb(offset, len) + input [31:0] a; output [7:0] y; + assign y = a[`sel_bits(16, 8)]; + +endmodule + +// --------------------------------------------------- + +module test_ifdef(a, y); + +input [2:0] a; +output reg [31:0] y; + +always @* begin + y = 0; + + `undef X + `ifdef X + y = y + 42; + `else + `undef A + `undef B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `undef A + `define B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `undef B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `define B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + // ------------------------------------ + `undef A + `undef B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `undef A + `define B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `undef B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `define B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + // ------------------------------------ + `undef A + `ifdef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `ifdef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + // ------------------------------------ + `undef A + `ifndef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `ifndef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + `endif + + `define X + `ifdef X + `undef A + `undef B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `undef A + `define B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `undef B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `define B + `ifdef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + // ------------------------------------ + `undef A + `undef B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `undef A + `define B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `undef B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `define B + `ifndef A + y = (y << 1) | a[0]; + `elsif B + y = (y << 1) | a[1]; + `else + y = (y << 1) | a[2]; + `endif + // ------------------------------------ + `undef A + `ifdef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `ifdef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + // ------------------------------------ + `undef A + `ifndef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + `define A + `ifndef A + y = (y << 1) | a[0]; + `else + y = (y << 1) | a[2]; + `endif + `else + y = y + 42; + `endif +end + endmodule