mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-27 10:55:51 +00:00
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
8 changed files with 197 additions and 11 deletions
|
@ -727,7 +727,8 @@ frontend_verilog_preproc(std::istream &f,
|
|||
|
||||
std::vector<std::string> filename_stack;
|
||||
int ifdef_fail_level = 0;
|
||||
bool in_elseif = false;
|
||||
int ifdef_pass_level = 0;
|
||||
bool ifdef_already_satisfied = false;
|
||||
|
||||
output_code.clear();
|
||||
input_buffer.clear();
|
||||
|
@ -743,42 +744,68 @@ frontend_verilog_preproc(std::istream &f,
|
|||
if (tok == "`endif") {
|
||||
if (ifdef_fail_level > 0)
|
||||
ifdef_fail_level--;
|
||||
if (ifdef_fail_level == 0)
|
||||
in_elseif = false;
|
||||
else if (ifdef_pass_level > 0)
|
||||
ifdef_already_satisfied = --ifdef_pass_level;
|
||||
else
|
||||
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
else if (ifdef_fail_level == 1 && !in_elseif)
|
||||
} else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) {
|
||||
ifdef_fail_level = 0;
|
||||
ifdef_pass_level++;
|
||||
ifdef_already_satisfied = true;
|
||||
}
|
||||
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.find(name))
|
||||
ifdef_fail_level = 0, in_elseif = true;
|
||||
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;
|
||||
} else if (ifdef_fail_level == 1 && !ifdef_already_satisfied && defines.find(name)) {
|
||||
ifdef_fail_level = 0;
|
||||
ifdef_pass_level++;
|
||||
ifdef_already_satisfied = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tok == "`ifdef") {
|
||||
skip_spaces();
|
||||
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++;
|
||||
} else {
|
||||
ifdef_pass_level++;
|
||||
ifdef_already_satisfied = true;
|
||||
}
|
||||
if (ifdef_fail_level == 1)
|
||||
ifdef_already_satisfied = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tok == "`ifndef") {
|
||||
skip_spaces();
|
||||
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++;
|
||||
} else {
|
||||
ifdef_pass_level++;
|
||||
ifdef_already_satisfied = true;
|
||||
}
|
||||
if (ifdef_fail_level == 1)
|
||||
ifdef_already_satisfied = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue