Skip to content

Commit abc94cb

Browse files
extend api for bt
1 parent db19f29 commit abc94cb

File tree

3 files changed

+170
-24
lines changed

3 files changed

+170
-24
lines changed

plugins/clock_tree_extractor/include/clock_tree_extractor/clock_tree.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,23 @@ namespace hal
5959
{
6060
enum PtrType { UNKNOWN, GATE, NET };
6161

62+
struct VoidPtrHash
63+
{
64+
std::size_t operator()( const std::pair<const void *, const void *> &pair ) const noexcept
65+
{
66+
return std::hash<const void *>()( pair.first ) ^ ( std::hash<const void *>()( pair.second ) << 1 );
67+
}
68+
};
69+
70+
struct PairPtrEq
71+
{
72+
bool operator()( const std::pair<const void *, const void *> &p1,
73+
const std::pair<const void *, const void *> &p2 ) const noexcept
74+
{
75+
return p1.first == p2.first && p1.second == p2.second;
76+
}
77+
};
78+
6279
class ClockTree
6380
{
6481
public:
@@ -74,6 +91,9 @@ namespace hal
7491

7592
Result<std::monostate> export_dot( const std::string &pathname ) const;
7693

94+
Result<std::vector<std::pair<const void *, PtrType>>> get_neighbors( const void *ptr,
95+
igraph_neimode_t direction ) const;
96+
7797
Result<std::unique_ptr<ClockTree>> get_subtree( const void *ptr, const bool parent ) const;
7898

7999
Result<igraph_integer_t> get_vertex_from_ptr( const void *ptr ) const;
@@ -85,6 +105,10 @@ namespace hal
85105
Result<std::vector<std::pair<const void *, PtrType>>>
86106
get_ptrs_from_vertices( const std::vector<igraph_integer_t> &vertices ) const;
87107

108+
const std::
109+
unordered_map<std::pair<const void *, const void *>, std::vector<const Gate *>, VoidPtrHash, PairPtrEq>
110+
get_paths() const;
111+
88112
const std::vector<const Gate *> get_gates() const;
89113

90114
const std::vector<const Net *> get_nets() const;
@@ -113,6 +137,9 @@ namespace hal
113137
std::unordered_map<const void *, igraph_integer_t> m_ptrs_to_vertices;
114138

115139
std::unordered_map<const void *, PtrType> m_ptrs_to_types;
140+
141+
std::unordered_map<std::pair<const void *, const void *>, std::vector<const Gate *>, VoidPtrHash, PairPtrEq>
142+
m_paths;
116143
};
117144
} // namespace cte
118145
} // namespace hal

