@@ -123,10 +123,40 @@ bool CircuitValidator::setOverlapsUnpositioned() {
123123 return true ;
124124}
125125
126+
127+ // iterative dfs
128+ template <class PreVisit , class PostVisit >
129+ void depthFirstSearch (const std::unordered_map<block_id_t , std::vector<block_id_t >>& adj, block_id_t start, std::unordered_set<block_id_t >& visited, PreVisit preVisit, PostVisit postVisit) {
130+ std::stack<block_id_t > stack;
131+ stack.push (start);
132+ visited.insert (start);
133+ preVisit (start);
134+ while (!stack.empty ()) {
135+ block_id_t node = stack.top ();
136+ bool hasUnvisited = false ;
137+ if (adj.count (node)){
138+ for (block_id_t neighbor : adj.at (node)) {
139+ if (visited.count (neighbor)) continue ;
140+ visited.insert (neighbor);
141+ preVisit (neighbor);
142+ stack.push (neighbor);
143+ hasUnvisited = true ;
144+ break ;
145+ }
146+ }
147+
148+ if (!hasUnvisited) {
149+ stack.pop ();
150+ postVisit (node);
151+ }
152+ }
153+ }
154+
126155// SCC META GRAPH TOPOLOGICAL SORT
127156bool CircuitValidator::handleUnpositionedBlocks () {
128157 // Separate components so that we can place down disconnected components independently
129158 std::unordered_map<block_id_t , std::vector<block_id_t >> undirectedAdj;
159+ undirectedAdj.reserve (parsedCircuit.blocks .size ());
130160 for (const ParsedCircuit::ConnectionData& conn : parsedCircuit.connections ) {
131161 block_id_t u = conn.inputBlockId ;
132162 block_id_t v = conn.outputBlockId ;
@@ -136,94 +166,64 @@ bool CircuitValidator::handleUnpositionedBlocks() {
136166
137167 // find cc's by dfs
138168 std::vector<std::unordered_set<block_id_t >> components;
169+ std::unordered_map<block_id_t , int > blockToComponent;
139170 std::unordered_set<block_id_t > visited;
140- std::function<void (block_id_t )> dfsComponent = [&](block_id_t node) {
141- visited.insert (node);
142- components.back ().insert (node);
143- for (block_id_t neighbor : undirectedAdj[node]) {
144- if (!visited.count (neighbor)) {
145- dfsComponent (neighbor);
146- }
147- }
148- };
149171 for (const auto & [id, block] : parsedCircuit.blocks ) {
150172 if (!visited.count (id)) {
151173 components.push_back ({});
152- dfsComponent (id );
174+ depthFirstSearch (undirectedAdj, id, visited, [&]( block_id_t node){components. back (). insert (node); blockToComponent[node] = components. size ()- 1 ;}, [&]( block_id_t ){} );
153175 }
154176 }
155177
156- const int componentSpacing = 5 ;
157- int currentYOffset = 0 ;
158- int ccIndex = 0 ;
159- for (const std::unordered_set<block_id_t >& cc: components){
160- logInfo (" Parsing CC " + std::to_string (++ccIndex));
161-
162- // adjacency list
163- std::unordered_map<block_id_t , std::vector<block_id_t >> adj;
164- for (const auto & conn : parsedCircuit.connections ) {
165- if (cc.count (conn.inputBlockId ) && cc.count (conn.outputBlockId )) {
166- block_id_t to = conn.outputBlockId ;
167- block_id_t from = conn.inputBlockId ;
168- // logInfo("From: " + std::to_string(from) + "("+std::to_string(conn.outputId)+")" +
169- // ", To: " + std::to_string(to) + "("+std::to_string(conn.inputId)+")");
170- if (blockDataManager->isConnectionInput (parsedCircuit.blocks .at (conn.outputBlockId ).type , conn.outputId )){
171- adj[from].push_back (to);
172- }
173- }
178+ // preprocess connected component connections
179+ std::vector<std::unordered_map<block_id_t ,std::vector<block_id_t >>> componentAdjs (components.size ());
180+ for (const ParsedCircuit::ConnectionData& conn : parsedCircuit.connections ) {
181+ if (blockDataManager->isConnectionInput (parsedCircuit.blocks .at (conn.outputBlockId ).type ,conn.outputId )){
182+ int cc = blockToComponent[conn.inputBlockId ];
183+ componentAdjs[cc][conn.inputBlockId ].push_back (conn.outputBlockId );
174184 }
185+ }
175186
176- // find SCC metagraph DAG for topological sort using kosaraju's
177- std::unordered_map<block_id_t , std::vector<block_id_t >> revAdj;
178- std::stack<block_id_t > postNumber; // highest post number node is a part of a source SCC, run on G^R
179- std::vector<std::vector<block_id_t >> sccs;
187+ // precompute input connections for each block for layer placement
188+ std::unordered_map<block_id_t , std::vector<block_id_t >> inputConnections;
189+ for (const auto & conn : parsedCircuit.connections ) {
190+ inputConnections[conn.inputBlockId ].push_back (conn.outputBlockId );
191+ }
180192
181- std::function<void (block_id_t )> dfs =
182- [&](block_id_t node) -> void {
183- visited.insert (node);
184- for (block_id_t v : adj[node]) {
185- if (!visited.count (v)) {
186- dfs (v);
187- }
188- }
189- postNumber.push (node); // post visit
190- };
191-
192- std::function<void (block_id_t , std::vector<block_id_t >&)> dfsRev =
193- [&](block_id_t node, std::vector<block_id_t >& component) -> void {
194- visited.insert (node);
195- component.push_back (node);
196- for (block_id_t v : revAdj[node]) {
197- if (!visited.count (v)) {
198- dfsRev (v, component);
199- }
200- }
201- };
193+ const int componentSpacing = 5 ;
194+ int currentYOffset = 0 ;
195+ for (int ccIndex=0 ; ccIndex<componentAdjs.size (); ++ccIndex){
196+ const std::unordered_map<block_id_t , std::vector<block_id_t >>& adj = componentAdjs[ccIndex];
197+ logInfo (" Parsing CC " + std::to_string (ccIndex));
202198
199+ // find SCC metagraph DAG for topological sort using kosaraju's
203200 // gather stack that shows decreasing post visit numbers
201+ std::stack<block_id_t > postNumber; // highest post number node is a part of a source SCC, run on G^R
204202 visited.clear ();
205- for (block_id_t id : cc ) {
203+ for (block_id_t id : components[ccIndex] ) {
206204 if (!visited.count (id)) {
207- dfs (id );
205+ depthFirstSearch (adj, id, visited, [&]( block_id_t ){}, [&]( block_id_t node){postNumber. push (node);} );
208206 }
209207 }
210208
211209 // make reverse graph in adjacency list
210+ std::unordered_map<block_id_t , std::vector<block_id_t >> revAdj;
212211 for (const auto & [u, adjs] : adj) {
213212 for (block_id_t v : adjs) {
214213 revAdj[v].push_back (u);
215214 }
216215 }
217216
218217 // run dfs from source SCC's in reverse graph, sink SCCs of regular
218+ std::vector<std::vector<block_id_t >> sccs;
219219 visited.clear ();
220220 while (!postNumber.empty ()) {
221221 block_id_t node = postNumber.top ();
222222 postNumber.pop ();
223223 if (!visited.count (node)) {
224- std::vector<block_id_t > component ;
225- dfsRev ( node, component );
226- sccs.push_back (component );
224+ std::vector<block_id_t > revCC ;
225+ depthFirstSearch (adj, node, visited, [&]( block_id_t node){revCC. push_back (node);}, [&]( block_id_t ){} );
226+ sccs.push_back (revCC );
227227 }
228228 }
229229
@@ -275,12 +275,13 @@ bool CircuitValidator::handleUnpositionedBlocks() {
275275 }
276276
277277 std::unordered_map<block_id_t , int > layers;
278- for (int sccIndex : sccOrder) {
279- for (block_id_t id : sccs[sccIndex ]) {
278+ for (int sccIdx : sccOrder) {
279+ for (block_id_t id : sccs[sccIdx ]) {
280280 int maxLayer = 0 ;
281- for (const auto & conn : parsedCircuit.connections ) {
282- if (conn.inputBlockId == id) {
283- maxLayer = std::max (maxLayer, layers[conn.outputBlockId ] + 1 );
281+ auto it = inputConnections.find (id);
282+ if (it != inputConnections.end ()) {
283+ for (block_id_t outputBlock : it->second ) {
284+ maxLayer = std::max (maxLayer, layers[outputBlock] + 1 );
284285 }
285286 }
286287 layers[id] = maxLayer;
0 commit comments