10 #include "nlohmann/json.hpp"
22 namespace bitorder_propagation
26 typedef std::pair<Module*, PinGroup<ModulePin>*> MPG;
27 typedef std::map<MPG, std::set<u32>> POSSIBLE_BITINDICES;
37 Result<std::map<MPG, std::map<MPG, i32>>> build_offset_matrix(
const std::map<Net*, POSSIBLE_BITINDICES>& reduced_indices)
40 std::map<MPG, std::map<MPG, i32>> origin_offset_matrix;
42 for (
const auto& [
net, possible_bitindices] : reduced_indices)
44 std::map<MPG, u32> all_possible_indices;
47 for (
const auto& [org_mpg, indices] : possible_bitindices)
49 all_possible_indices[org_mpg] = *(indices.begin());
53 for (
const auto& [org_mpg, indices] : possible_bitindices)
55 for (
const auto& [already_set_org, already_set_index] : all_possible_indices)
58 if (origin_offset_matrix[org_mpg].find(already_set_org) == origin_offset_matrix[org_mpg].end())
60 i32 new_index = *indices.begin();
61 i32 offset = already_set_index - new_index;
63 origin_offset_matrix[org_mpg][already_set_org] = offset;
64 origin_offset_matrix[already_set_org][org_mpg] = -offset;
69 i32 new_index = *indices.begin();
70 i32 offset = origin_offset_matrix.at(org_mpg).at(already_set_org);
72 if (new_index + offset !=
i32(already_set_index))
74 return ERR(
"unable to build offset matrix: failed to find valid offset between " + std::to_string(org_mpg.first->get_id()) +
"-" + org_mpg.second->get_name()
75 +
" and " + std::to_string(already_set_org.first->get_id()) +
"-" + already_set_org.second->get_name());
82 return OK(origin_offset_matrix);
97 Result<i32> get_offset(
const MPG& org1,
const MPG& org2, std::map<MPG, std::map<MPG, i32>>& m, std::set<std::set<MPG>>& v)
99 if (v.find({org1, org2}) != v.end())
101 return ERR(
"already tried to follow that offset.");
104 v.insert({org1, org2});
112 if (m.find(org1) == m.end())
114 return ERR(
"no valid offset to other origins.");
117 if (m.at(org1).find(org2) != m.at(org1).end())
119 return OK(m.at(org1).at(org2));
122 for (
auto& [dst_c, first_proxy_offset] : m.at(org1))
124 auto second_proxy_offset_res = get_offset(dst_c, org2, m, v);
125 if (second_proxy_offset_res.is_error())
129 i32 second_proxy_offset = second_proxy_offset_res.get();
131 m[org1][org2] = first_proxy_offset + second_proxy_offset;
133 return OK(first_proxy_offset + second_proxy_offset);
136 return ERR(
"could not find an valid offset");
151 Result<std::map<MPG, std::set<Net*>>> gather_connected_neighbors(Net* n,
153 const std::set<MPG>& relevant_pin_groups,
154 const bool guarantee_propagation,
155 const Module* inwards_module,
156 std::set<std::tuple<Endpoint*, const bool, const Module*>>& visited,
157 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>>& cache)
159 std::map<MPG, std::set<Net*>> connected_neighbors;
161 #ifdef PRINT_CONNECTIVITY_BUILDING
162 std::cout <<
"Gathering bit index for net " << n->get_id() <<
" with" << (guarantee_propagation ?
"" :
"out") <<
" guaranteed propagation "
163 <<
"in direction: " << (successors ?
"forwards" :
"backwards") << std::endl;
167 if ((successors && n->is_global_output_net()) || (!successors && n->is_global_input_net()))
169 auto m = n->get_netlist()->get_top_module();
170 bool is_border_pin = successors ? m->is_input_net(n) : m->is_output_net(n);
173 auto border_pin = m->get_pin_by_net(n);
174 if (border_pin ==
nullptr)
176 return ERR(
"cannot get bit index information for net with ID " + std::to_string(n->get_id()) +
" from module with ID " + std::to_string(m->get_id())
177 +
": net is border net but does not have a pin.");
179 auto pg = border_pin->get_group().first;
181 #ifdef PRINT_CONNECTIVITY_BUILDING
182 std::cout <<
"Added global IO net as origin " << m->get_name() <<
" - " << pg->get_name() <<
" - " << n->get_id() << std::endl;
185 connected_neighbors[{m, pg}].insert(n);
189 const auto neighbors = successors ? n->get_destinations() : n->get_sources();
190 for (
const auto& ep : neighbors)
192 std::tuple<Endpoint*, const bool, const Module*> t_ep = {ep, guarantee_propagation, inwards_module};
193 if (visited.find(t_ep) != visited.end())
197 visited.insert(t_ep);
199 Gate* g = ep->get_gate();
206 #ifdef PRINT_CONNECTIVITY_BUILDING
207 std::cout <<
"Checking gate " << g->get_id() << std::endl;
210 if ((inwards_module !=
nullptr) && !inwards_module->contains_gate(g,
true))
212 #ifdef PRINT_CONNECTIVITY_BUILDING
213 std::cout <<
"Ended propagation at gate " << g->get_id() <<
" as it is not contained in the currently entered module " << inwards_module->get_name() << std::endl;
219 const auto modules = g->get_modules();
221 if (!guarantee_propagation)
224 bool found_relevant_pin_group =
false;
225 for (
const auto& m : modules)
227 bool is_border_pin = successors ? m->is_input_net(n) : m->is_output_net(n);
230 auto border_pin = m->get_pin_by_net(n);
231 if (border_pin ==
nullptr)
233 return ERR(
"cannot get bit index information for net with ID " + std::to_string(n->get_id()) +
" from module with ID " + std::to_string(m->get_id())
234 +
": net is border net but does not have a pin.");
236 auto border_pg = border_pin->get_group().first;
239 if (relevant_pin_groups.find({m, border_pg}) == relevant_pin_groups.end())
241 #ifdef PRINT_CONNECTIVITY_BUILDING
242 std::cout <<
"Skipping border pin " << border_pin->get_name() <<
" of module " << m->get_name() <<
" as it is not relevant." << std::endl;
247 connected_neighbors[{m, border_pg}].insert(n);
248 found_relevant_pin_group =
true;
253 if (found_relevant_pin_group)
255 #ifdef PRINT_CONNECTIVITY_BUILDING
256 std::cout <<
"Ended propagation at gate " << g->get_id() <<
" as we reached it via a relevant pin group." << std::endl;
263 std::vector<Endpoint*> next_eps;
265 for (
const auto& next_ep : successors ? g->get_fan_out_endpoints() : g->get_fan_in_endpoints())
267 const GatePin* pin = next_ep->get_pin();
272 next_eps.push_back(next_ep);
277 next_eps.push_back(next_ep);
281 for (Endpoint* next_ep : next_eps)
284 bool found_relevant_pin_group =
false;
285 for (
const auto& m : modules)
287 bool is_border_pin = successors ? m->is_output_net(next_ep->get_net()) : m->is_input_net(next_ep->get_net());
290 auto border_pin = m->get_pin_by_net(next_ep->get_net());
291 if (border_pin ==
nullptr)
293 return ERR(
"cannot get bit index information for net with ID " + std::to_string(next_ep->get_net()->get_id()) +
" from module with ID "
294 + std::to_string(m->get_id()) +
": net is border net but does not have a pin.");
296 auto border_pg = border_pin->get_group().first;
299 if (relevant_pin_groups.find({m, border_pg}) == relevant_pin_groups.end())
304 connected_neighbors[{m, border_pg}].insert(next_ep->get_net());
305 found_relevant_pin_group =
true;
310 if (found_relevant_pin_group)
315 std::map<MPG, std::set<hal::Net*>> connected;
316 std::tuple<Endpoint*, const bool, const Module*> t = {next_ep,
false,
nullptr};
317 if (
auto it = cache.find(t); it != cache.end())
319 connected = it->second;
323 auto res = gather_connected_neighbors(next_ep->get_net(), successors, relevant_pin_groups,
false,
nullptr, visited, cache);
328 connected = res.get();
331 cache[t] = connected;
333 for (
auto& [org_mpg, nets] : connected)
335 connected_neighbors[org_mpg].insert(nets.begin(), nets.end());
340 return OK(connected_neighbors);
352 const std::map<Net*, POSSIBLE_BITINDICES> reduce_indices(
const std::map<Net*, POSSIBLE_BITINDICES>& collected_bitindices)
354 #ifdef PRINT_CONFLICT
355 std::cout <<
"\tVanilla indices: " << std::endl;
356 for (
const auto& [
net, possible_bitindices] : collected_bitindices)
358 std::cout <<
"\t\tNet " <<
net->get_id() <<
" - " <<
net->get_name() <<
": " << std::endl;
360 for (
const auto& [org_mpg, indices] : possible_bitindices)
362 auto org_m = org_mpg.first;
363 auto org_pg = org_mpg.second;
365 std::cout <<
"\t\t\t" << org_m->get_id() <<
"-" << org_pg->get_name() <<
": [";
366 for (
const auto&
index : indices)
368 std::cout <<
index <<
", ";
370 std::cout <<
"]" << std::endl;
374 std::cout <<
"\t\tORIGINS: [" << origins <<
"]" << std::endl;
378 auto reduced_collected_indices = collected_bitindices;
381 std::set<std::pair<MPG, u32>> origin_indices;
382 std::set<std::pair<MPG, u32>> origin_indices_to_remove;
384 for (
const auto& [
net, possible_bitindices] : reduced_collected_indices)
386 for (
const auto& [org_mpg, indices] : possible_bitindices)
388 for (
const auto&
index : indices)
390 if (origin_indices.find({org_mpg, index}) != origin_indices.end())
392 origin_indices_to_remove.insert({org_mpg,
index});
396 origin_indices.insert({org_mpg,
index});
402 #ifdef PRINT_CONFLICT
403 for (
const auto& [org_mpg,
index] : origin_indices_to_remove)
405 std::cout <<
"Found org " << org_mpg.first->get_id() <<
"-" << org_mpg.second->get_name() <<
" index " <<
index <<
" pair to remove!" << std::endl;
409 for (
auto& [
net, possible_bitindices] : collected_bitindices)
411 for (
auto& [org_mpg, indices] : possible_bitindices)
413 for (
const auto&
index : indices)
415 if (origin_indices_to_remove.find({org_mpg, index}) != origin_indices_to_remove.end())
417 reduced_collected_indices.at(
net).at(org_mpg).erase(
index);
421 if (reduced_collected_indices.at(
net).at(org_mpg).empty())
423 reduced_collected_indices.at(
net).erase(org_mpg);
427 if (reduced_collected_indices.at(
net).empty())
429 reduced_collected_indices.erase(
net);
433 if (reduced_collected_indices.empty())
439 auto further_reduced_collected_indices = reduced_collected_indices;
440 for (
auto& [
net, possible_bitindices] : reduced_collected_indices)
442 for (
auto& [org_mpg, indices] : possible_bitindices)
444 if (indices.size() != 1)
446 further_reduced_collected_indices.at(
net).erase(org_mpg);
450 if (further_reduced_collected_indices.at(
net).empty())
452 further_reduced_collected_indices.erase(
net);
456 if (further_reduced_collected_indices.empty())
461 #ifdef PRINT_CONFLICT
462 std::cout <<
"\tReduced Possible Indices: " << std::endl;
463 for (
const auto& [
net, possible_bitindices] : further_reduced_collected_indices)
465 std::cout <<
"\t\tNet " <<
net->get_id() <<
": " << std::endl;
467 for (
const auto& [org_mpg, indices] : possible_bitindices)
469 auto org_m = org_mpg.first;
470 auto org_pg = org_mpg.second;
472 std::cout <<
"\t\t\t" << org_m->get_id() <<
"-" << org_pg->get_name() <<
": [";
473 for (
const auto&
index : indices)
475 std::cout <<
index <<
", ";
477 std::cout <<
"]" << std::endl;
482 return further_reduced_collected_indices;
492 const bool check_completeness(
const MPG& mpg,
const std::map<Net*, i32>& consensus_bitindices)
494 bool is_complete_pin_group_bitorder =
true;
496 for (
auto& pin : mpg.second->get_pins())
498 Net*
net = pin->get_net();
499 if (consensus_bitindices.find(
net) == consensus_bitindices.end())
501 is_complete_pin_group_bitorder =
false;
503 #ifdef PRINT_CONFLICT
504 std::cout <<
"Missing net " <<
net->get_id() <<
" - " <<
net->get_name() <<
" for complete bitorder." << std::endl;
510 #ifdef PRINT_CONFLICT
511 if (is_complete_pin_group_bitorder)
513 std::cout <<
"Found complete bitorder for pingroup " << mpg.second->get_name() << std::endl;
514 for (
const auto& [
net,
index] : consensus_bitindices)
516 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
521 return is_complete_pin_group_bitorder;
533 const std::map<Net*, u32> align_indices(
const std::map<Net*, i32>& consensus_bitindices,
const bool enforce_continuous_bitorders)
535 std::map<Net*, u32> aligned_consensus;
537 std::set<i32> unique_indices;
538 for (
const auto& [_n,
index] : consensus_bitindices)
540 unique_indices.insert(
index);
543 if (unique_indices.empty())
548 const i32 min_index = *(unique_indices.begin());
549 const i32 max_index = *(unique_indices.rbegin());
552 if (enforce_continuous_bitorders && ((max_index - min_index) > (
i32(consensus_bitindices.size()) - 1)))
558 if (unique_indices.size() < consensus_bitindices.size())
563 std::map<i32, Net*> index_to_net;
564 for (
const auto& [
net,
index] : consensus_bitindices)
569 u32 index_counter = 0;
570 for (
const auto& [_unaligned_index,
net] : index_to_net)
572 aligned_consensus[
net] = index_counter++;
575 return aligned_consensus;
588 std::map<Net*, u32> find_consensus_via_offset(
const MPG& mpg,
const std::map<hal::Net*, POSSIBLE_BITINDICES>& indices,
const bool enforce_continuous_bitorders)
590 std::map<Net*, i32> consensus_bitindices;
592 auto offset_matrix_res = build_offset_matrix(indices);
593 if (offset_matrix_res.is_error())
595 #ifdef PRINT_CONFLICT
596 std::cout <<
"Failed to build offset matrix : " << offset_matrix_res.get_error().get() << std::endl;
600 auto offset_matrix = offset_matrix_res.get();
603 auto base_line = offset_matrix.begin()->first;
605 #ifdef PRINT_CONFLICT
606 std::cout <<
"Found valid offsets pingroup " << mpg.second->get_name() <<
": " << std::endl;
607 std::cout <<
"Baseline: " << base_line.first->get_id() <<
"-" << base_line.second->get_name() << std::endl;
608 for (
const auto& [org1, col] : offset_matrix)
610 std::cout << org1.first->get_id() <<
"-" << org1.second->get_name() <<
": ";
611 for (
const auto& [org2, offset] : col)
613 std::cout << org2.first->get_id() <<
"-" << org2.second->get_name() <<
"[" << offset <<
"] ";
615 std::cout << std::endl;
619 for (
const auto& [
net, possible_bitindices] : indices)
622 MPG org = possible_bitindices.begin()->first;
624 i32 org_index = *(possible_bitindices.begin()->second.begin());
625 std::set<std::set<MPG>> v;
626 auto offset_res = get_offset(org, base_line, offset_matrix, v);
627 if (offset_res.is_error())
629 if (possible_bitindices.size() == 1)
633 consensus_bitindices[
net] = org_index;
642 i32 offset = offset_res.get();
643 consensus_bitindices[
net] = org_index + offset;
647 #ifdef PRINT_CONFLICT
648 std::cout <<
"Found offset bitorder: " << std::endl;
649 for (
const auto& [
net,
index] : consensus_bitindices)
651 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
656 const auto is_complete_pin_group_bitorder = check_completeness(mpg, consensus_bitindices);
658 if (!is_complete_pin_group_bitorder)
664 const auto aligned_indices = align_indices(consensus_bitindices, enforce_continuous_bitorders);
666 return aligned_indices;
675 const std::map<Net*, i32> conduct_majority_vote(
const std::map<hal::Net*, POSSIBLE_BITINDICES>& indices)
677 std::map<Net*, i32> majority_indices;
679 for (
const auto& [
net, possible_indices] : indices)
681 std::map<u32, u32> index_to_count;
682 for (
const auto& [_org, org_indices] : possible_indices)
684 for (
const auto&
index : org_indices)
686 index_to_count[
index]++;
691 if (index_to_count.size() == 1)
693 majority_indices.insert({
net, index_to_count.begin()->first});
698 std::vector<std::pair<u32, u32>> index_counts = {index_to_count.begin(), index_to_count.end()};
699 std::sort(index_counts.begin(), index_counts.end(), [](
const auto& p1,
const auto& p2) { return p1.second > p2.second; });
702 if (index_counts.at(0).second > index_counts.at(1).second)
704 majority_indices.insert({
net, index_counts.at(0).first});
708 return majority_indices;
719 std::map<Net*, u32> find_consensus_via_majority(
const MPG& mpg,
const std::map<hal::Net*, POSSIBLE_BITINDICES>& indices,
const bool enforce_continuous_bitorders)
721 const auto majority_indices = conduct_majority_vote(indices);
723 #ifdef PRINT_CONFLICT
724 std::cout <<
"Found majority bitorder: " << std::endl;
725 for (
const auto& [
net,
index] : majority_indices)
727 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
732 const auto is_complete_pin_group_bitorder = check_completeness(mpg, majority_indices);
733 if (!is_complete_pin_group_bitorder)
739 const auto aligned_indices = align_indices(majority_indices, enforce_continuous_bitorders);
741 return aligned_indices;
757 std::map<Net*, u32> find_consensus_via_majority_relaxed(
const MPG& mpg,
758 const std::map<hal::Net*, POSSIBLE_BITINDICES>& all_indices,
759 const std::map<hal::Net*, POSSIBLE_BITINDICES>& reduced_indices,
760 const bool enforce_continuous_bitorders)
763 const auto first_majority_indices = conduct_majority_vote(reduced_indices);
766 auto unfound_indices = all_indices;
767 for (
const auto& [
net, _] : first_majority_indices)
769 unfound_indices.erase(
net);
773 auto relaxed_reduced_indices = reduce_indices(unfound_indices);
776 const auto second_majority_indices = conduct_majority_vote(relaxed_reduced_indices);
778 #ifdef PRINT_CONFLICT
779 std::cout <<
"Found majority bitorder: " << std::endl;
780 for (
const auto& [
net,
index] : second_majority_indices)
782 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
786 std::map<Net*, i32> combined_indices = first_majority_indices;
787 for (
const auto& p : second_majority_indices)
789 combined_indices.insert(p);
793 const auto is_complete_pin_group_bitorder = check_completeness(mpg, combined_indices);
794 if (!is_complete_pin_group_bitorder)
800 const auto aligned_indices = align_indices(combined_indices, enforce_continuous_bitorders);
802 return aligned_indices;
818 std::map<Net*, u32> extract_well_formed_bitorder(
const MPG& mpg,
const std::map<Net*, POSSIBLE_BITINDICES>& collected_bitindices,
bool enforce_continuous_bitorders =
true)
820 auto reduced_collected_indices = reduce_indices(collected_bitindices);
822 if (reduced_collected_indices.empty())
827 auto aligned_consensus = find_consensus_via_offset(mpg, reduced_collected_indices, enforce_continuous_bitorders);
829 if (aligned_consensus.empty())
831 aligned_consensus = find_consensus_via_majority(mpg, reduced_collected_indices, enforce_continuous_bitorders);
834 if (aligned_consensus.empty())
836 aligned_consensus = find_consensus_via_majority_relaxed(mpg, collected_bitindices, reduced_collected_indices, enforce_continuous_bitorders);
839 if (aligned_consensus.empty())
844 #ifdef PRINT_CONFLICT
845 std::cout <<
"Found valid input bitorder for pingroup " << mpg.second->get_name() << std::endl;
846 for (
const auto& [
net,
index] : aligned_consensus)
848 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
852 return aligned_consensus;
861 std::map<MPG, std::map<Net*, u32>> to_internal(
const BitOrderResult& bit_orders)
863 std::map<MPG, std::map<Net*, u32>> res;
864 for (
const auto& bit_order : bit_orders)
866 std::map<Net*, u32> indices;
867 for (
const auto& [
net,
index] : bit_order.get_order())
871 res.insert({{bit_order.get_module(), bit_order.get_pin_group()}, std::move(indices)});
876 BitOrderResult from_internal(
const std::map<MPG, std::map<Net*, u32>>& bit_orders)
879 for (
const auto& [mpg, indices] : bit_orders)
881 res.add(BitOrder(mpg.first, mpg.second, {indices.begin(), indices.end()}));
887 Result<BitOrderResult>
890 const std::map<MPG, std::map<Net*, u32>> known_bitorders = to_internal(src);
895 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_inwards;
896 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_outwards;
899 std::cout <<
"Known bitorders [" << known_bitorders.size() <<
"]:" << std::endl;
900 for (
const auto& [mpg, net_indices] : known_bitorders)
902 std::cout <<
"\t" << mpg.first->get_name() <<
" - " << mpg.second->get_name() << std::endl;
903 for (
const auto& [
net,
index] : net_indices)
905 std::cout <<
"\t\t" <<
net->get_id() <<
" / " <<
net->get_name() <<
" - " <<
index << std::endl;
909 std::cout <<
"Unknown bitorders [" << unknown_bitorders.size() <<
"]:" << std::endl;
910 for (
const auto& [m, pg] : unknown_bitorders)
912 std::cout <<
"\t" << m->get_name() <<
" - " << pg->get_name() << std::endl;
917 std::set<MPG> relevant_pin_groups = unknown_bitorders;
918 for (
const auto& [kb, _] : known_bitorders)
920 relevant_pin_groups.insert(kb);
923 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_outwards;
924 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_inwards;
927 for (
const auto& [m, pg] : unknown_bitorders)
934 return ERR(
"cannot propagate bitorder: pin group " + pg->get_name() +
" of module " + m->get_name() +
" has direction other than input, output or none.");
940 std::set<PinDirection> pin_directions;
941 for (
const auto& p : pg->get_pins())
943 pin_directions.insert(p->get_direction());
944 if (pin_directions.size() > 1)
950 pg_direction = *(pin_directions.begin());
952 "Pin group {} of module {} has no set direction, but all pins have the same direction {}. Assuming this to be the pin groups direction.",
960 return ERR(
"cannot propagate bitorder: pin group " + pg->get_name() +
" of module " + m->get_name()
961 +
" has direction other than input or output and contains pins of different or other directions, such that we cannot deduce a pin group order.");
966 for (
const auto& p : pg->get_pins())
968 const auto starting_net = p->get_net();
970 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_outwards;
971 const auto res_outwards = gather_connected_neighbors(starting_net, successors, relevant_pin_groups,
false,
nullptr, visited_outwards, cache_outwards);
972 if (res_outwards.is_error())
975 "cannot porpagate bitorder: failed to gather bit indices outwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
978 const auto connected_outwards = res_outwards.get();
980 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_inwards;
982 const auto res_inwards = gather_connected_neighbors(starting_net, !successors, relevant_pin_groups,
true, m, visited_inwards, cache_inwards);
983 if (res_inwards.is_error())
986 "cannot porpagate bitorder: failed to gather bit indices inwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
989 const auto connected_inwards = res_inwards.get();
991 for (
const auto& [org_mpg, nets] : connected_outwards)
993 connectivity_outwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
996 for (
const auto& [org_mpg, nets] : connected_inwards)
998 connectivity_inwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
1003 #ifdef PRINT_CONNECTIVITY
1004 for (
const auto& [start, connected] : connectivity_outwards)
1006 std::cout << start.first.first->get_id() <<
" / " << start.first.first->get_name() <<
" - " << start.first.second->get_name() <<
" (OUTWARDS)@ " << start.second->get_id() <<
" / "
1007 << start.second->get_name() << std::endl;
1008 for (
const auto& [mpg, nets] : connected)
1010 for (
const auto&
net : nets)
1012 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() <<
": " <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
1016 for (
const auto& [start, connected] : connectivity_inwards)
1018 std::cout << start.first.first->get_id() <<
" / " << start.first.first->get_name() <<
" - " << start.first.second->get_name() <<
" (INWARDS)@ " << start.second->get_id() <<
" / "
1019 << start.second->get_name() << std::endl;
1020 for (
const auto& [mpg, nets] : connected)
1022 for (
const auto&
net : nets)
1024 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() <<
": " <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
1030 log_info(
"bitorder_propagation",
"Finished conncetivity analysis for bitorder propagation");
1032 std::map<MPG, std::map<Net*, u32>> wellformed_module_pin_groups = known_bitorders;
1034 u32 iteration_ctr = 0;
1039 std::vector<MPG> modules_and_pingroup;
1040 for (
const auto& mpg : unknown_bitorders)
1042 if (mpg.first->is_top_module())
1044 log_error(
"bitorder_propagation",
"Top module is part of the unknown bitorders!");
1049 if (wellformed_module_pin_groups.find(mpg) == wellformed_module_pin_groups.end())
1051 modules_and_pingroup.push_back(mpg);
1055 std::deque<MPG> q = {modules_and_pingroup.begin(), modules_and_pingroup.end()};
1062 log_info(
"bitorder_propagation",
"Starting {}bitorder propagation iteration {}.", (enforce_continuous_bitorders ?
"strict " :
""), iteration_ctr);
1064 std::map<MPG, std::map<Net*, u32>> new_wellformed_module_pin_groups = {};
1068 auto [m, pg] = q.front();
1072 bool no_submodules_in_q =
true;
1073 for (
const auto& sub_m : m->get_submodules(
nullptr,
true))
1075 for (
const auto& [sm, sp] : q)
1079 no_submodules_in_q =
false;
1085 if (!no_submodules_in_q)
1087 q.push_back({m, pg});
1093 std::map<Net*, POSSIBLE_BITINDICES> collected_inwards;
1094 std::map<Net*, POSSIBLE_BITINDICES> collected_outwards;
1095 std::map<Net*, POSSIBLE_BITINDICES> collected_combined;
1097 for (
const auto& pin : pg->get_pins())
1099 Net* starting_net = pin->get_net();
1105 if (
auto con_it = connectivity_inwards.find({{m, pg}, starting_net}); con_it == connectivity_inwards.end())
1107 #ifdef PRINT_CONNECTIVITY
1108 std::cout <<
"There are no valid origins connected inwards to modue " << m->
get_id() <<
" / " << m->get_name() <<
" with pin group " << pg->get_name() <<
" and net "
1109 << starting_net->get_id() <<
" / " << starting_net->get_name() <<
"." << std::endl;
1114 const auto& connected_inwards = con_it->second;
1116 for (
const auto& [org_mpg, org_nets] : connected_inwards)
1118 if (
auto mpg_it = wellformed_module_pin_groups.find(org_mpg); mpg_it != wellformed_module_pin_groups.end())
1120 const auto& nets = mpg_it->second;
1121 for (
const auto& org_net : org_nets)
1123 if (
auto net_it = nets.find(org_net); net_it != nets.end())
1125 collected_inwards[starting_net][org_mpg].insert(net_it->second);
1126 collected_combined[starting_net][org_mpg].insert(net_it->second);
1131 "Module {} / {} and pin group {} are wellformed but are missing an index for net {} / {}!",
1132 org_mpg.first->get_id(),
1133 org_mpg.first->get_name(),
1134 org_mpg.second->get_name(),
1136 org_net->get_name());
1147 if (
const auto con_it = connectivity_outwards.find({{m, pg}, starting_net}); con_it == connectivity_outwards.end())
1149 #ifdef PRINT_CONNECTIVITY
1150 std::cout <<
"There are no valid origins connected outwards to modue " << m->get_id() <<
" / " << m->get_name() <<
" with pin group " << pg->get_name() <<
" and net "
1151 << starting_net->get_id() <<
" / " << starting_net->get_name() <<
"." << std::endl;
1157 const auto& connected_outwards = con_it->second;
1159 for (
const auto& [org_mpg, org_nets] : connected_outwards)
1161 if (
auto mpg_it = wellformed_module_pin_groups.find(org_mpg); mpg_it != wellformed_module_pin_groups.end())
1163 const auto& nets = mpg_it->second;
1164 for (
const auto& org_net : org_nets)
1166 if (
auto net_it = nets.find(org_net); net_it != nets.end())
1168 collected_outwards[starting_net][org_mpg].insert(net_it->second);
1169 collected_combined[starting_net][org_mpg].insert(net_it->second);
1174 "Module {} / {} and pin group {} are wellformed but are missing an index for net {} / {}!",
1175 org_mpg.first->get_id(),
1176 org_mpg.first->get_name(),
1177 org_mpg.second->get_name(),
1179 org_net->get_name());
1187 #ifdef PRINT_CONFLICT
1188 std::cout <<
"Extract for " << m->get_id() <<
" / " << m->get_name() <<
" - " << pg->get_name() <<
": (INWARDS) " << std::endl;
1189 for (
const auto& [
net, collected] : collected_inwards)
1191 std::cout <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
1192 for (
const auto& [mpg, indices] : collected)
1194 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() << std::endl;
1195 std::cout <<
"\t\t";
1196 for (
const auto&
index : indices)
1198 std::cout <<
index <<
", ";
1200 std::cout << std::endl;
1205 const auto newly_wellformed_inwards = extract_well_formed_bitorder({m, pg}, collected_inwards, enforce_continuous_bitorders);
1206 if (!newly_wellformed_inwards.empty())
1208 new_wellformed_module_pin_groups[{m, pg}] = newly_wellformed_inwards;
1212 #ifdef PRINT_CONFLICT
1213 std::cout <<
"Extract for " << m->get_id() <<
" / " << m->get_name() <<
" - " << pg->get_name() <<
": (OUTWARDS) " << std::endl;
1214 for (
const auto& [
net, collected] : collected_outwards)
1216 std::cout <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
1217 for (
const auto& [mpg, indices] : collected)
1219 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() << std::endl;
1220 std::cout <<
"\t\t";
1221 for (
const auto&
index : indices)
1223 std::cout <<
index <<
", ";
1225 std::cout << std::endl;
1229 const auto newly_wellformed_outwards = extract_well_formed_bitorder({m, pg}, collected_outwards, enforce_continuous_bitorders);
1230 if (!newly_wellformed_outwards.empty())
1232 new_wellformed_module_pin_groups[{m, pg}] = newly_wellformed_outwards;
1236 #ifdef PRINT_CONFLICT
1237 std::cout <<
"Extract for " << m->get_id() <<
" / " << m->get_name() <<
" - " << pg->get_name() <<
": (COMBINED) " << std::endl;
1239 const auto newly_wellformed_combined = extract_well_formed_bitorder({m, pg}, collected_combined, enforce_continuous_bitorders);
1240 if (!newly_wellformed_combined.empty())
1242 new_wellformed_module_pin_groups[{m, pg}] = newly_wellformed_combined;
1246 if (new_wellformed_module_pin_groups.empty())
1251 log_info(
"bitorder_propagation",
"Found {} new bitorders in iteration: {}", new_wellformed_module_pin_groups.size(), iteration_ctr);
1254 wellformed_module_pin_groups.insert(new_wellformed_module_pin_groups.begin(), new_wellformed_module_pin_groups.end());
1258 if (iteration_ctr > 100)
1260 log_error(
"bitorder_propagation",
"Endless loop protection, something went wrong!");
1265 log_info(
"bitorder_propagation",
"Found a valid bitorder for {} pingroups.", wellformed_module_pin_groups.size());
1267 return OK(from_internal(wellformed_module_pin_groups));
1272 const std::map<MPG, std::map<Net*, u32>> ordered_module_pin_groups = to_internal(bit_orders);
1275 for (
const auto& [mpg, bitorder] : ordered_module_pin_groups)
1278 auto pg = mpg.second;
1280 std::map<u32, ModulePin*> index_to_pin;
1283 for (
const auto& [
net,
index] : bitorder)
1288 auto [current_pin_group, _old_index] = pin->
get_group();
1289 if (pg == current_pin_group)
1291 index_to_pin[
index] = pin;
1295 return ERR(
"cannot reorder module pin groups: pin '" + pin->
get_name() +
"' appears in bit order of pin group '" + pg->get_name() +
"' for module with ID "
1296 + std::to_string(m->get_id()) +
" but belongs to pin group '" + current_pin_group->get_name() +
"'");
1302 for (
const auto& [
index, pin] : index_to_pin)
1304 if (!m->move_pin_within_group(pg, pin,
index))
1306 return ERR(
"cannot reorder module pin groups: failed to move pin '" + pin->get_name() +
"' in pin group '" + pg->get_name() +
"' of module with ID "
1307 + std::to_string(m->get_id()) +
" to new index " + std::to_string(
index));
1310 const auto pin_name = pg->get_name() +
"(" + std::to_string(
index) +
")";
1311 if (
auto collision_pins = m->get_pins([pin_name](
const ModulePin* pin) { return pin->get_name() == pin_name; }); !collision_pins.empty())
1313 m->set_pin_name(collision_pins.front(), pin_name +
"_OLD");
1316 m->set_pin_name(pin, pin_name);
1325 const std::vector<std::pair<u32, std::string>> src_vec = {src};
1326 const std::vector<std::pair<u32, std::string>> dst_vec = {dst};
1335 return ERR(
"cannot propagate bitorder: no source given");
1339 return ERR(
"cannot propagate bitorder: no destination given");
1341 const std::vector<std::pair<Module*, PinGroup<ModulePin>*>> src_vec = {src};
1342 const std::vector<std::pair<Module*, PinGroup<ModulePin>*>> dst_vec = {dst};
1349 std::vector<std::pair<Module*, PinGroup<ModulePin>*>> internal_src;
1350 std::vector<std::pair<Module*, PinGroup<ModulePin>*>> internal_dst;
1353 for (
const auto& [mod_id, pg_name] : src)
1356 if (src_mod ==
nullptr)
1358 return ERR(
"Cannot propagate bit order: failed to find a module with ID " + std::to_string(mod_id));
1362 for (
const auto& pin_group : src_mod->get_pin_groups())
1364 if (pin_group->get_name() == pg_name)
1367 if (src_pin_group !=
nullptr)
1369 return ERR(
"Cannot propagate bit order: found multiple pin groups with name " + pg_name +
" at module with ID " + std::to_string(mod_id));
1372 src_pin_group = pin_group;
1376 if (src_pin_group ==
nullptr)
1378 return ERR(
"Cannot propagate bit order: failed to find a pin group with the name '" + pg_name +
"' at module with ID " + std::to_string(mod_id));
1381 internal_src.push_back({src_mod, src_pin_group});
1385 for (
const auto& [mod_id, pg_name] : dst)
1388 if (src_mod ==
nullptr)
1390 return ERR(
"Cannot propagate bit order: failed to find a module with ID " + std::to_string(mod_id));
1394 for (
const auto& pin_group : src_mod->get_pin_groups())
1396 if (pin_group->get_name() == pg_name)
1399 if (src_pin_group !=
nullptr)
1401 return ERR(
"Cannot propagate bitorder: found multiple pin groups with name '" + pg_name +
"' at module with ID " + std::to_string(mod_id));
1404 src_pin_group = pin_group;
1408 if (src_pin_group ==
nullptr)
1410 return ERR(
"Cannot propagate bitorder: failed to find a pin group with the name '" + pg_name +
"' at module with ID " + std::to_string(mod_id));
1413 internal_dst.push_back({src_mod, src_pin_group});
1423 std::map<MPG, std::map<Net*, u32>> known_bitorders;
1424 std::set<MPG> unknown_bitorders = {dst.begin(), dst.end()};
1427 for (
auto& [m, pg] : src)
1429 std::map<Net*, u32> src_bitorder;
1434 auto pin_res = pg->get_pin_at_index(
index);
1435 if (pin_res.is_error())
1437 return ERR_APPEND(pin_res.get_error(),
"cannot propagate bit order: failed to get pin at index " + std::to_string(
index) +
" inside of pin group '" + pg->get_name() +
"'");
1444 known_bitorders.insert({{m, pg}, src_bitorder});
1451 return ERR_APPEND(res.get_error(),
"cannot propagate bit order: failed propagation");
1454 const auto all_wellformed_module_pin_groups = res.get();
1459 #ifdef PRINT_GENERAL
1460 for (
const auto& [mpg, bitorder] : all_wellformed_module_pin_groups)
1463 auto pg = mpg.second;
1465 std::cout <<
"Module: " << m->get_id() <<
" / " << m->get_name() <<
": " << std::endl;
1466 std::cout <<
"Pingroup: " << pg->get_name() <<
": " << std::endl;
1468 for (
const auto& [
net,
index] : bitorder)
1470 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
1476 const u32 all_wellformed_bitorders_count = all_wellformed_module_pin_groups.get_size();
1477 const u32 new_bit_order_count = all_wellformed_bitorders_count - src.size();
1479 log_info(
"bitorder_propagation",
"reconstructed {} unknown bit orders from {} known bit orders", new_bit_order_count, src.size());
1480 log_info(
"bitorder_propagation",
"{} / {} = {} of all unknown bit orders", new_bit_order_count, dst.size(),
double(new_bit_order_count) /
double(dst.size()));
1482 "{} / {} = {} of all pin group bit orders",
1483 all_wellformed_bitorders_count,
1484 dst.size() + src.size(),
1485 double(all_wellformed_bitorders_count) /
double(dst.size() + src.size()));
1487 return OK(all_wellformed_module_pin_groups);
1492 const std::string& export_filepath)
1494 std::map<MPG, std::map<Net*, u32>> known_bitorders;
1495 std::set<MPG> unknown_bitorders = {dst.begin(), dst.end()};
1498 for (
auto& [m, pg] : src)
1500 std::map<Net*, u32> src_bitorder;
1505 auto pin_res = pg->get_pin_at_index(
index);
1506 if (pin_res.is_error())
1508 return ERR_APPEND(pin_res.get_error(),
"cannot propagate bit order: failed to get pin at index " + std::to_string(
index) +
" inside of pin group '" + pg->get_name() +
"'");
1515 known_bitorders.insert({{m, pg}, src_bitorder});
1523 const std::string& export_filepath)
1525 const std::map<MPG, std::map<Net*, u32>> known_bitorders = to_internal(src);
1527 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_inwards;
1528 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_outwards;
1530 std::set<MPG> relevant_pin_groups = unknown_bitorders;
1531 for (
const auto& [kb, _] : known_bitorders)
1533 relevant_pin_groups.insert(kb);
1536 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_outwards;
1537 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_inwards;
1540 for (
const auto& [m, pg] : relevant_pin_groups)
1542 bool successors = pg->get_direction() == PinDirection::output;
1544 for (
const auto& p : pg->get_pins())
1546 const auto starting_net = p->get_net();
1548 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_outwards;
1549 const auto res_outwards = gather_connected_neighbors(starting_net, successors, relevant_pin_groups,
false,
nullptr, visited_outwards, cache_outwards);
1550 if (res_outwards.is_error())
1553 "cannot porpagate bitorder: failed to gather bit indices outwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
1556 const auto connected_outwards = res_outwards.get();
1558 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_inwards;
1560 const auto res_inwards = gather_connected_neighbors(starting_net, !successors, relevant_pin_groups,
true, m, visited_inwards, cache_inwards);
1561 if (res_inwards.is_error())
1564 "cannot porpagate bitorder: failed to gather bit indices inwwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
1567 const auto connected_inwards = res_inwards.get();
1569 for (
const auto& [org_mpg, nets] : connected_outwards)
1571 connectivity_outwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
1574 for (
const auto& [org_mpg, nets] : connected_inwards)
1576 connectivity_inwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
1581 nlohmann::json info;
1584 std::vector<MPG> mpgs;
1585 std::map<MPG, u32> mpg_to_idx;
1586 std::vector<std::vector<Net*>> words;
1587 std::map<std::string, std::vector<std::string>> word_definitions;
1589 for (
const auto& [m, pg] : relevant_pin_groups)
1591 std::vector<Net*> nets;
1592 std::vector<std::string> nets_str;
1594 for (
const auto& p : pg->get_pins())
1596 const auto& n = p->get_net();
1601 word_definitions.insert({std::to_string(words.size()), nets_str});
1602 mpg_to_idx.insert({{m, pg}, (
unsigned int)mpg_to_idx.size()});
1603 mpgs.push_back({m, pg});
1604 words.push_back(nets);
1607 info[
"word_definitions"] = word_definitions;
1610 std::map<std::string, std::vector<std::string>> known_word_orders;
1612 for (
u32 i = 0; i < mpgs.size(); i++)
1614 const auto& mpg = mpgs.at(i);
1616 if (
const auto it = known_bitorders.find(mpg); it != known_bitorders.end())
1618 std::vector<std::string> ordered_nets_str;
1620 std::vector<std::pair<Net*, u32>> net_index_vec = {it->second.begin(), it->second.end()};
1621 std::sort(net_index_vec.begin(), net_index_vec.end(), [](
const auto& p1,
const auto& p2) { return p1.second < p2.second; });
1622 for (
const auto& [n, _idx] : net_index_vec)
1627 known_word_orders.insert({std::to_string(i), ordered_nets_str});
1631 info[
"known_bit_order"] = known_word_orders;
1634 std::map<std::string, std::vector<std::pair<u32, std::string>>> connected_words;
1635 std::map<std::string, std::vector<std::pair<u32, std::string>>> connected_words_forward;
1636 std::map<std::string, std::vector<std::pair<u32, std::string>>> connected_words_backward;
1638 for (
u32 i = 0; i < mpgs.size(); i++)
1640 const auto& mpg = mpgs.at(i);
1641 const auto& nets = words.at(i);
1643 for (
const auto& src_net : nets)
1645 std::vector<std::pair<u32, std::string>> connections;
1646 std::vector<std::pair<u32, std::string>> connections_forward;
1647 std::vector<std::pair<u32, std::string>> connections_backward;
1649 const auto it_in = connectivity_inwards.find({mpg, src_net});
1650 if (it_in != connectivity_inwards.end())
1652 for (
const auto& [dst_mpg, dst_nets] : it_in->second)
1654 for (
const auto& dst_net : dst_nets)
1662 const auto it_out = connectivity_outwards.find({mpg, src_net});
1663 if (it_out != connectivity_outwards.end())
1665 for (
const auto& [dst_mpg, dst_nets] : it_out->second)
1667 for (
const auto& dst_net : dst_nets)
1675 if (!connections.empty())
1679 connected_words.insert({
identifier, connections});
1681 if (!connections_backward.empty())
1683 connected_words_backward.insert({
identifier, connections_backward});
1686 if (!connections_forward.empty())
1688 connected_words_forward.insert({
identifier, connections_forward});
1694 info[
"connected_words"] = connected_words;
1695 info[
"connected_words_backward"] = connected_words_backward;
1696 info[
"connected_words_forward"] = connected_words_forward;
1699 std::ofstream json_file(export_filepath);
1702 if (json_file.is_open())
1704 json_file << info.dump(4);
1708 return ERR(
"cannot export bitorder information: failed to open file at path " + export_filepath +
" for writing");
1711 return OK(mpg_to_idx);
This file contains the bit order of a module pin group and the collection of bit orders that a propag...
This file contains functions for bit-order propagation from pin groups of known bit order to pin grou...
const std::string & get_name() const
const std::pair< PinGroup< T > *, i32 > & get_group() const
std::string get_boolean_variable_name() const
Module * get_module_by_id(u32 module_id) const
#define log_error(channel,...)
#define log_info(channel,...)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
Result< BitOrderResult > propagate_bitorder(Netlist *nl, const std::pair< u32, std::string > &src, const std::pair< u32, std::string > &dst)
Propagate known bit-order information from one module pin group to another module pin group of unknow...
Result< BitOrderResult > propagate_module_pingroup_bitorder(const BitOrderResult &src, const std::set< MPG > &unknown_bitorders, const bool enforce_continuous_bitorders)
Result< std::monostate > reorder_module_pin_groups(const BitOrderResult &ordered_module_pin_groups)
Reorder and rename the pins of the pin groups according to the provided bit-order information.
Result< BitOrderResult > propagate_module_pingroup_bitorder(const BitOrderResult &src, const std::set< std::pair< Module *, PinGroup< ModulePin > * >> &dst, const bool enforce_continuous_bitorders=true)
Propagate known bit-order information from the given module pin groups to module pin groups of unknow...
Result< std::map< std::pair< Module *, PinGroup< ModulePin > * >, WordIndex > > export_bitorder_propagation_information(const std::vector< std::pair< Module *, PinGroup< ModulePin > * >> &src, const std::vector< std::pair< Module *, PinGroup< ModulePin > * >> &dst, const std::string &export_filepath)
Export word composition, known bitorder and connectivity in .json format to solve with external tools...
std::string enum_to_string(T e)