plugins/clock_tree_extractor/python/python_bindings.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,86 @@ namespace hal
240240
},
241241
py::arg( "vertices" ),
242242
R"()" )
243+
.def(
244+
"get_paths",
245+
[]( const cte::ClockTree &self ) -> py::dict {
246+
auto res = self.get_paths();
247+
py::dict result;
248+
for( const auto &[key, val] : res )
249+
{
250+
py::tuple py_key( 2 );
251+
py_key[0] = py::cast( (const Gate *) key.first );
252+
py_key[1] = py::cast( (const Gate *) key.second );
253+
py::list py_val;
254+
for( const Gate *gate : val )
255+
{
256+
py_val.append( gate );
257+
}
258+
result[py_key] = py_val;
259+
}
260+
return result;
261+
},
262+
R"()" )
263+
.def(
264+
"get_parents",
265+
[]( const cte::ClockTree &self, const void *ptr ) -> py::list {
266+
auto res = self.get_neighbors( ptr, IGRAPH_IN );
267+
if( res.is_ok() )
268+
{
269+
py::list result;
270+
for( const auto &[ptr, type] : res.get() )
271+
{
272+
if( type == cte::PtrType::GATE )
273+
{
274+
result.append( py::cast( (const Gate *) ptr ) );
275+
}
276+
else if( type == cte::PtrType::NET )
277+
{
278+
result.append( py::cast( (const Net *) ptr ) );
279+
}
280+
else
281+
{
282+
log_error( "clock_tree_extractor", "unknown ptr type" );
283+
return py::none();
284+
}
285+
}
286+
return result;
287+
}
288+
log_error( "clock_tree_extractor", "{}", res.get_error().get() );
289+
return py::none();
290+
},
291+
py::arg( "ptr" ),
292+
R"()" )
293+
.def(
294+
"get_childs",
295+
[]( const cte::ClockTree &self, const void *ptr ) -> py::list {
296+
auto res = self.get_neighbors( ptr, IGRAPH_OUT );
297+
if( res.is_ok() )
298+
{
299+
py::list result;
300+
for( const auto &[ptr, type] : res.get() )
301+
{
302+
if( type == cte::PtrType::GATE )
303+
{
304+
result.append( py::cast( (const Gate *) ptr ) );
305+
}
306+
else if( type == cte::PtrType::NET )
307+
{
308+
result.append( py::cast( (const Net *) ptr ) );
309+
}
310+
else
311+
{
312+
log_error( "clock_tree_extractor", "unknown ptr type" );
313+
return py::none();
314+
}
315+
}
316+
return result;
317+
}
318+
log_error( "clock_tree_extractor", "{}", res.get_error().get() );
319+
return py::none();
320+
},
321+
py::arg( "ptr" ),
322+
R"()" )
243323
.def( "get_gates", &cte::ClockTree::get_gates, R"()" )
244324
.def( "get_nets", &cte::ClockTree::get_nets, R"()" )
245325
.def( "get_netlist", &cte::ClockTree::get_netlist, R"()" );

