|
3 | 3 |
|
4 | 4 | #include "dbSdcNetwork.hh" |
5 | 5 |
|
| 6 | +#include <spdlog/fmt/fmt.h> |
| 7 | + |
6 | 8 | #include <memory> |
7 | 9 | #include <string> |
| 10 | +#include <string_view> |
8 | 11 |
|
9 | 12 | #include "sta/ParseBus.hh" |
10 | 13 | #include "sta/PatternMatch.hh" |
@@ -62,14 +65,47 @@ InstanceSeq dbSdcNetwork::findInstancesMatching( |
62 | 65 | void dbSdcNetwork::findInstancesMatching1(const PatternMatch* pattern, |
63 | 66 | InstanceSeq& insts) const |
64 | 67 | { |
65 | | - std::unique_ptr<InstanceChildIterator> child_iter{ |
66 | | - childIterator(topInstance())}; |
67 | | - while (child_iter->hasNext()) { |
68 | | - Instance* child = child_iter->next(); |
69 | | - if (pattern->match(staToSdc(name(child)))) { |
70 | | - insts.push_back(child); |
| 68 | + // A recursive lambda to traverse the design hierarchy with a depth-first |
| 69 | + // search (DFS). |
| 70 | + // It builds the hierarchical path incrementally using fmt::memory_buffer to |
| 71 | + // avoid expensive std::string allocations and copies at each step. |
| 72 | + std::function<void(Instance*, fmt::memory_buffer&)> dfs_search |
| 73 | + = [&, this](Instance* instance, fmt::memory_buffer& path_buffer) -> void { |
| 74 | + // Iterate over the children of the current instance. |
| 75 | + std::unique_ptr<InstanceChildIterator> child_iter{childIterator(instance)}; |
| 76 | + while (child_iter->hasNext()) { |
| 77 | + Instance* child = child_iter->next(); |
| 78 | + |
| 79 | + // Save the current size of the buffer to restore it later. |
| 80 | + const size_t original_size = path_buffer.size(); |
| 81 | + |
| 82 | + // Build the child's full path name incrementally. |
| 83 | + if (original_size > 0) { |
| 84 | + path_buffer.push_back(pathDivider()); |
| 85 | + } |
| 86 | + path_buffer.append(std::string_view(name(child))); |
| 87 | + |
| 88 | + // Check if the child instance name matches the pattern. |
| 89 | + // Add a null terminator for C-style string compatibility. |
| 90 | + path_buffer.push_back('\0'); |
| 91 | + if (pattern->match(staToSdc(path_buffer.data()))) { |
| 92 | + insts.push_back(child); |
| 93 | + } |
| 94 | + path_buffer.resize(path_buffer.size() - 1); // Remove the null terminator |
| 95 | + |
| 96 | + // Recurse into the child's hierarchy if it's not a leaf. |
| 97 | + if (!isLeaf(child)) { |
| 98 | + dfs_search(child, path_buffer); |
| 99 | + } |
| 100 | + |
| 101 | + // Restore the buffer to its original state for the next sibling. |
| 102 | + path_buffer.resize(original_size); |
71 | 103 | } |
72 | | - } |
| 104 | + }; |
| 105 | + |
| 106 | + // Start the search from the top-level instance. |
| 107 | + fmt::memory_buffer path_buffer; |
| 108 | + dfs_search(topInstance(), path_buffer); |
73 | 109 | } |
74 | 110 |
|
75 | 111 | NetSeq dbSdcNetwork::findNetsMatching(const Instance*, |
|
0 commit comments