From 6d2e287a7403b92ba549b7888d368bfea3d579fc Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 26 May 2026 16:12:43 -0700 Subject: [PATCH 01/13] union --- kernel/fstdata.cc | 141 ++++++++++++++++++++++++++++++---------------- kernel/fstdata.h | 1 + 2 files changed, 93 insertions(+), 49 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index 0a6f406ef..65abee311 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -109,18 +109,108 @@ static std::string remove_spaces(std::string str) return str; } +void FstData::registerVar(const FstVar &var) +{ + vars.push_back(var); + if (!var.is_alias) + handle_to_var[var.id] = var; + + std::string clean_name = var.name; + if (!clean_name.empty() && clean_name[0] == '\\') + clean_name = clean_name.substr(1); + + // Strip trailing bit range [N:M] if present + if (!clean_name.empty() && clean_name.back() == ']') { + size_t open = clean_name.rfind('['); + if (open != std::string::npos) { + std::string inner = clean_name.substr(open + 1, clean_name.size() - open - 2); + if (inner.find(':') != std::string::npos) + clean_name.erase(open); + } + } + + // Handle memory addresses + size_t pos = clean_name.find_last_of("<"); + if (pos != std::string::npos && clean_name.back() == '>') { + std::string mem_cell = clean_name.substr(0, pos); + normalize_brackets(mem_cell); + std::string addr = clean_name.substr(pos+1); + addr.pop_back(); // remove closing bracket + char *endptr; + int mem_addr = strtol(addr.c_str(), &endptr, 16); + if (*endptr) { + log_debug("Error parsing memory address in : %s\n", clean_name); + } else { + memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; + } + } + pos = clean_name.find_last_of("["); + if (pos != std::string::npos && clean_name.back() == ']') { + std::string mem_cell = clean_name.substr(0, pos); + normalize_brackets(mem_cell); + std::string addr = clean_name.substr(pos+1); + addr.pop_back(); // remove closing bracket + char *endptr; + int mem_addr = strtol(addr.c_str(), &endptr, 10); + if (*endptr) { + log_debug("Error parsing memory address in : %s\n", clean_name); + } else { + memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; + } + } + normalize_brackets(clean_name); + name_to_handle[var.scope+"."+clean_name] = var.id; +} + void FstData::extractVarNames() { struct fstHier *h; std::string fst_scope_name; + /* Variables for resolving unions with $fork. */ + bool in_fork = false; // if we are inside a $fork scope + std::string fork_parent_scope; // parent scope of fork (used to resolve union location) + std::string fork_name; // name of fork (used to resolve union name) + std::vector fork_vars; // stores all variables in the fork scope + while ((h = fstReaderIterateHier(ctx))) { switch (h->htyp) { case FST_HT_SCOPE: { + // Handle tracking for potential union structs with $fork. + if (!in_fork && h->u.scope.typ == FST_ST_VCD_FORK) { + in_fork = true; + fork_parent_scope = fst_scope_name; + fork_name = h->u.scope.name; + fork_vars.clear(); + } + // Push the scope onto the stack to 'descend' into the hierarchy. fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } case FST_HT_UPSCOPE: { + if (in_fork) { + // A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle. + bool is_union = fork_vars.size() >= 2 && + std::all_of(fork_vars.begin() + 1, fork_vars.end(), + [&](const FstVar &v) { return v.id == fork_vars[0].id; }); + if (is_union) { + // If a union, register the fork name as the variable at the parent scope. + FstVar u = fork_vars[0]; + u.name = fork_name; + u.scope = fork_parent_scope; + normalize_brackets(u.scope); + u.is_alias = false; + registerVar(u); + } else { + // If not a union, register all variables in the fork scope as normal. + for (auto &v : fork_vars) { + registerVar(v); + } + } + in_fork = false; + fork_vars.clear(); + } + // Pop the scope off the stack. fst_scope_name = fstReaderPopScope(ctx); break; } @@ -133,62 +223,15 @@ void FstData::extractVarNames() var.scope = fst_scope_name; normalize_brackets(var.scope); var.width = h->u.var.length; - vars.push_back(var); - if (!var.is_alias) - handle_to_var[h->u.var.handle] = var; - std::string clean_name = var.name; - if (!clean_name.empty() && clean_name[0] == '\\') - clean_name = clean_name.substr(1); - - // Strip trailing bit range [N:M] if present - if (!clean_name.empty() && clean_name.back() == ']') { - size_t open = clean_name.rfind('['); - if (open != std::string::npos) { - std::string inner = clean_name.substr(open + 1, clean_name.size() - open - 2); - if (inner.find(':') != std::string::npos) - clean_name.erase(open); - } - } - - // Handle memory addresses - size_t pos = clean_name.find_last_of("<"); - if (pos != std::string::npos && clean_name.back() == '>') { - std::string mem_cell = clean_name.substr(0, pos); - normalize_brackets(mem_cell); - std::string addr = clean_name.substr(pos+1); - addr.pop_back(); // remove closing bracket - char *endptr; - int mem_addr = strtol(addr.c_str(), &endptr, 16); - if (*endptr) { - log_debug("Error parsing memory address in : %s\n", clean_name); - } else { - memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; - } - } - pos = clean_name.find_last_of("["); - if (pos != std::string::npos && clean_name.back() == ']') { - std::string mem_cell = clean_name.substr(0, pos); - normalize_brackets(mem_cell); - std::string addr = clean_name.substr(pos+1); - addr.pop_back(); // remove closing bracket - char *endptr; - int mem_addr = strtol(addr.c_str(), &endptr, 10); - if (*endptr) { - log_debug("Error parsing memory address in : %s\n", clean_name); - } else { - memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; - } - } - normalize_brackets(clean_name); - name_to_handle[var.scope+"."+clean_name] = h->u.var.handle; + if (in_fork) fork_vars.push_back(var); // store all variables in fork scope into a vector + else registerVar(var); // otherwise, register the variable as normal break; } } } } - static void reconstruct_clb_varlen_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen) { FstData *ptr = (FstData*)user_data; diff --git a/kernel/fstdata.h b/kernel/fstdata.h index 98f5d5014..6263db056 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -61,6 +61,7 @@ class FstData std::string autoScope(Module *topmod); private: void extractVarNames(); + void registerVar(const FstVar &var); struct fstReaderContext *ctx; std::vector vars; From 73fd2fdc478a9460ea343f762a8be5689395b481 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 26 May 2026 22:47:03 -0700 Subject: [PATCH 02/13] warn for scopes --- kernel/fstdata.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index 65abee311..92f12e480 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -168,7 +168,7 @@ void FstData::extractVarNames() std::string fst_scope_name; /* Variables for resolving unions with $fork. */ - bool in_fork = false; // if we are inside a $fork scope + bool detect_union = false; // if we should be detecting unions with $fork std::string fork_parent_scope; // parent scope of fork (used to resolve union location) std::string fork_name; // name of fork (used to resolve union name) std::vector fork_vars; // stores all variables in the fork scope @@ -177,18 +177,26 @@ void FstData::extractVarNames() switch (h->htyp) { case FST_HT_SCOPE: { // Handle tracking for potential union structs with $fork. - if (!in_fork && h->u.scope.typ == FST_ST_VCD_FORK) { - in_fork = true; + if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { + detect_union = true; fork_parent_scope = fst_scope_name; fork_name = h->u.scope.name; fork_vars.clear(); + } else if (in_fork && h->u.scope.typ == FST_ST_VCD_STRUCT) { + // Signal that a nested $fork can not be a candidate for union struct detection. + log_warning("Nested $fork '%s' inside $fork '%s'; " + "abandoning union detection for this scope...\n", + h->u.scope.name, fork_name.c_str()); + for (auto &v : fork_vars) registerVar(v); + detect_union = false; + fork_vars.clear(); } // Push the scope onto the stack to 'descend' into the hierarchy. fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } case FST_HT_UPSCOPE: { - if (in_fork) { + if (detect_union) { // A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle. bool is_union = fork_vars.size() >= 2 && std::all_of(fork_vars.begin() + 1, fork_vars.end(), @@ -207,7 +215,7 @@ void FstData::extractVarNames() registerVar(v); } } - in_fork = false; + detect_union = false; fork_vars.clear(); } // Pop the scope off the stack. @@ -224,7 +232,7 @@ void FstData::extractVarNames() normalize_brackets(var.scope); var.width = h->u.var.length; - if (in_fork) fork_vars.push_back(var); // store all variables in fork scope into a vector + if (detect_union) fork_vars.push_back(var); // store all variables in fork scope into a vector else registerVar(var); // otherwise, register the variable as normal break; } From 8c0ded23b7852c3e5b2b2922b4ea5e430fd3fd94 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 26 May 2026 23:14:11 -0700 Subject: [PATCH 03/13] fix --- kernel/fstdata.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index 92f12e480..f1d85f1eb 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -182,7 +182,7 @@ void FstData::extractVarNames() fork_parent_scope = fst_scope_name; fork_name = h->u.scope.name; fork_vars.clear(); - } else if (in_fork && h->u.scope.typ == FST_ST_VCD_STRUCT) { + } else if (detect_union && h->u.scope.typ == FST_ST_VCD_STRUCT) { // Signal that a nested $fork can not be a candidate for union struct detection. log_warning("Nested $fork '%s' inside $fork '%s'; " "abandoning union detection for this scope...\n", From a3613866bfc18ec44c707554c667f90b064dd6a7 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 02:41:40 -0700 Subject: [PATCH 04/13] Update kernel/fstdata.cc Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- kernel/fstdata.cc | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index f1d85f1eb..b98b8d1a0 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -195,33 +195,26 @@ void FstData::extractVarNames() fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } - case FST_HT_UPSCOPE: { - if (detect_union) { - // A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle. - bool is_union = fork_vars.size() >= 2 && - std::all_of(fork_vars.begin() + 1, fork_vars.end(), - [&](const FstVar &v) { return v.id == fork_vars[0].id; }); - if (is_union) { - // If a union, register the fork name as the variable at the parent scope. - FstVar u = fork_vars[0]; - u.name = fork_name; - u.scope = fork_parent_scope; - normalize_brackets(u.scope); - u.is_alias = false; - registerVar(u); - } else { - // If not a union, register all variables in the fork scope as normal. - for (auto &v : fork_vars) { - registerVar(v); - } - } + case FST_HT_SCOPE: { + // Handle tracking for potential union structs with $fork. + if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { + detect_union = true; + fork_parent_scope = fst_scope_name; + fork_name = h->u.scope.name; + fork_vars.clear(); + } else if (detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { + // Nested $fork: abandon union detection. Warning is emitted + // at upscope time, only if the outer fork would have been a union. + for (auto &v : fork_vars) registerVar(v); detect_union = false; fork_vars.clear(); + fork_vars_had_nested_fork = true; } - // Pop the scope off the stack. - fst_scope_name = fstReaderPopScope(ctx); + // Push the scope onto the stack to 'descend' into the hierarchy. + fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } + } case FST_HT_VAR: { FstVar var; var.id = h->u.var.handle; From 7e64b6855bcc40f81e38e4c5f1251934196dde7b Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 02:57:52 -0700 Subject: [PATCH 05/13] Fix formatting by removing extra brace Removed unnecessary closing brace in switch case. --- kernel/fstdata.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index b98b8d1a0..e1b66b873 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -214,7 +214,6 @@ void FstData::extractVarNames() fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } - } case FST_HT_VAR: { FstVar var; var.id = h->u.var.handle; From 10a4056e3bd50b52771c0bf5a059cba7f5a3bb15 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:03:38 -0700 Subject: [PATCH 06/13] Remove nested $fork handling from union detection Removed logic for nested $fork handling in union struct detection. --- kernel/fstdata.cc | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index e1b66b873..da3f7ee23 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -175,26 +175,6 @@ void FstData::extractVarNames() while ((h = fstReaderIterateHier(ctx))) { switch (h->htyp) { - case FST_HT_SCOPE: { - // Handle tracking for potential union structs with $fork. - if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { - detect_union = true; - fork_parent_scope = fst_scope_name; - fork_name = h->u.scope.name; - fork_vars.clear(); - } else if (detect_union && h->u.scope.typ == FST_ST_VCD_STRUCT) { - // Signal that a nested $fork can not be a candidate for union struct detection. - log_warning("Nested $fork '%s' inside $fork '%s'; " - "abandoning union detection for this scope...\n", - h->u.scope.name, fork_name.c_str()); - for (auto &v : fork_vars) registerVar(v); - detect_union = false; - fork_vars.clear(); - } - // Push the scope onto the stack to 'descend' into the hierarchy. - fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); - break; - } case FST_HT_SCOPE: { // Handle tracking for potential union structs with $fork. if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { From d6216ea85d2064ff59c42b0f6318d1a3fc6cfa97 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:05:11 -0700 Subject: [PATCH 07/13] Add flag to track nested fork detection --- kernel/fstdata.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/fstdata.h b/kernel/fstdata.h index 6263db056..56f0ee51a 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -63,6 +63,7 @@ private: void extractVarNames(); void registerVar(const FstVar &var); + bool fork_vars_had_nested_fork = false; // Track if nested fork was detected struct fstReaderContext *ctx; std::vector vars; std::map handle_to_var; From e421fa8547aaf892d3d4ed92e99975822b73db6c Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:54:53 -0700 Subject: [PATCH 08/13] Revert "Add flag to track nested fork detection" This reverts commit d6216ea85d2064ff59c42b0f6318d1a3fc6cfa97. --- kernel/fstdata.h | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/fstdata.h b/kernel/fstdata.h index 56f0ee51a..6263db056 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -63,7 +63,6 @@ private: void extractVarNames(); void registerVar(const FstVar &var); - bool fork_vars_had_nested_fork = false; // Track if nested fork was detected struct fstReaderContext *ctx; std::vector vars; std::map handle_to_var; From 7b68f5d532520b6c9efa2b426f284b79c20fe1e8 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:55:03 -0700 Subject: [PATCH 09/13] Revert "Remove nested $fork handling from union detection" This reverts commit 10a4056e3bd50b52771c0bf5a059cba7f5a3bb15. --- kernel/fstdata.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index da3f7ee23..e1b66b873 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -175,6 +175,26 @@ void FstData::extractVarNames() while ((h = fstReaderIterateHier(ctx))) { switch (h->htyp) { + case FST_HT_SCOPE: { + // Handle tracking for potential union structs with $fork. + if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { + detect_union = true; + fork_parent_scope = fst_scope_name; + fork_name = h->u.scope.name; + fork_vars.clear(); + } else if (detect_union && h->u.scope.typ == FST_ST_VCD_STRUCT) { + // Signal that a nested $fork can not be a candidate for union struct detection. + log_warning("Nested $fork '%s' inside $fork '%s'; " + "abandoning union detection for this scope...\n", + h->u.scope.name, fork_name.c_str()); + for (auto &v : fork_vars) registerVar(v); + detect_union = false; + fork_vars.clear(); + } + // Push the scope onto the stack to 'descend' into the hierarchy. + fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); + break; + } case FST_HT_SCOPE: { // Handle tracking for potential union structs with $fork. if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { From f2dacbfa3fa5cf441ae9be23972b1d358697e86c Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:55:10 -0700 Subject: [PATCH 10/13] Revert "Fix formatting by removing extra brace" This reverts commit 7e64b6855bcc40f81e38e4c5f1251934196dde7b. --- kernel/fstdata.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index e1b66b873..b98b8d1a0 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -214,6 +214,7 @@ void FstData::extractVarNames() fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } + } case FST_HT_VAR: { FstVar var; var.id = h->u.var.handle; From 7dcbdcbb34da56bd6b3c38ad7e7b90f109a36b6f Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:55:18 -0700 Subject: [PATCH 11/13] Revert "Update kernel/fstdata.cc" This reverts commit a3613866bfc18ec44c707554c667f90b064dd6a7. --- kernel/fstdata.cc | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index b98b8d1a0..f1d85f1eb 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -195,26 +195,33 @@ void FstData::extractVarNames() fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } - case FST_HT_SCOPE: { - // Handle tracking for potential union structs with $fork. - if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { - detect_union = true; - fork_parent_scope = fst_scope_name; - fork_name = h->u.scope.name; - fork_vars.clear(); - } else if (detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { - // Nested $fork: abandon union detection. Warning is emitted - // at upscope time, only if the outer fork would have been a union. - for (auto &v : fork_vars) registerVar(v); + case FST_HT_UPSCOPE: { + if (detect_union) { + // A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle. + bool is_union = fork_vars.size() >= 2 && + std::all_of(fork_vars.begin() + 1, fork_vars.end(), + [&](const FstVar &v) { return v.id == fork_vars[0].id; }); + if (is_union) { + // If a union, register the fork name as the variable at the parent scope. + FstVar u = fork_vars[0]; + u.name = fork_name; + u.scope = fork_parent_scope; + normalize_brackets(u.scope); + u.is_alias = false; + registerVar(u); + } else { + // If not a union, register all variables in the fork scope as normal. + for (auto &v : fork_vars) { + registerVar(v); + } + } detect_union = false; fork_vars.clear(); - fork_vars_had_nested_fork = true; } - // Push the scope onto the stack to 'descend' into the hierarchy. - fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); + // Pop the scope off the stack. + fst_scope_name = fstReaderPopScope(ctx); break; } - } case FST_HT_VAR: { FstVar var; var.id = h->u.var.handle; From b4286acc22f30636c502a5fe6430c25761e3984b Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:55:23 -0700 Subject: [PATCH 12/13] Revert "fix" This reverts commit 8c0ded23b7852c3e5b2b2922b4ea5e430fd3fd94. --- kernel/fstdata.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index f1d85f1eb..92f12e480 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -182,7 +182,7 @@ void FstData::extractVarNames() fork_parent_scope = fst_scope_name; fork_name = h->u.scope.name; fork_vars.clear(); - } else if (detect_union && h->u.scope.typ == FST_ST_VCD_STRUCT) { + } else if (in_fork && h->u.scope.typ == FST_ST_VCD_STRUCT) { // Signal that a nested $fork can not be a candidate for union struct detection. log_warning("Nested $fork '%s' inside $fork '%s'; " "abandoning union detection for this scope...\n", From 367af96ae1b55c20f578938220ebd88104e4c443 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 27 May 2026 03:58:23 -0700 Subject: [PATCH 13/13] Revert "warn for scopes" This reverts commit 73fd2fdc478a9460ea343f762a8be5689395b481. --- kernel/fstdata.cc | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index 92f12e480..65abee311 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -168,7 +168,7 @@ void FstData::extractVarNames() std::string fst_scope_name; /* Variables for resolving unions with $fork. */ - bool detect_union = false; // if we should be detecting unions with $fork + bool in_fork = false; // if we are inside a $fork scope std::string fork_parent_scope; // parent scope of fork (used to resolve union location) std::string fork_name; // name of fork (used to resolve union name) std::vector fork_vars; // stores all variables in the fork scope @@ -177,26 +177,18 @@ void FstData::extractVarNames() switch (h->htyp) { case FST_HT_SCOPE: { // Handle tracking for potential union structs with $fork. - if (!detect_union && h->u.scope.typ == FST_ST_VCD_FORK) { - detect_union = true; + if (!in_fork && h->u.scope.typ == FST_ST_VCD_FORK) { + in_fork = true; fork_parent_scope = fst_scope_name; fork_name = h->u.scope.name; fork_vars.clear(); - } else if (in_fork && h->u.scope.typ == FST_ST_VCD_STRUCT) { - // Signal that a nested $fork can not be a candidate for union struct detection. - log_warning("Nested $fork '%s' inside $fork '%s'; " - "abandoning union detection for this scope...\n", - h->u.scope.name, fork_name.c_str()); - for (auto &v : fork_vars) registerVar(v); - detect_union = false; - fork_vars.clear(); } // Push the scope onto the stack to 'descend' into the hierarchy. fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL); break; } case FST_HT_UPSCOPE: { - if (detect_union) { + if (in_fork) { // A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle. bool is_union = fork_vars.size() >= 2 && std::all_of(fork_vars.begin() + 1, fork_vars.end(), @@ -215,7 +207,7 @@ void FstData::extractVarNames() registerVar(v); } } - detect_union = false; + in_fork = false; fork_vars.clear(); } // Pop the scope off the stack. @@ -232,7 +224,7 @@ void FstData::extractVarNames() normalize_brackets(var.scope); var.width = h->u.var.length; - if (detect_union) fork_vars.push_back(var); // store all variables in fork scope into a vector + if (in_fork) fork_vars.push_back(var); // store all variables in fork scope into a vector else registerVar(var); // otherwise, register the variable as normal break; }