plugins/clock_tree_extractor/src/clock_tree.cpp

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,6 @@ namespace hal
2626
{
2727
namespace
2828
{
29-
struct VoidPtrHash
30-
{
31-
std::size_t operator()( const std::pair<const void *, const void *> &pair ) const
32-
{
33-
return std::hash<const void *>()( pair.first ) ^ ( std::hash<const void *>()( pair.second ) << 1 );
34-
}
35-
};
36-
37-
struct PairPtrEq
38-
{
39-
bool operator()( const std::pair<void *, void *> &p1,
40-
const std::pair<void *, void *> &p2 ) const noexcept
41-
{
42-
return p1.first == p2.first && p1.second == p2.second;
43-
}
44-
};
45-
4629
inline bool is_ff( const Gate *gate )
4730
{
4831
return gate->get_type()->has_property( GateTypeProperty::ff );
@@ -154,10 +137,13 @@ namespace hal
154137
std::unordered_set<std::pair<void *, void *>, VoidPtrHash> edges;
155138
std::unordered_map<const void *, PtrType> ptrs_to_type;
156139

157-
std::queue<std::pair<const Gate *, const Gate *>> queue;
140+
std::queue<std::tuple<const Gate *, const Gate *, std::vector<const Gate *>>> queue;
158141
NetlistTraversalDecorator ntd = NetlistTraversalDecorator( *netlist );
159142
std::unordered_set<std::pair<const Gate *, const Gate *>, VoidPtrHash> visited;
160143

144+
std::unordered_map<std::pair<const void *, const void *>, std::vector<const Gate *>, VoidPtrHash, PairPtrEq>
145+
paths;
146+
161147
for( const Gate *ff : netlist->get_gates( is_ff ) )
162148
{
163149
const std::vector<hal::GatePin *> clock_pins = ff->get_type()->get_pins( []( const auto &p ) {
@@ -201,7 +187,7 @@ namespace hal
201187
continue;
202188
}
203189

204-
queue.push( { ff, clk->get_sources().front()->get_gate() } );
190+
queue.push( { ff, clk->get_sources().front()->get_gate(), std::vector<const Gate *>{} } );
205191

206192
vertices.insert( (void *) ff );
207193
ptrs_to_type[(void *) ff] = PtrType::GATE;
@@ -211,11 +197,14 @@ namespace hal
211197

212198
while( !queue.empty() )
213199
{
214-
const std::pair<const Gate *, const Gate *> pair = queue.front();
200+
const std::tuple<const Gate *, const Gate *, std::vector<const Gate *>> tuple = queue.front();
215201
queue.pop();
216202

217-
Gate *source = (Gate *) pair.second;
218-
Gate *reference = (Gate *) pair.first;
203+
Gate *source = (Gate *) std::get<1>( tuple );
204+
Gate *reference = (Gate *) std::get<0>( tuple );
205+
std::vector<const Gate *> path = std::get<2>( tuple );
206+
207+
path.push_back( source );
219208

220209
if( is_latch( source ) )
221210
{
@@ -237,6 +226,9 @@ namespace hal
237226
ptrs_to_type[(void *) reference] = PtrType::GATE;
238227

239228
edges.insert( { (void *) source, (void *) reference } );
229+
path.push_back( reference );
230+
paths[{ (void *) source, (void *) reference }] = path;
231+
path.clear();
240232

241233
if( is_ff( source ) )
242234
{
@@ -246,7 +238,7 @@ namespace hal
246238
reference = (Gate *) source;
247239
}
248240

249-
visited.insert( pair );
241+
visited.insert( std::make_pair( reference, source ) );
250242

251243
for( const Endpoint *ep : source->get_fan_in_endpoints() )
252244
{
@@ -272,6 +264,10 @@ namespace hal
272264
ptrs_to_type[(void *) reference] = PtrType::GATE;
273265

274266
edges.insert( { (void *) net, (void *) reference } );
267+
268+
// paths[{ (void *) net, (void *) reference }] = path;
269+
// path.clear();
270+
275271
continue;
276272
}
277273

@@ -293,7 +289,7 @@ namespace hal
293289
const Gate *new_source = net->get_sources().front()->get_gate();
294290
if( visited.find( { reference, new_source } ) == visited.end() )
295291
{
296-
queue.push( { reference, new_source } );
292+
queue.push( { reference, new_source, path } );
297293
}
298294
}
299295
}
@@ -310,6 +306,7 @@ namespace hal
310306
}
311307

312308
clock_tree->m_ptrs_to_types = ptrs_to_type;
309+
clock_tree->m_paths = std::move( paths );
313310

314311
igraph_error_t ierror;
315312
igraph_vector_int_t iedges;
@@ -710,5 +707,47 @@ namespace hal
710707
{
711708
return m_igraph_ptr;
712709
}
710+
711+
const std::
712+
unordered_map<std::pair<const void *, const void *>, std::vector<const Gate *>, VoidPtrHash, PairPtrEq>
713+
ClockTree::get_paths() const
714+
{
715+
return m_paths;
716+
}
717+
718+
Result<std::vector<std::pair<const void *, PtrType>>>
719+
ClockTree::get_neighbors( const void *ptr, igraph_neimode_t direction ) const
720+
{
721+
auto it = m_ptrs_to_vertices.find( ptr );
722+
if( it == m_ptrs_to_vertices.end() )
723+
{
724+
return ERR( "object is not part of clock tree" );
725+
}
726+
727+
igraph_error_t ierror;
728+
igraph_vector_int_t neighbors;
729+
730+
if( ( ierror = igraph_vector_int_init( &neighbors, 0 ) ) != IGRAPH_SUCCESS )
731+
{
732+
return ERR( igraph_strerror( ierror ) );
733+
}
734+
735+
if( ( ierror = igraph_neighbors( m_igraph_ptr, &neighbors, it->second, direction ) ) != IGRAPH_SUCCESS )
736+
{
737+
igraph_vector_int_destroy( &neighbors );
738+
return ERR( igraph_strerror( ierror ) );
739+
}
740+
741+
std::vector<std::pair<const void *, PtrType>> result;
742+
for( igraph_integer_t idx = 0; idx < igraph_vector_int_size( &neighbors ); idx++ )
743+
{
744+
const void *n_ptr = m_vertices_to_ptrs.at( VECTOR( neighbors )[idx] );
745+
result.push_back( std::make_pair( n_ptr, m_ptrs_to_types.at( n_ptr ) ) );
746+
}
747+
748+
igraph_vector_int_destroy( &neighbors );
749+
750+
return OK( result );
751+
}
713752
} // namespace cte
714753
} // namespace hal

0 commit comments

Comments
 (0)