@@ -336,7 +336,7 @@ namespace hal
336
336
{
337
337
if (std::find (allowed_pin_types.begin (), allowed_pin_types.end (), endpoint->get_pin ()->get_type ()) != allowed_pin_types.end () || allowed_pin_types.empty ())
338
338
{
339
- auto n = endpoint->get_net ();
339
+ auto n = endpoint->get_net ();
340
340
auto suc = get_next_sequential_gates (n, get_successors, allowed_pin_types, cache);
341
341
found_ffs.insert (found_ffs.end (), suc.begin (), suc.end ());
342
342
}
@@ -831,6 +831,96 @@ namespace hal
831
831
}
832
832
}
833
833
834
+ Result<std::vector<std::vector<Gate*>>> find_carry_chains (const Netlist* nl, const std::string input_pin, const std::string output_pin)
835
+ {
836
+ if (input_pin.empty () || output_pin.empty ())
837
+ {
838
+ return ERR (" input or output pin is empty" );
839
+ }
840
+
841
+ std::vector<std::vector<Gate*>> carry_chains;
842
+
843
+ // retrieve all carry gates
844
+ std::vector<Gate*> carry_gates = nl->get_gates ([](const Gate* g) { return g->get_type ()->has_property (GateTypeProperty::c_carry); });
845
+ std::set<Gate*> carry_gates_set = std::set<Gate*>(carry_gates.begin (), carry_gates.end ());
846
+ if (carry_gates_set.empty ())
847
+ {
848
+ return ERR (" no carry gates in netlists" );
849
+ }
850
+
851
+ // collect carry chains until all carry gates have been analyzed
852
+ while (!carry_gates_set.empty ())
853
+ {
854
+ Gate* current_gate = *carry_gates_set.begin ();
855
+ const GateType* carry_type = current_gate->get_type ();
856
+
857
+ auto input_pin_type = carry_type->get_pin_by_name (input_pin);
858
+ if (input_pin_type == nullptr )
859
+ {
860
+ return ERR (" could not get input pin type, is nullptr" );
861
+ }
862
+
863
+ auto output_pin_type = carry_type->get_pin_by_name (output_pin);
864
+ if (output_pin_type == nullptr )
865
+ {
866
+ return ERR (" could not get output pin type, is nullptr" );
867
+ }
868
+
869
+ // get carry chains by defining appropriate filter function
870
+ auto chain_res = netlist_utils::get_gate_chain (current_gate, {input_pin_type}, {output_pin_type});
871
+ if (chain_res.is_error ())
872
+ {
873
+ return ERR (chain_res.get_error ());
874
+ }
875
+ std::vector<Gate*> carry_chain = chain_res.get ();
876
+
877
+ // remove shift register gates from candidate set
878
+ for (Gate* g : carry_chain)
879
+ {
880
+ carry_gates_set.erase (g);
881
+ }
882
+
883
+ // only consider carry chains with more than 2 gates for now
884
+ if (carry_chain.size () >= 2 )
885
+ {
886
+ log_debug (" netlist_utils" , " \t carry_gate: {}" , carry_chain.front ()->get_name ());
887
+ carry_chains.push_back (carry_chain);
888
+ }
889
+ }
890
+
891
+ // check whether a carry chain is a subset of another one
892
+ std::vector<std::vector<Gate*>> filtered_carry_chains;
893
+ for (u32 i = 0 ; i < carry_chains.size (); i++)
894
+ {
895
+ auto & c_test = carry_chains.at (i);
896
+ std::set<Gate*> test_set = {c_test.begin (), c_test.end ()};
897
+
898
+ bool is_subset = false ;
899
+ for (u32 j = 0 ; j < carry_chains.size (); j++)
900
+ {
901
+ if (i == j)
902
+ {
903
+ continue ;
904
+ }
905
+
906
+ auto & c_other = carry_chains.at (j);
907
+ std::set<Gate*> other_set = {c_other.begin (), c_other.end ()};
908
+
909
+ if (std::includes (other_set.begin (), other_set.end (), test_set.begin (), test_set.end ()))
910
+ {
911
+ is_subset = true ;
912
+ break ;
913
+ }
914
+ }
915
+
916
+ if (!is_subset)
917
+ {
918
+ filtered_carry_chains.push_back (c_test);
919
+ }
920
+ }
921
+ return OK (filtered_carry_chains);
922
+ }
923
+
834
924
Result<std::vector<Gate*>>
835
925
get_gate_chain (Gate* start_gate, const std::vector<const GatePin*>& input_pins, const std::vector<const GatePin*>& output_pins, const std::function<bool (const Gate*)>& filter)
836
926
{
0 commit comments