@@ -105,6 +105,12 @@ namespace hal
105105
106106 return result;
107107 }
108+
109+ igraph_error_t
110+ in_callback ( const igraph_t *graph, igraph_integer_t vid, igraph_integer_t dist, void *extra )
111+ {
112+ return igraph_vector_int_push_back ( (igraph_vector_int_t *) extra, vid );
113+ }
108114 } // namespace
109115
110116 ClockTree::ClockTree ( const Netlist *netlist )
@@ -113,6 +119,25 @@ namespace hal
113119 {
114120 }
115121
122+ ClockTree::ClockTree ( const Netlist *netlist,
123+ igraph_t &&igraph,
124+ std::unordered_set<igraph_integer_t > &&roots,
125+ std::unordered_map<igraph_integer_t , const void *> &&vertices_to_ptrs,
126+ std::unordered_map<const void *, PtrType> &&ptrs_to_types )
127+ : m_netlist( netlist )
128+ , m_igraph( std::move( igraph ) )
129+ , m_roots( std::move( roots ) )
130+ , m_vertices_to_ptrs( std::move( vertices_to_ptrs ) )
131+ , m_ptrs_to_types( std::move( ptrs_to_types ) )
132+ {
133+ m_igraph_ptr = &m_igraph;
134+
135+ for ( const auto &[vertex, ptr] : m_vertices_to_ptrs )
136+ {
137+ m_ptrs_to_vertices[ptr] = vertex;
138+ }
139+ }
140+
116141 ClockTree::~ClockTree ()
117142 {
118143 igraph_destroy ( &m_igraph );
@@ -127,7 +152,7 @@ namespace hal
127152
128153 std::unordered_set<void *> vertices;
129154 std::unordered_set<std::pair<void *, void *>, VoidPtrHash> edges;
130- std::unordered_map<const void *, std::string > ptrs_to_type;
155+ std::unordered_map<const void *, PtrType > ptrs_to_type;
131156
132157 std::queue<std::pair<const Gate *, const Gate *>> queue;
133158 NetlistTraversalDecorator ntd = NetlistTraversalDecorator ( *netlist );
@@ -165,7 +190,7 @@ namespace hal
165190 else if ( clk->is_global_input_net () )
166191 {
167192 vertices.insert ( (void *) clk );
168- ptrs_to_type[(void *) clk] = " net " ;
193+ ptrs_to_type[(void *) clk] = PtrType::NET ;
169194 continue ;
170195 }
171196 else if ( clk->get_num_of_sources () == 0 )
@@ -176,7 +201,7 @@ namespace hal
176201 queue.push ( { ff, clk->get_sources ().front ()->get_gate () } );
177202
178203 vertices.insert ( (void *) ff );
179- ptrs_to_type[(void *) ff] = " gate " ;
204+ ptrs_to_type[(void *) ff] = PtrType::GATE ;
180205 }
181206
182207 const std::unordered_set<const Gate *> toggle_ffs = get_toggle_ffs ( netlist );
@@ -205,8 +230,8 @@ namespace hal
205230 vertices.insert ( (void *) source );
206231 vertices.insert ( (void *) reference );
207232
208- ptrs_to_type[(void *) source] = " gate " ;
209- ptrs_to_type[(void *) reference] = " gate " ;
233+ ptrs_to_type[(void *) source] = PtrType::GATE ;
234+ ptrs_to_type[(void *) reference] = PtrType::GATE ;
210235
211236 edges.insert ( { (void *) source, (void *) reference } );
212237
@@ -240,8 +265,8 @@ namespace hal
240265 vertices.insert ( (void *) net );
241266 vertices.insert ( (void *) reference );
242267
243- ptrs_to_type[(void *) net] = " net " ;
244- ptrs_to_type[(void *) reference] = " gate " ;
268+ ptrs_to_type[(void *) net] = PtrType::NET ;
269+ ptrs_to_type[(void *) reference] = PtrType::GATE ;
245270
246271 edges.insert ( { (void *) net, (void *) reference } );
247272 continue ;
@@ -347,7 +372,7 @@ namespace hal
347372
348373 for ( const auto &[ptr, vertex] : m_ptrs_to_vertices )
349374 {
350- if ( m_ptrs_to_types.at ( ptr ) == " net " )
375+ if ( m_ptrs_to_types.at ( ptr ) == PtrType::NET )
351376 {
352377 dot_fd << " " << ( (Net *) ptr )->get_name () << " [shape=circle];\n " ;
353378 continue ;
@@ -400,9 +425,9 @@ namespace hal
400425 visited.insert ( vertex );
401426
402427 const void *sptr = m_vertices_to_ptrs.at ( vertex );
403- const std::string stype = m_ptrs_to_types.at ( sptr );
428+ const PtrType stype = m_ptrs_to_types.at ( sptr );
404429
405- if ( stype == " gate " && is_inverter ( (Gate *) sptr ) )
430+ if ( stype == PtrType::GATE && is_inverter ( (Gate *) sptr ) )
406431 {
407432 edge_color = edge_color == " red" ? " blue" : " red" ;
408433 }
@@ -423,13 +448,13 @@ namespace hal
423448
424449 for ( igraph_integer_t idx = 0 ; idx < igraph_vector_int_size ( &neighbors ); idx++ )
425450 {
426- const std::string src_id =
427- stype == " gate " ? std::to_string ( ( (Gate *) sptr )-> get_id () ) : ( (Net *) sptr )->get_name ();
451+ const std::string src_id = stype == PtrType::GATE ? std::to_string ( ( (Gate *) sptr )-> get_id () )
452+ : ( (Net *) sptr )->get_name ();
428453
429454 const void *dptr = m_vertices_to_ptrs.at ( VECTOR ( neighbors )[idx] );
430- const std::string dtype = m_ptrs_to_types.at ( dptr );
431- const std::string dst_id =
432- dtype == " gate " ? std::to_string ( ( (Gate *) dptr )-> get_id () ) : ( (Net *) dptr )->get_name ();
455+ const PtrType dtype = m_ptrs_to_types.at ( dptr );
456+ const std::string dst_id = dtype == PtrType::GATE ? std::to_string ( ( (Gate *) dptr )-> get_id () )
457+ : ( (Net *) dptr )->get_name ();
433458
434459 dot_fd << " " << src_id << " -> " << dst_id << " [color=" << edge_color << " ];\n " ;
435460 queue.push ( { VECTOR ( neighbors )[idx], edge_color } );
@@ -444,6 +469,164 @@ namespace hal
444469 return OK ( {} );
445470 }
446471
472+ Result<std::unique_ptr<ClockTree>> ClockTree::get_subtree ( const void *ptr ) const
473+ {
474+ auto it = m_ptrs_to_vertices.find ( ptr );
475+ if ( it == m_ptrs_to_vertices.end () )
476+ {
477+ return ERR ( " object is not part of clock tree" );
478+ }
479+
480+ const igraph_integer_t root = it->second ;
481+
482+ igraph_error_t ierror;
483+ igraph_vector_int_t vertices;
484+ if ( ( ierror = igraph_vector_int_init ( &vertices, 0 ) ) != IGRAPH_SUCCESS )
485+ {
486+ return ERR ( igraph_strerror ( ierror ) );
487+ }
488+
489+ if ( ( ierror = igraph_dfs ( m_igraph_ptr,
490+ root,
491+ IGRAPH_OUT,
492+ false ,
493+ nullptr ,
494+ nullptr ,
495+ nullptr ,
496+ nullptr ,
497+ in_callback,
498+ nullptr ,
499+ &vertices ) )
500+ != IGRAPH_SUCCESS )
501+ {
502+ igraph_vector_int_destroy ( &vertices );
503+ return ERR ( igraph_strerror ( ierror ) );
504+ }
505+
506+ igraph_vs_t vs;
507+ if ( ( ierror = igraph_vs_vector ( &vs, &vertices ) ) != IGRAPH_SUCCESS )
508+ {
509+ igraph_vector_int_destroy ( &vertices );
510+ return ERR ( igraph_strerror ( ierror ) );
511+ }
512+
513+ igraph_vector_int_t map;
514+ if ( ( ierror = igraph_vector_int_init ( &map, igraph_vcount ( m_igraph_ptr ) ) ) != IGRAPH_SUCCESS )
515+ {
516+ return ERR ( igraph_strerror ( ierror ) );
517+ }
518+
519+ igraph_t igraph;
520+ if ( ( ierror =
521+ igraph_induced_subgraph_map ( m_igraph_ptr, &igraph, vs, IGRAPH_SUBGRAPH_AUTO, &map, nullptr ) )
522+ != IGRAPH_SUCCESS )
523+ {
524+ igraph_vs_destroy ( &vs );
525+ igraph_vector_int_destroy ( &map );
526+ igraph_vector_int_destroy ( &vertices );
527+ return ERR ( igraph_strerror ( ierror ) );
528+ }
529+
530+ igraph_vs_destroy ( &vs );
531+ igraph_vector_int_destroy ( &vertices );
532+
533+ std::unordered_set<igraph_integer_t > roots;
534+ std::unordered_map<const void *, PtrType> ptrs_to_types;
535+ std::unordered_map<igraph_integer_t , const void *> vertices_to_ptrs;
536+
537+ for ( igraph_integer_t idx = 0 ; idx < igraph_vector_int_size ( &map ); idx++ )
538+ {
539+ const igraph_integer_t vertex = VECTOR ( map )[idx];
540+ if ( vertex == 0 )
541+ {
542+ continue ;
543+ }
544+
545+ const void *ptr = m_vertices_to_ptrs.at ( idx );
546+
547+ vertices_to_ptrs[vertex - 1 ] = ptr;
548+ ptrs_to_types[ptr] = m_ptrs_to_types.at ( ptr );
549+ }
550+
551+ igraph_vector_int_destroy ( &map );
552+
553+ igraph_vector_int_t indegrees;
554+ if ( ( ierror = igraph_vector_int_init ( &indegrees, igraph_vcount ( &igraph ) ) ) != IGRAPH_SUCCESS )
555+ {
556+ return ERR ( igraph_strerror ( ierror ) );
557+ }
558+
559+ if ( ( ierror = igraph_degree ( &igraph, &indegrees, igraph_vss_all (), IGRAPH_IN, IGRAPH_NO_LOOPS ) )
560+ != IGRAPH_SUCCESS )
561+ {
562+ igraph_vector_int_destroy ( &indegrees );
563+ return ERR ( igraph_strerror ( ierror ) );
564+ }
565+
566+ for ( igraph_integer_t idx = 0 ; idx < igraph_vector_int_size ( &indegrees ); idx++ )
567+ {
568+ if ( VECTOR ( indegrees )[idx] != 0 )
569+ {
570+ continue ;
571+ }
572+ roots.insert ( idx );
573+ }
574+
575+ igraph_vector_int_destroy ( &indegrees );
576+
577+ return OK ( std::make_unique<ClockTree>( m_netlist,
578+ std::move ( igraph ),
579+ std::move ( roots ),
580+ std::move ( vertices_to_ptrs ),
581+ std::move ( ptrs_to_types ) ) );
582+ }
583+
584+ Result<igraph_integer_t > ClockTree::get_vertex_from_ptr ( const void *ptr ) const
585+ {
586+ auto it = m_ptrs_to_vertices.find ( ptr );
587+ if ( it == m_ptrs_to_vertices.end () )
588+ {
589+ return ERR ( " object is not part of clock tree" );
590+ }
591+
592+ return OK ( it->second );
593+ }
594+
595+ const std::vector<const Gate *> ClockTree::get_gates () const
596+ {
597+ std::vector<const Gate *> result;
598+
599+ for ( const auto &[ptr, type] : m_ptrs_to_types )
600+ {
601+ if ( type == PtrType::GATE )
602+ {
603+ result.push_back ( (const Gate *) ptr );
604+ }
605+ }
606+
607+ return result;
608+ }
609+
610+ const std::vector<const Net *> ClockTree::get_nets () const
611+ {
612+ std::vector<const Net *> result;
613+
614+ for ( const auto &[ptr, type] : m_ptrs_to_types )
615+ {
616+ if ( type == PtrType::NET )
617+ {
618+ result.push_back ( (const Net *) ptr );
619+ }
620+ }
621+
622+ return result;
623+ }
624+
625+ const std::unordered_map<const void *, PtrType> ClockTree::get_all () const
626+ {
627+ return m_ptrs_to_types;
628+ }
629+
447630 const Netlist *ClockTree::get_netlist () const
448631 {
449632 return m_netlist;
@@ -458,3 +641,6 @@ namespace hal
458641
459642// BUG: looks like ~20 vertices plus their edges are missing in benchmark
460643// TODO: investigate possible BUG
644+
645+ // BUG: subtree is wrong
646+ // TODO: investigate why? Probably mapping is broken
0 commit comments