aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog/preproc.cc
diff options
context:
space:
mode:
authorZachary Snow <zach@zachjs.com>2021-02-25 15:53:55 -0500
committerZachary Snow <zachary.j.snow@gmail.com>2021-03-01 12:28:33 -0500
commit1ec5994100510d6fb9e18ff7234ede496f831a51 (patch)
tree77c8403f0ece00ad1b42e2e91f86befe0f736cac /frontends/verilog/preproc.cc
parentb6904a8e5344fcd01c1a0feea281cd7d7bf0f210 (diff)
downloadyosys-1ec5994100510d6fb9e18ff7234ede496f831a51.tar.gz
yosys-1ec5994100510d6fb9e18ff7234ede496f831a51.tar.bz2
yosys-1ec5994100510d6fb9e18ff7234ede496f831a51.zip
verilog: fix handling of nested ifdef directives
- track depth so we know whether to consider higher-level elsifs - error on unmatched endif/elsif/else
Diffstat (limited to 'frontends/verilog/preproc.cc')
-rw-r--r--frontends/verilog/preproc.cc49
1 files changed, 38 insertions, 11 deletions
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index de707593f..84966e501 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -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;
}