mirror of https://github.com/YosysHQ/yosys.git
verilog: fix handling of nested ifdef directives
- track depth so we know whether to consider higher-level elsifs - error on unmatched endif/elsif/else
This commit is contained in:
parent
b6904a8e53
commit
1ec5994100
|
@ -727,7 +727,8 @@ frontend_verilog_preproc(std::istream &f,
|
||||||
|
|
||||||
std::vector<std::string> filename_stack;
|
std::vector<std::string> filename_stack;
|
||||||
int ifdef_fail_level = 0;
|
int ifdef_fail_level = 0;
|
||||||
bool in_elseif = false;
|
int ifdef_pass_level = 0;
|
||||||
|
bool ifdef_already_satisfied = false;
|
||||||
|
|
||||||
output_code.clear();
|
output_code.clear();
|
||||||
input_buffer.clear();
|
input_buffer.clear();
|
||||||
|
@ -743,42 +744,68 @@ frontend_verilog_preproc(std::istream &f,
|
||||||
if (tok == "`endif") {
|
if (tok == "`endif") {
|
||||||
if (ifdef_fail_level > 0)
|
if (ifdef_fail_level > 0)
|
||||||
ifdef_fail_level--;
|
ifdef_fail_level--;
|
||||||
if (ifdef_fail_level == 0)
|
else if (ifdef_pass_level > 0)
|
||||||
in_elseif = false;
|
ifdef_already_satisfied = --ifdef_pass_level;
|
||||||
|
else
|
||||||
|
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == "`else") {
|
if (tok == "`else") {
|
||||||
if (ifdef_fail_level == 0)
|
if (ifdef_fail_level == 0) {
|
||||||
|
if (ifdef_pass_level == 0)
|
||||||
|
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
|
||||||
|
log_assert(ifdef_already_satisfied);
|
||||||
ifdef_fail_level = 1;
|
ifdef_fail_level = 1;
|
||||||
else if (ifdef_fail_level == 1 && !in_elseif)
|
} else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) {
|
||||||
ifdef_fail_level = 0;
|
ifdef_fail_level = 0;
|
||||||
|
ifdef_pass_level++;
|
||||||
|
ifdef_already_satisfied = true;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == "`elsif") {
|
if (tok == "`elsif") {
|
||||||
skip_spaces();
|
skip_spaces();
|
||||||
std::string name = next_token(true);
|
std::string name = next_token(true);
|
||||||
if (ifdef_fail_level == 0)
|
if (ifdef_fail_level == 0) {
|
||||||
ifdef_fail_level = 1, in_elseif = true;
|
if (ifdef_pass_level == 0)
|
||||||
else if (ifdef_fail_level == 1 && defines.find(name))
|
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
|
||||||
ifdef_fail_level = 0, in_elseif = true;
|
log_assert(ifdef_already_satisfied);
|
||||||
|
ifdef_fail_level = 1;
|
||||||
|
} else if (ifdef_fail_level == 1 && !ifdef_already_satisfied && defines.find(name)) {
|
||||||
|
ifdef_fail_level = 0;
|
||||||
|
ifdef_pass_level++;
|
||||||
|
ifdef_already_satisfied = true;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == "`ifdef") {
|
if (tok == "`ifdef") {
|
||||||
skip_spaces();
|
skip_spaces();
|
||||||
std::string name = next_token(true);
|
std::string name = next_token(true);
|
||||||
if (ifdef_fail_level > 0 || !defines.find(name))
|
if (ifdef_fail_level > 0 || !defines.find(name)) {
|
||||||
ifdef_fail_level++;
|
ifdef_fail_level++;
|
||||||
|
} else {
|
||||||
|
ifdef_pass_level++;
|
||||||
|
ifdef_already_satisfied = true;
|
||||||
|
}
|
||||||
|
if (ifdef_fail_level == 1)
|
||||||
|
ifdef_already_satisfied = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == "`ifndef") {
|
if (tok == "`ifndef") {
|
||||||
skip_spaces();
|
skip_spaces();
|
||||||
std::string name = next_token(true);
|
std::string name = next_token(true);
|
||||||
if (ifdef_fail_level > 0 || defines.find(name))
|
if (ifdef_fail_level > 0 || defines.find(name)) {
|
||||||
ifdef_fail_level++;
|
ifdef_fail_level++;
|
||||||
|
} else {
|
||||||
|
ifdef_pass_level++;
|
||||||
|
ifdef_already_satisfied = true;
|
||||||
|
}
|
||||||
|
if (ifdef_fail_level == 1)
|
||||||
|
ifdef_already_satisfied = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
module top(o1, o2, o3, o4);
|
||||||
|
|
||||||
|
`define FAIL input wire not_a_port;
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_2
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_3
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_4
|
||||||
|
`FAIL
|
||||||
|
`else
|
||||||
|
|
||||||
|
`define COND_4
|
||||||
|
output wire o4;
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_2
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_3
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_4
|
||||||
|
|
||||||
|
`define COND_3
|
||||||
|
output wire o3;
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_2
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_3
|
||||||
|
|
||||||
|
`define COND_2
|
||||||
|
output wire o2;
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_2
|
||||||
|
|
||||||
|
`define COND_1
|
||||||
|
output wire o1;
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
`elsif COND_2
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_3
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_4
|
||||||
|
`FAIL
|
||||||
|
`else
|
||||||
|
`FAIL
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`elsif COND_2
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_3
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_4
|
||||||
|
`FAIL
|
||||||
|
`else
|
||||||
|
`FAIL
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`elsif COND_3
|
||||||
|
`FAIL
|
||||||
|
`elsif COND_4
|
||||||
|
`FAIL
|
||||||
|
`else
|
||||||
|
`FAIL
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`elsif COND_4
|
||||||
|
`FAIL
|
||||||
|
`else
|
||||||
|
`FAIL
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`else
|
||||||
|
`FAIL
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,21 @@
|
||||||
|
module top(o1, o2, o3);
|
||||||
|
|
||||||
|
output wire o1;
|
||||||
|
|
||||||
|
`define COND_1
|
||||||
|
`define COND_2
|
||||||
|
`define COND_3
|
||||||
|
|
||||||
|
`ifdef COND_1
|
||||||
|
output wire o2;
|
||||||
|
`elsif COND_2
|
||||||
|
input wire dne1;
|
||||||
|
`elsif COND_3
|
||||||
|
input wire dne2;
|
||||||
|
`else
|
||||||
|
input wire dne3;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
output wire o3;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,30 @@
|
||||||
|
`ifdef GUARD_5
|
||||||
|
module top;
|
||||||
|
wire x;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`elsif GUARD_4
|
||||||
|
`define GUARD_5
|
||||||
|
`include "include_self.v"
|
||||||
|
|
||||||
|
`elsif GUARD_3
|
||||||
|
`define GUARD_4
|
||||||
|
`include "include_self.v"
|
||||||
|
|
||||||
|
`elsif GUARD_2
|
||||||
|
`define GUARD_3
|
||||||
|
`include "include_self.v"
|
||||||
|
|
||||||
|
`elsif GUARD_1
|
||||||
|
`define GUARD_2
|
||||||
|
`include "include_self.v"
|
||||||
|
|
||||||
|
`elsif GUARD_0
|
||||||
|
`define GUARD_1
|
||||||
|
`include "include_self.v"
|
||||||
|
|
||||||
|
`else
|
||||||
|
`define GUARD_0
|
||||||
|
`include "include_self.v"
|
||||||
|
|
||||||
|
`endif
|
|
@ -0,0 +1,2 @@
|
||||||
|
read_verilog include_self.v
|
||||||
|
select -assert-count 1 top/x
|
|
@ -0,0 +1,6 @@
|
||||||
|
logger -expect error "Found `else outside of macro conditional branch!" 1
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top;
|
||||||
|
`else
|
||||||
|
endmodule
|
||||||
|
EOT
|
|
@ -0,0 +1,6 @@
|
||||||
|
logger -expect error "Found `elsif outside of macro conditional branch!" 1
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top;
|
||||||
|
`elsif
|
||||||
|
endmodule
|
||||||
|
EOT
|
|
@ -0,0 +1,6 @@
|
||||||
|
logger -expect error "Found `endif outside of macro conditional branch!" 1
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top;
|
||||||
|
`endif
|
||||||
|
endmodule
|
||||||
|
EOT
|
Loading…
Reference in New Issue