Skip to content

Commit 2164d55

Browse files
start to implement methods to query clock tree
1 parent 62e9afa commit 2164d55

File tree

3 files changed

+254
-20
lines changed

3 files changed

+254
-20
lines changed

plugins/clock_tree_extractor/include/clock_tree_extractor/clock_tree.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#pragma once
2828

29+
#include "graph_algorithm/netlist_graph.h"
2930
#include "hal_core/defines.h"
3031
#include "hal_core/utilities/result.h"
3132

@@ -56,22 +57,32 @@ namespace hal
5657
{
5758
namespace cte
5859
{
60+
enum PtrType { UNKNOWN, GATE, NET };
61+
5962
class ClockTree
6063
{
6164
public:
65+
ClockTree( const Netlist *netlist,
66+
igraph_t &&graph,
67+
std::unordered_set<igraph_integer_t> &&roots,
68+
std::unordered_map<igraph_integer_t, const void *> &&m_vertices_to_ptrs,
69+
std::unordered_map<const void *, PtrType> &&m_ptrs_to_types );
70+
6271
~ClockTree();
6372

6473
static Result<std::unique_ptr<ClockTree>> from_netlist( const Netlist *netlist );
6574

6675
Result<std::monostate> export_dot( const std::string &pathname ) const;
6776

68-
const Gate *get_gate_from_vertex( igraph_integer_t vertex ) const;
77+
Result<std::unique_ptr<ClockTree>> get_subtree( const void *ptr ) const;
78+
79+
Result<igraph_integer_t> get_vertex_from_ptr( const void *ptr ) const;
6980

70-
const igraph_integer_t get_vertex_from_gate( const Gate *gate ) const;
81+
const std::vector<const Gate *> get_gates() const;
7182

72-
const Net *get_net_from_vertex( igraph_integer_t vertex ) const;
83+
const std::vector<const Net *> get_nets() const;
7384

74-
const igraph_integer_t get_vertex_from_net( const Net *net ) const;
85+
const std::unordered_map<const void *, PtrType> get_all() const;
7586

7687
const Netlist *get_netlist() const;
7788

@@ -94,7 +105,7 @@ namespace hal
94105

95106
std::unordered_map<const void *, igraph_integer_t> m_ptrs_to_vertices;
96107

97-
std::unordered_map<const void *, std::string> m_ptrs_to_types;
108+
std::unordered_map<const void *, PtrType> m_ptrs_to_types;
98109
};
99110
} // namespace cte
100111
} // namespace hal

plugins/clock_tree_extractor/python/python_bindings.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,43 @@ namespace hal
125125
},
126126
py::arg( "pathname" ),
127127
R"()" )
128+
.def(
129+
"get_subtree",
130+
[]( const cte::ClockTree &self, const void *ptr ) -> std::unique_ptr<cte::ClockTree> {
131+
auto result = self.get_subtree( ptr );
132+
if( result.is_ok() )
133+
{
134+
return result.get();
135+
}
136+
137+
log_error( "clock_tree_extractor", "{}", result.get_error().get() );
138+
return nullptr;
139+
},
140+
py::arg( "ptr" ),
141+
py::return_value_policy::move,
142+
R"()" )
143+
.def(
144+
"get_all",
145+
[]( const cte::ClockTree &self ) -> py::list {
146+
py::list result;
147+
const auto &map = self.get_all();
148+
for( auto &[ptr, type] : map )
149+
{
150+
if( type == cte::PtrType::GATE )
151+
{
152+
result.append( py::cast( (const Gate *) ptr ) );
153+
}
154+
else if( type == cte::PtrType::NET )
155+
{
156+
result.append( py::cast( (const Net *) ptr ) );
157+
}
158+
}
159+
return result;
160+
},
161+
R"()" )
162+
.def( "get_vertex_from_ptr", &cte::ClockTree::get_vertex_from_ptr, R"()" )
163+
.def( "get_gates", &cte::ClockTree::get_gates, R"()" )
164+
.def( "get_nets", &cte::ClockTree::get_nets, R"()" )
128165
.def( "get_netlist", &cte::ClockTree::get_netlist, R"()" );
129166

130167
#ifndef PYBIND11_MODULE

plugins/clock_tree_extractor/src/clock_tree.cpp

Lines changed: 201 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)