From b6f118091cf881c07d15a642d82da201c75062dd Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 31 Mar 2026 12:50:36 -0700 Subject: [PATCH 1/3] Support for N-dimensional arrays in simulation --- kernel/fstdata.cc | 34 +++++++++++++++++++++++++--------- kernel/fstdata.h | 4 ++-- passes/sat/sim.cc | 33 +++++++++++++++++---------------- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index 7aee18837..5244a0395 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -103,11 +103,11 @@ dict FstData::getMemoryHandles(std::string name) { return dict(); }; -dict FstData::getArrayHandles(std::string name) { +dict,fstHandle> FstData::getArrayHandles(std::string name) { if (array_to_handle.find(name) != array_to_handle.end()) return array_to_handle[name]; else - return dict(); + return dict,fstHandle>(); }; static std::string remove_spaces(std::string str) @@ -213,22 +213,38 @@ void FstData::extractVarNames() } } } else { - // Handle "signal [index][bitrange]" format + + // Handle "signal [i0][i1]...[iN][bitrange]" format std::string full_name = h->u.var.name; size_t space_pos = full_name.find(' '); if (space_pos != std::string::npos) { + + // Extract "[i0][i1]...[iN][bitrange]" suffix std::string suffix = full_name.substr(space_pos + 1); - // Parse first bracket pair for array index - if (!suffix.empty() && suffix[0] == '[') { - size_t close_bracket = suffix.find(']'); - if (close_bracket != std::string::npos) { - std::string index_str = suffix.substr(1, close_bracket - 1); + + // Parse arbitrary number of array indices + size_t open = 0; + std::vector array_indices; + while (open < suffix.length() && suffix[open] == '[') { + + size_t close = suffix.find(']', open); + if (close != std::string::npos) { + std::string index_str = suffix.substr(open + 1, close - open - 1); + // Check it's an array index (no colon), not a bit range if (index_str.find(':') == std::string::npos) { int array_index = std::stoi(index_str); - array_to_handle[var.scope+"."+clean_name][array_index] = var.id; + array_indices.push_back(array_index); } } + + // Move to next opening bracket + open = close + 1; + } + + // Add array indices to array_to_handle map if there are any + if (!array_indices.empty()) { + array_to_handle[var.scope+"."+clean_name][array_indices] = var.id; } } } diff --git a/kernel/fstdata.h b/kernel/fstdata.h index 87a7f3eb7..a7a269da6 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -55,7 +55,7 @@ class FstData std::string valueOf(fstHandle signal); fstHandle getHandle(std::string name); dict getMemoryHandles(std::string name); - dict getArrayHandles(std::string name); + dict,fstHandle> getArrayHandles(std::string name); double getTimescale() { return timescale; } const char *getTimescaleString() { return timescale_str.c_str(); } int getWidth(fstHandle signal); @@ -68,7 +68,7 @@ private: std::map handle_to_var; std::map name_to_handle; std::map> memory_to_handle; - std::map> array_to_handle; + std::map, fstHandle>> array_to_handle; std::map last_data; uint64_t last_time; std::map past_data; diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 65bddbe00..f11075dbd 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -225,15 +225,15 @@ struct SimInstance dict> fst_memories; // For multi-dimensional arrays - dict> fst_array_handles; - dict> fst_array_inputs; + dict,fstHandle>> fst_array_handles; + dict,fstHandle>> fst_array_inputs; // Helper function to detect and retrieve array element handles // Returns non-empty dict if wire is a multi-dimensional array split in VCD - dict tryGetArrayHandles(FstData* fst, const std::string& scope, Wire* wire) + dict, fstHandle> tryGetArrayHandles(FstData* fst, const std::string& scope, Wire* wire) { std::string wire_name = scope + "." + RTLIL::unescape_id(wire->name); - dict array_handles = fst->getArrayHandles(wire_name); + dict, fstHandle> array_handles = fst->getArrayHandles(wire_name); if (!array_handles.empty()) { int total_width = 0; @@ -250,25 +250,26 @@ struct SimInstance log_warning("Array wire '%s' found in VCD (total width %d) but does not match Yosys wire width %d; skipping.\n", wire_name.c_str(), total_width, wire->width); } - return dict(); + return dict, fstHandle>(); } // Helper function to set wire state from array element handles // Concatenates values from array elements in descending index order - bool setStateFromArrayHandles(Wire* wire, dict& handles) + bool setStateFromArrayHandles(Wire* wire, dict, fstHandle>& handles) { - // Collect and sort indices in descending order (MSB = highest index) - std::vector indices; - for (auto &kv : handles) - indices.push_back(kv.first); - std::sort(indices.begin(), indices.end(), std::greater()); + // Collect and sort indices in descending row-major orde + std::vector, fstHandle>> sorted_elements; + for (auto &kv : handles) { + sorted_elements.push_back({kv.first, kv.second}); + } + std::sort(sorted_elements.begin(), sorted_elements.end(), std::greater<>()); // Concatenate values in descending index order - std::string concatenated = ""; - for (int idx : indices) { - concatenated += shared->fst->valueOf(handles[idx]); - } - return set_state(wire, Const::from_string(concatenated)); + std::string concatenated = ""; + for (auto &elem : sorted_elements) { + concatenated += shared->fst->valueOf(elem.second); + } + return set_state(wire, Const::from_string(concatenated)); } SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : From 286303deca8e583c6b458e2dfd93f9ac4e1802dd Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 31 Mar 2026 12:57:27 -0700 Subject: [PATCH 2/3] Compilation fix --- passes/sat/sim.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index f11075dbd..d6d2de649 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -308,7 +308,7 @@ struct SimInstance fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); // Try to get array element handles if this is a multi-dimensional array - dict array_handles = tryGetArrayHandles(shared->fst, scope, wire); + dict, fstHandle> array_handles = tryGetArrayHandles(shared->fst, scope, wire); if (!array_handles.empty()) { // Must be an array, store in fst_array_handles fst_array_handles[wire] = array_handles; @@ -1591,7 +1591,7 @@ struct SimWorker : SimShared fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); // Try to get array element handles if this is a multi-dimensional array - dict array_handles = top->tryGetArrayHandles(fst, scope, wire); + dict, fstHandle> array_handles = top->tryGetArrayHandles(fst, scope, wire); if (!array_handles.empty()) { // Must be an array, store in fst_array_inputs top->fst_array_inputs[wire] = array_handles; From 91345c2283f7a83a818dd189aa9ad620feb1d494 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 1 Apr 2026 09:21:02 -0700 Subject: [PATCH 3/3] warning msg and address spaces --- kernel/fstdata.cc | 3 +++ passes/sat/sim.cc | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index 5244a0395..42f2f76e0 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -236,6 +236,9 @@ void FstData::extractVarNames() int array_index = std::stoi(index_str); array_indices.push_back(array_index); } + } else { + log_warning("Error parsing array index in : %s\n", full_name.c_str()); + break; } // Move to next opening bracket diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index d6d2de649..d0c6d8748 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -257,19 +257,19 @@ struct SimInstance // Concatenates values from array elements in descending index order bool setStateFromArrayHandles(Wire* wire, dict, fstHandle>& handles) { - // Collect and sort indices in descending row-major orde - std::vector, fstHandle>> sorted_elements; - for (auto &kv : handles) { - sorted_elements.push_back({kv.first, kv.second}); - } + // Collect and sort indices in descending row-major order + std::vector, fstHandle>> sorted_elements; + for (auto &kv : handles) { + sorted_elements.push_back({kv.first, kv.second}); + } std::sort(sorted_elements.begin(), sorted_elements.end(), std::greater<>()); - + // Concatenate values in descending index order - std::string concatenated = ""; - for (auto &elem : sorted_elements) { - concatenated += shared->fst->valueOf(elem.second); - } - return set_state(wire, Const::from_string(concatenated)); + std::string concatenated = ""; + for (auto &elem : sorted_elements) { + concatenated += shared->fst->valueOf(elem.second); + } + return set_state(wire, Const::from_string(concatenated)); } SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :