8 #include "nlohmann/json.hpp"
20 namespace bitorder_propagation
24 typedef std::pair<Module*, PinGroup<ModulePin>*> MPG;
25 typedef std::map<MPG, std::set<u32>> POSSIBLE_BITINDICES;
35 Result<std::map<MPG, std::map<MPG, i32>>> build_offset_matrix(
const std::map<Net*, POSSIBLE_BITINDICES>& reduced_indices)
38 std::map<MPG, std::map<MPG, i32>> origin_offset_matrix;
40 for (
const auto& [
net, possible_bitindices] : reduced_indices)
42 std::map<MPG, u32> all_possible_indices;
45 for (
const auto& [org_mpg, indices] : possible_bitindices)
47 all_possible_indices[org_mpg] = *(indices.begin());
51 for (
const auto& [org_mpg, indices] : possible_bitindices)
53 for (
const auto& [already_set_org, already_set_index] : all_possible_indices)
56 if (origin_offset_matrix[org_mpg].find(already_set_org) == origin_offset_matrix[org_mpg].end())
58 i32 new_index = *indices.begin();
59 i32 offset = already_set_index - new_index;
61 origin_offset_matrix[org_mpg][already_set_org] = offset;
62 origin_offset_matrix[already_set_org][org_mpg] = -offset;
67 i32 new_index = *indices.begin();
68 i32 offset = origin_offset_matrix.at(org_mpg).at(already_set_org);
70 if (new_index + offset !=
i32(already_set_index))
72 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()
73 +
" and " + std::to_string(already_set_org.first->get_id()) +
"-" + already_set_org.second->get_name());
80 return OK(origin_offset_matrix);
95 Result<i32> get_offset(
const MPG& org1,
const MPG& org2, std::map<MPG, std::map<MPG, i32>>& m, std::set<std::set<MPG>>& v)
97 if (v.find({org1, org2}) != v.end())
99 return ERR(
"already tried to follow that offset.");
102 v.insert({org1, org2});
110 if (m.find(org1) == m.end())
112 return ERR(
"no valid offset to other origins.");
115 if (m.at(org1).find(org2) != m.at(org1).end())
117 return OK(m.at(org1).at(org2));
120 for (
auto& [dst_c, first_proxy_offset] : m.at(org1))
122 auto second_proxy_offset_res = get_offset(dst_c, org2, m, v);
123 if (second_proxy_offset_res.is_error())
127 i32 second_proxy_offset = second_proxy_offset_res.get();
129 m[org1][org2] = first_proxy_offset + second_proxy_offset;
131 return OK(first_proxy_offset + second_proxy_offset);
134 return ERR(
"could not find an valid offset");
149 Result<std::map<MPG, std::set<Net*>>> gather_connected_neighbors(Net* n,
151 const std::set<MPG>& relevant_pin_groups,
152 const bool guarantee_propagation,
153 const Module* inwards_module,
154 std::set<std::tuple<Endpoint*, const bool, const Module*>>& visited,
155 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>>& cache)
157 std::map<MPG, std::set<Net*>> connected_neighbors;
159 #ifdef PRINT_CONNECTIVITY_BUILDING
160 std::cout <<
"Gathering bit index for net " << n->get_id() <<
" with" << (guarantee_propagation ?
"" :
"out") <<
" guaranteed propagation "
161 <<
"in direction: " << (successors ?
"forwards" :
"backwards") << std::endl;
165 if ((successors && n->is_global_output_net()) || (!successors && n->is_global_input_net()))
167 auto m = n->get_netlist()->get_top_module();
168 bool is_border_pin = successors ? m->is_input_net(n) : m->is_output_net(n);
171 auto border_pin = m->get_pin_by_net(n);
172 if (border_pin ==
nullptr)
174 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())
175 +
": net is border net but does not have a pin.");
177 auto pg = border_pin->get_group().first;
179 #ifdef PRINT_CONNECTIVITY_BUILDING
180 std::cout <<
"Added global IO net as origin " << m->get_name() <<
" - " << pg->get_name() <<
" - " << n->get_id() << std::endl;
183 connected_neighbors[{m, pg}].insert(n);
187 const auto neighbors = successors ? n->get_destinations() : n->get_sources();
188 for (
const auto& ep : neighbors)
190 std::tuple<Endpoint*, const bool, const Module*> t_ep = {ep, guarantee_propagation, inwards_module};
191 if (visited.find(t_ep) != visited.end())
195 visited.insert(t_ep);
197 Gate* g = ep->get_gate();
204 #ifdef PRINT_CONNECTIVITY_BUILDING
205 std::cout <<
"Checking gate " << g->get_id() << std::endl;
208 if ((inwards_module !=
nullptr) && !inwards_module->contains_gate(g,
true))
210 #ifdef PRINT_CONNECTIVITY_BUILDING
211 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;
217 const auto modules = g->get_modules();
219 if (!guarantee_propagation)
222 bool found_relevant_pin_group =
false;
223 for (
const auto& m : modules)
225 bool is_border_pin = successors ? m->is_input_net(n) : m->is_output_net(n);
228 auto border_pin = m->get_pin_by_net(n);
229 if (border_pin ==
nullptr)
231 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())
232 +
": net is border net but does not have a pin.");
234 auto border_pg = border_pin->get_group().first;
237 if (relevant_pin_groups.find({m, border_pg}) == relevant_pin_groups.end())
239 #ifdef PRINT_CONNECTIVITY_BUILDING
240 std::cout <<
"Skipping border pin " << border_pin->get_name() <<
" of module " << m->get_name() <<
" as it is not relevant." << std::endl;
245 connected_neighbors[{m, border_pg}].insert(n);
246 found_relevant_pin_group =
true;
251 if (found_relevant_pin_group)
253 #ifdef PRINT_CONNECTIVITY_BUILDING
254 std::cout <<
"Ended propagation at gate " << g->get_id() <<
" as we reached it via a relevant pin group." << std::endl;
261 std::vector<Endpoint*> next_eps;
263 for (
const auto& next_ep : successors ? g->get_fan_out_endpoints() : g->get_fan_in_endpoints())
265 const GatePin* pin = next_ep->get_pin();
270 next_eps.push_back(next_ep);
275 next_eps.push_back(next_ep);
279 for (Endpoint* next_ep : next_eps)
282 bool found_relevant_pin_group =
false;
283 for (
const auto& m : modules)
285 bool is_border_pin = successors ? m->is_output_net(next_ep->get_net()) : m->is_input_net(next_ep->get_net());
288 auto border_pin = m->get_pin_by_net(next_ep->get_net());
289 if (border_pin ==
nullptr)
291 return ERR(
"cannot get bit index information for net with ID " + std::to_string(next_ep->get_net()->get_id()) +
" from module with ID "
292 + std::to_string(m->get_id()) +
": net is border net but does not have a pin.");
294 auto border_pg = border_pin->get_group().first;
297 if (relevant_pin_groups.find({m, border_pg}) == relevant_pin_groups.end())
302 connected_neighbors[{m, border_pg}].insert(next_ep->get_net());
303 found_relevant_pin_group =
true;
308 if (found_relevant_pin_group)
313 std::map<MPG, std::set<hal::Net*>> connected;
314 std::tuple<Endpoint*, const bool, const Module*> t = {next_ep,
false,
nullptr};
315 if (
auto it = cache.find(t); it != cache.end())
317 connected = it->second;
321 auto res = gather_connected_neighbors(next_ep->get_net(), successors, relevant_pin_groups,
false,
nullptr, visited, cache);
326 connected = res.get();
329 cache[t] = connected;
331 for (
auto& [org_mpg, nets] : connected)
333 connected_neighbors[org_mpg].insert(nets.begin(), nets.end());
338 return OK(connected_neighbors);
350 const std::map<Net*, POSSIBLE_BITINDICES> reduce_indices(
const std::map<Net*, POSSIBLE_BITINDICES>& collected_bitindices)
352 #ifdef PRINT_CONFLICT
353 std::cout <<
"\tVanilla indices: " << std::endl;
354 for (
const auto& [
net, possible_bitindices] : collected_bitindices)
356 std::cout <<
"\t\tNet " <<
net->get_id() <<
" - " <<
net->get_name() <<
": " << std::endl;
358 for (
const auto& [org_mpg, indices] : possible_bitindices)
360 auto org_m = org_mpg.first;
361 auto org_pg = org_mpg.second;
363 std::cout <<
"\t\t\t" << org_m->get_id() <<
"-" << org_pg->get_name() <<
": [";
364 for (
const auto&
index : indices)
366 std::cout <<
index <<
", ";
368 std::cout <<
"]" << std::endl;
372 std::cout <<
"\t\tORIGINS: [" << origins <<
"]" << std::endl;
376 auto reduced_collected_indices = collected_bitindices;
379 std::set<std::pair<MPG, u32>> origin_indices;
380 std::set<std::pair<MPG, u32>> origin_indices_to_remove;
382 for (
const auto& [
net, possible_bitindices] : reduced_collected_indices)
384 for (
const auto& [org_mpg, indices] : possible_bitindices)
386 for (
const auto&
index : indices)
388 if (origin_indices.find({org_mpg, index}) != origin_indices.end())
390 origin_indices_to_remove.insert({org_mpg,
index});
394 origin_indices.insert({org_mpg,
index});
400 #ifdef PRINT_CONFLICT
401 for (
const auto& [org_mpg,
index] : origin_indices_to_remove)
403 std::cout <<
"Found org " << org_mpg.first->get_id() <<
"-" << org_mpg.second->get_name() <<
" index " <<
index <<
" pair to remove!" << std::endl;
407 for (
auto& [
net, possible_bitindices] : collected_bitindices)
409 for (
auto& [org_mpg, indices] : possible_bitindices)
411 for (
const auto&
index : indices)
413 if (origin_indices_to_remove.find({org_mpg, index}) != origin_indices_to_remove.end())
415 reduced_collected_indices.at(
net).at(org_mpg).erase(
index);
419 if (reduced_collected_indices.at(
net).at(org_mpg).empty())
421 reduced_collected_indices.at(
net).erase(org_mpg);
425 if (reduced_collected_indices.at(
net).empty())
427 reduced_collected_indices.erase(
net);
431 if (reduced_collected_indices.empty())
437 auto further_reduced_collected_indices = reduced_collected_indices;
438 for (
auto& [
net, possible_bitindices] : reduced_collected_indices)
440 for (
auto& [org_mpg, indices] : possible_bitindices)
442 if (indices.size() != 1)
444 further_reduced_collected_indices.at(
net).erase(org_mpg);
448 if (further_reduced_collected_indices.at(
net).empty())
450 further_reduced_collected_indices.erase(
net);
454 if (further_reduced_collected_indices.empty())
459 #ifdef PRINT_CONFLICT
460 std::cout <<
"\tReduced Possible Indices: " << std::endl;
461 for (
const auto& [
net, possible_bitindices] : further_reduced_collected_indices)
463 std::cout <<
"\t\tNet " <<
net->get_id() <<
": " << std::endl;
465 for (
const auto& [org_mpg, indices] : possible_bitindices)
467 auto org_m = org_mpg.first;
468 auto org_pg = org_mpg.second;
470 std::cout <<
"\t\t\t" << org_m->get_id() <<
"-" << org_pg->get_name() <<
": [";
471 for (
const auto&
index : indices)
473 std::cout <<
index <<
", ";
475 std::cout <<
"]" << std::endl;
480 return further_reduced_collected_indices;
490 const bool check_completeness(
const MPG& mpg,
const std::map<Net*, i32>& consensus_bitindices)
492 bool is_complete_pin_group_bitorder =
true;
494 for (
auto& pin : mpg.second->get_pins())
496 Net*
net = pin->get_net();
497 if (consensus_bitindices.find(
net) == consensus_bitindices.end())
499 is_complete_pin_group_bitorder =
false;
501 #ifdef PRINT_CONFLICT
502 std::cout <<
"Missing net " <<
net->get_id() <<
" - " <<
net->get_name() <<
" for complete bitorder." << std::endl;
508 #ifdef PRINT_CONFLICT
509 if (is_complete_pin_group_bitorder)
511 std::cout <<
"Found complete bitorder for pingroup " << mpg.second->get_name() << std::endl;
512 for (
const auto& [
net,
index] : consensus_bitindices)
514 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
519 return is_complete_pin_group_bitorder;
531 const std::map<Net*, u32> align_indices(
const std::map<Net*, i32>& consensus_bitindices,
const bool enforce_continuous_bitorders)
533 std::map<Net*, u32> aligned_consensus;
535 std::set<i32> unique_indices;
536 for (
const auto& [_n,
index] : consensus_bitindices)
538 unique_indices.insert(
index);
541 if (unique_indices.empty())
546 const i32 min_index = *(unique_indices.begin());
547 const i32 max_index = *(unique_indices.rbegin());
550 if (enforce_continuous_bitorders && ((max_index - min_index) > (
i32(consensus_bitindices.size()) - 1)))
556 if (unique_indices.size() < consensus_bitindices.size())
561 std::map<i32, Net*> index_to_net;
562 for (
const auto& [
net,
index] : consensus_bitindices)
567 u32 index_counter = 0;
568 for (
const auto& [_unaligned_index,
net] : index_to_net)
570 aligned_consensus[
net] = index_counter++;
573 return aligned_consensus;
586 std::map<Net*, u32> find_consensus_via_offset(
const MPG& mpg,
const std::map<hal::Net*, POSSIBLE_BITINDICES>& indices,
const bool enforce_continuous_bitorders)
588 std::map<Net*, i32> consensus_bitindices;
590 auto offset_matrix_res = build_offset_matrix(indices);
591 if (offset_matrix_res.is_error())
593 #ifdef PRINT_CONFLICT
594 std::cout <<
"Failed to build offset matrix : " << offset_matrix_res.get_error().get() << std::endl;
598 auto offset_matrix = offset_matrix_res.get();
601 auto base_line = offset_matrix.begin()->first;
603 #ifdef PRINT_CONFLICT
604 std::cout <<
"Found valid offsets pingroup " << mpg.second->get_name() <<
": " << std::endl;
605 std::cout <<
"Baseline: " << base_line.first->get_id() <<
"-" << base_line.second->get_name() << std::endl;
606 for (
const auto& [org1, col] : offset_matrix)
608 std::cout << org1.first->get_id() <<
"-" << org1.second->get_name() <<
": ";
609 for (
const auto& [org2, offset] : col)
611 std::cout << org2.first->get_id() <<
"-" << org2.second->get_name() <<
"[" << offset <<
"] ";
613 std::cout << std::endl;
617 for (
const auto& [
net, possible_bitindices] : indices)
620 MPG org = possible_bitindices.begin()->first;
622 i32 org_index = *(possible_bitindices.begin()->second.begin());
623 std::set<std::set<MPG>> v;
624 auto offset_res = get_offset(org, base_line, offset_matrix, v);
625 if (offset_res.is_error())
627 if (possible_bitindices.size() == 1)
631 consensus_bitindices[
net] = org_index;
640 i32 offset = offset_res.get();
641 consensus_bitindices[
net] = org_index + offset;
645 #ifdef PRINT_CONFLICT
646 std::cout <<
"Found offset bitorder: " << std::endl;
647 for (
const auto& [
net,
index] : consensus_bitindices)
649 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
654 const auto is_complete_pin_group_bitorder = check_completeness(mpg, consensus_bitindices);
656 if (!is_complete_pin_group_bitorder)
662 const auto aligned_indices = align_indices(consensus_bitindices, enforce_continuous_bitorders);
664 return aligned_indices;
673 const std::map<Net*, i32> conduct_majority_vote(
const std::map<hal::Net*, POSSIBLE_BITINDICES>& indices)
675 std::map<Net*, i32> majority_indices;
677 for (
const auto& [
net, possible_indices] : indices)
679 std::map<u32, u32> index_to_count;
680 for (
const auto& [_org, org_indices] : possible_indices)
682 for (
const auto&
index : org_indices)
684 index_to_count[
index]++;
689 if (index_to_count.size() == 1)
691 majority_indices.insert({
net, index_to_count.begin()->first});
696 std::vector<std::pair<u32, u32>> index_counts = {index_to_count.begin(), index_to_count.end()};
697 std::sort(index_counts.begin(), index_counts.end(), [](
const auto& p1,
const auto& p2) { return p1.second > p2.second; });
700 if (index_counts.at(0).second > index_counts.at(1).second)
702 majority_indices.insert({
net, index_counts.at(0).first});
706 return majority_indices;
717 std::map<Net*, u32> find_consensus_via_majority(
const MPG& mpg,
const std::map<hal::Net*, POSSIBLE_BITINDICES>& indices,
const bool enforce_continuous_bitorders)
719 const auto majority_indices = conduct_majority_vote(indices);
721 #ifdef PRINT_CONFLICT
722 std::cout <<
"Found majority bitorder: " << std::endl;
723 for (
const auto& [
net,
index] : majority_indices)
725 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
730 const auto is_complete_pin_group_bitorder = check_completeness(mpg, majority_indices);
731 if (!is_complete_pin_group_bitorder)
737 const auto aligned_indices = align_indices(majority_indices, enforce_continuous_bitorders);
739 return aligned_indices;
755 std::map<Net*, u32> find_consensus_via_majority_relaxed(
const MPG& mpg,
756 const std::map<hal::Net*, POSSIBLE_BITINDICES>& all_indices,
757 const std::map<hal::Net*, POSSIBLE_BITINDICES>& reduced_indices,
758 const bool enforce_continuous_bitorders)
761 const auto first_majority_indices = conduct_majority_vote(reduced_indices);
764 auto unfound_indices = all_indices;
765 for (
const auto& [
net, _] : first_majority_indices)
767 unfound_indices.erase(
net);
771 auto relaxed_reduced_indices = reduce_indices(unfound_indices);
774 const auto second_majority_indices = conduct_majority_vote(relaxed_reduced_indices);
776 #ifdef PRINT_CONFLICT
777 std::cout <<
"Found majority bitorder: " << std::endl;
778 for (
const auto& [
net,
index] : second_majority_indices)
780 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
784 std::map<Net*, i32> combined_indices = first_majority_indices;
785 for (
const auto& p : second_majority_indices)
787 combined_indices.insert(p);
791 const auto is_complete_pin_group_bitorder = check_completeness(mpg, combined_indices);
792 if (!is_complete_pin_group_bitorder)
798 const auto aligned_indices = align_indices(combined_indices, enforce_continuous_bitorders);
800 return aligned_indices;
816 std::map<Net*, u32> extract_well_formed_bitorder(
const MPG& mpg,
const std::map<Net*, POSSIBLE_BITINDICES>& collected_bitindices,
bool enforce_continuous_bitorders =
true)
818 auto reduced_collected_indices = reduce_indices(collected_bitindices);
820 if (reduced_collected_indices.empty())
825 auto aligned_consensus = find_consensus_via_offset(mpg, reduced_collected_indices, enforce_continuous_bitorders);
827 if (aligned_consensus.empty())
829 aligned_consensus = find_consensus_via_majority(mpg, reduced_collected_indices, enforce_continuous_bitorders);
832 if (aligned_consensus.empty())
834 aligned_consensus = find_consensus_via_majority_relaxed(mpg, collected_bitindices, reduced_collected_indices, enforce_continuous_bitorders);
837 if (aligned_consensus.empty())
842 #ifdef PRINT_CONFLICT
843 std::cout <<
"Found valid input bitorder for pingroup " << mpg.second->get_name() << std::endl;
844 for (
const auto& [
net,
index] : aligned_consensus)
846 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
850 return aligned_consensus;
855 Result<std::map<MPG, std::map<Net*, u32>>>
861 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_inwards;
862 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_outwards;
865 std::cout <<
"Known bitorders [" << known_bitorders.size() <<
"]:" << std::endl;
866 for (
const auto& [mpg, net_indices] : known_bitorders)
868 std::cout <<
"\t" << mpg.first->get_name() <<
" - " << mpg.second->get_name() << std::endl;
869 for (
const auto& [
net,
index] : net_indices)
871 std::cout <<
"\t\t" <<
net->get_id() <<
" / " <<
net->get_name() <<
" - " <<
index << std::endl;
875 std::cout <<
"Unknown bitorders [" << unknown_bitorders.size() <<
"]:" << std::endl;
876 for (
const auto& [m, pg] : unknown_bitorders)
878 std::cout <<
"\t" << m->get_name() <<
" - " << pg->get_name() << std::endl;
883 std::set<MPG> relevant_pin_groups = unknown_bitorders;
884 for (
const auto& [kb, _] : known_bitorders)
886 relevant_pin_groups.insert(kb);
889 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_outwards;
890 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_inwards;
893 for (
const auto& [m, pg] : unknown_bitorders)
900 return ERR(
"cannot propagate bitorder: pin group " + pg->get_name() +
" of module " + m->get_name() +
" has direction other than input, output or none.");
906 std::set<PinDirection> pin_directions;
907 for (
const auto& p : pg->get_pins())
909 pin_directions.insert(p->get_direction());
910 if (pin_directions.size() > 1)
916 pg_direction = *(pin_directions.begin());
918 "Pin group {} of module {} has no set direction, but all pins have the same direction {}. Assuming this to be the pin groups direction.",
926 return ERR(
"cannot propagate bitorder: pin group " + pg->get_name() +
" of module " + m->get_name()
927 +
" has direction other than input or output and contains pins of different or other directions, such that we cannot deduce a pin group order.");
932 for (
const auto& p : pg->get_pins())
934 const auto starting_net = p->get_net();
936 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_outwards;
937 const auto res_outwards = gather_connected_neighbors(starting_net, successors, relevant_pin_groups,
false,
nullptr, visited_outwards, cache_outwards);
938 if (res_outwards.is_error())
941 "cannot porpagate bitorder: failed to gather bit indices outwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
944 const auto connected_outwards = res_outwards.get();
946 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_inwards;
948 const auto res_inwards = gather_connected_neighbors(starting_net, !successors, relevant_pin_groups,
true, m, visited_inwards, cache_inwards);
949 if (res_inwards.is_error())
952 "cannot porpagate bitorder: failed to gather bit indices inwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
955 const auto connected_inwards = res_inwards.get();
957 for (
const auto& [org_mpg, nets] : connected_outwards)
959 connectivity_outwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
962 for (
const auto& [org_mpg, nets] : connected_inwards)
964 connectivity_inwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
969 #ifdef PRINT_CONNECTIVITY
970 for (
const auto& [start, connected] : connectivity_outwards)
972 std::cout << start.first.first->get_id() <<
" / " << start.first.first->get_name() <<
" - " << start.first.second->get_name() <<
" (OUTWARDS)@ " << start.second->get_id() <<
" / "
973 << start.second->get_name() << std::endl;
974 for (
const auto& [mpg, nets] : connected)
976 for (
const auto&
net : nets)
978 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() <<
": " <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
982 for (
const auto& [start, connected] : connectivity_inwards)
984 std::cout << start.first.first->get_id() <<
" / " << start.first.first->get_name() <<
" - " << start.first.second->get_name() <<
" (INWARDS)@ " << start.second->get_id() <<
" / "
985 << start.second->get_name() << std::endl;
986 for (
const auto& [mpg, nets] : connected)
988 for (
const auto&
net : nets)
990 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() <<
": " <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
996 log_info(
"bitorder_propagation",
"Finished conncetivity analysis for bitorder propagation");
998 std::map<MPG, std::map<Net*, u32>> wellformed_module_pin_groups = known_bitorders;
1000 u32 iteration_ctr = 0;
1005 std::vector<MPG> modules_and_pingroup;
1006 for (
const auto& mpg : unknown_bitorders)
1008 if (mpg.first->is_top_module())
1010 log_error(
"bitorder_propagation",
"Top module is part of the unknown bitorders!");
1015 if (wellformed_module_pin_groups.find(mpg) == wellformed_module_pin_groups.end())
1017 modules_and_pingroup.push_back(mpg);
1021 std::deque<MPG> q = {modules_and_pingroup.begin(), modules_and_pingroup.end()};
1028 log_info(
"bitorder_propagation",
"Starting {}bitorder propagation iteration {}.", (enforce_continuous_bitorders ?
"strict " :
""), iteration_ctr);
1030 std::map<MPG, std::map<Net*, u32>> new_wellformed_module_pin_groups = {};
1034 auto [m, pg] = q.front();
1038 bool no_submodules_in_q =
true;
1039 for (
const auto& sub_m : m->get_submodules(
nullptr,
true))
1041 for (
const auto& [sm, sp] : q)
1045 no_submodules_in_q =
false;
1051 if (!no_submodules_in_q)
1053 q.push_back({m, pg});
1059 std::map<Net*, POSSIBLE_BITINDICES> collected_inwards;
1060 std::map<Net*, POSSIBLE_BITINDICES> collected_outwards;
1061 std::map<Net*, POSSIBLE_BITINDICES> collected_combined;
1063 for (
const auto& pin : pg->get_pins())
1065 Net* starting_net = pin->get_net();
1071 if (
auto con_it = connectivity_inwards.find({{m, pg}, starting_net}); con_it == connectivity_inwards.end())
1073 #ifdef PRINT_CONNECTIVITY
1074 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 "
1075 << starting_net->get_id() <<
" / " << starting_net->get_name() <<
"." << std::endl;
1080 const auto& connected_inwards = con_it->second;
1082 for (
const auto& [org_mpg, org_nets] : connected_inwards)
1084 if (
auto mpg_it = wellformed_module_pin_groups.find(org_mpg); mpg_it != wellformed_module_pin_groups.end())
1086 const auto& nets = mpg_it->second;
1087 for (
const auto& org_net : org_nets)
1089 if (
auto net_it = nets.find(org_net); net_it != nets.end())
1091 collected_inwards[starting_net][org_mpg].insert(net_it->second);
1092 collected_combined[starting_net][org_mpg].insert(net_it->second);
1097 "Module {} / {} and pin group {} are wellformed but are missing an index for net {} / {}!",
1098 org_mpg.first->get_id(),
1099 org_mpg.first->get_name(),
1100 org_mpg.second->get_name(),
1102 org_net->get_name());
1113 if (
const auto con_it = connectivity_outwards.find({{m, pg}, starting_net}); con_it == connectivity_outwards.end())
1115 #ifdef PRINT_CONNECTIVITY
1116 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 "
1117 << starting_net->get_id() <<
" / " << starting_net->get_name() <<
"." << std::endl;
1123 const auto& connected_outwards = con_it->second;
1125 for (
const auto& [org_mpg, org_nets] : connected_outwards)
1127 if (
auto mpg_it = wellformed_module_pin_groups.find(org_mpg); mpg_it != wellformed_module_pin_groups.end())
1129 const auto& nets = mpg_it->second;
1130 for (
const auto& org_net : org_nets)
1132 if (
auto net_it = nets.find(org_net); net_it != nets.end())
1134 collected_outwards[starting_net][org_mpg].insert(net_it->second);
1135 collected_combined[starting_net][org_mpg].insert(net_it->second);
1140 "Module {} / {} and pin group {} are wellformed but are missing an index for net {} / {}!",
1141 org_mpg.first->get_id(),
1142 org_mpg.first->get_name(),
1143 org_mpg.second->get_name(),
1145 org_net->get_name());
1153 #ifdef PRINT_CONFLICT
1154 std::cout <<
"Extract for " << m->get_id() <<
" / " << m->get_name() <<
" - " << pg->get_name() <<
": (INWARDS) " << std::endl;
1155 for (
const auto& [
net, collected] : collected_inwards)
1157 std::cout <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
1158 for (
const auto& [mpg, indices] : collected)
1160 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() << std::endl;
1161 std::cout <<
"\t\t";
1162 for (
const auto&
index : indices)
1164 std::cout <<
index <<
", ";
1166 std::cout << std::endl;
1171 const auto newly_wellformed_inwards = extract_well_formed_bitorder({m, pg}, collected_inwards, enforce_continuous_bitorders);
1172 if (!newly_wellformed_inwards.empty())
1174 new_wellformed_module_pin_groups[{m, pg}] = newly_wellformed_inwards;
1178 #ifdef PRINT_CONFLICT
1179 std::cout <<
"Extract for " << m->get_id() <<
" / " << m->get_name() <<
" - " << pg->get_name() <<
": (OUTWARDS) " << std::endl;
1180 for (
const auto& [
net, collected] : collected_outwards)
1182 std::cout <<
net->get_id() <<
" / " <<
net->get_name() << std::endl;
1183 for (
const auto& [mpg, indices] : collected)
1185 std::cout <<
"\t" << mpg.first->get_id() <<
" / " << mpg.first->get_name() <<
" - " << mpg.second->get_name() << std::endl;
1186 std::cout <<
"\t\t";
1187 for (
const auto&
index : indices)
1189 std::cout <<
index <<
", ";
1191 std::cout << std::endl;
1195 const auto newly_wellformed_outwards = extract_well_formed_bitorder({m, pg}, collected_outwards, enforce_continuous_bitorders);
1196 if (!newly_wellformed_outwards.empty())
1198 new_wellformed_module_pin_groups[{m, pg}] = newly_wellformed_outwards;
1202 #ifdef PRINT_CONFLICT
1203 std::cout <<
"Extract for " << m->get_id() <<
" / " << m->get_name() <<
" - " << pg->get_name() <<
": (COMBINED) " << std::endl;
1205 const auto newly_wellformed_combined = extract_well_formed_bitorder({m, pg}, collected_combined, enforce_continuous_bitorders);
1206 if (!newly_wellformed_combined.empty())
1208 new_wellformed_module_pin_groups[{m, pg}] = newly_wellformed_combined;
1212 if (new_wellformed_module_pin_groups.empty())
1217 log_info(
"bitorder_propagation",
"Found {} new bitorders in iteration: {}", new_wellformed_module_pin_groups.size(), iteration_ctr);
1220 wellformed_module_pin_groups.insert(new_wellformed_module_pin_groups.begin(), new_wellformed_module_pin_groups.end());
1224 if (iteration_ctr > 100)
1226 log_error(
"bitorder_propagation",
"Endless loop protection, something went wrong!");
1231 log_info(
"bitorder_propagation",
"Found a valid bitorder for {} pingroups.", wellformed_module_pin_groups.size());
1233 return OK(wellformed_module_pin_groups);
1239 for (
const auto& [mpg, bitorder] : ordered_module_pin_groups)
1242 auto pg = mpg.second;
1244 std::map<u32, ModulePin*> index_to_pin;
1247 for (
const auto& [
net,
index] : bitorder)
1252 auto [current_pin_group, _old_index] = pin->
get_group();
1253 if (pg == current_pin_group)
1255 index_to_pin[
index] = pin;
1259 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 "
1260 + std::to_string(m->get_id()) +
" but belongs to pin group '" + current_pin_group->get_name() +
"'");
1266 for (
const auto& [
index, pin] : index_to_pin)
1268 if (!m->move_pin_within_group(pg, pin,
index))
1270 return ERR(
"cannot reorder module pin groups: failed to move pin '" + pin->get_name() +
"' in pin group '" + pg->get_name() +
"' of module with ID "
1271 + std::to_string(m->get_id()) +
" to new index " + std::to_string(
index));
1274 const auto pin_name = pg->get_name() +
"(" + std::to_string(
index) +
")";
1275 if (
auto collision_pins = m->get_pins([pin_name](
const ModulePin* pin) { return pin->get_name() == pin_name; }); !collision_pins.empty())
1277 m->set_pin_name(collision_pins.front(), pin_name +
"_OLD");
1280 m->set_pin_name(pin, pin_name);
1289 const std::vector<std::pair<u32, std::string>> src_vec = {src};
1290 const std::vector<std::pair<u32, std::string>> dst_vec = {dst};
1299 return ERR(
"cannot propagate bitorder: no source given");
1303 return ERR(
"cannot propagate bitorder: no destination given");
1305 const std::vector<std::pair<Module*, PinGroup<ModulePin>*>> src_vec = {src};
1306 const std::vector<std::pair<Module*, PinGroup<ModulePin>*>> dst_vec = {dst};
1313 std::vector<std::pair<Module*, PinGroup<ModulePin>*>> internal_src;
1314 std::vector<std::pair<Module*, PinGroup<ModulePin>*>> internal_dst;
1317 for (
const auto& [mod_id, pg_name] : src)
1320 if (src_mod ==
nullptr)
1322 return ERR(
"Cannot propagate bit order: failed to find a module with ID " + std::to_string(mod_id));
1326 for (
const auto& pin_group : src_mod->get_pin_groups())
1328 if (pin_group->get_name() == pg_name)
1331 if (src_pin_group !=
nullptr)
1333 return ERR(
"Cannot propagate bit order: found multiple pin groups with name " + pg_name +
" at module with ID " + std::to_string(mod_id));
1336 src_pin_group = pin_group;
1340 if (src_pin_group ==
nullptr)
1342 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));
1345 internal_src.push_back({src_mod, src_pin_group});
1349 for (
const auto& [mod_id, pg_name] : dst)
1352 if (src_mod ==
nullptr)
1354 return ERR(
"Cannot propagate bit order: failed to find a module with ID " + std::to_string(mod_id));
1358 for (
const auto& pin_group : src_mod->get_pin_groups())
1360 if (pin_group->get_name() == pg_name)
1363 if (src_pin_group !=
nullptr)
1365 return ERR(
"Cannot propagate bitorder: found multiple pin groups with name '" + pg_name +
"' at module with ID " + std::to_string(mod_id));
1368 src_pin_group = pin_group;
1372 if (src_pin_group ==
nullptr)
1374 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));
1377 internal_dst.push_back({src_mod, src_pin_group});
1387 std::map<MPG, std::map<Net*, u32>> known_bitorders;
1388 std::set<MPG> unknown_bitorders = {dst.begin(), dst.end()};
1391 for (
auto& [m, pg] : src)
1393 std::map<Net*, u32> src_bitorder;
1398 auto pin_res = pg->get_pin_at_index(
index);
1399 if (pin_res.is_error())
1401 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() +
"'");
1408 known_bitorders.insert({{m, pg}, src_bitorder});
1415 return ERR_APPEND(res.get_error(),
"cannot propagate bit order: failed propagation");
1418 const auto all_wellformed_module_pin_groups = res.get();
1423 #ifdef PRINT_GENERAL
1424 for (
const auto& [mpg, bitorder] : all_wellformed_module_pin_groups)
1427 auto pg = mpg.second;
1429 std::cout <<
"Module: " << m->get_id() <<
" / " << m->get_name() <<
": " << std::endl;
1430 std::cout <<
"Pingroup: " << pg->get_name() <<
": " << std::endl;
1432 for (
const auto& [
net,
index] : bitorder)
1434 std::cout <<
net->get_id() <<
": " <<
index << std::endl;
1440 const u32 all_wellformed_bitorders_count = all_wellformed_module_pin_groups.size();
1441 const u32 new_bit_order_count = all_wellformed_bitorders_count - src.size();
1443 log_info(
"bitorder_propagation",
"reconstructed {} unknown bit orders from {} known bit orders", new_bit_order_count, src.size());
1444 log_info(
"bitorder_propagation",
"{} / {} = {} of all unknown bit orders", new_bit_order_count, dst.size(),
double(new_bit_order_count) /
double(dst.size()));
1446 "{} / {} = {} of all pin group bit orders",
1447 all_wellformed_bitorders_count,
1448 dst.size() + src.size(),
1449 double(all_wellformed_bitorders_count) /
double(dst.size() + src.size()));
1451 return OK(all_wellformed_module_pin_groups);
1456 const std::string& export_filepath)
1458 std::map<MPG, std::map<Net*, u32>> known_bitorders;
1459 std::set<MPG> unknown_bitorders = {dst.begin(), dst.end()};
1462 for (
auto& [m, pg] : src)
1464 std::map<Net*, u32> src_bitorder;
1469 auto pin_res = pg->get_pin_at_index(
index);
1470 if (pin_res.is_error())
1472 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() +
"'");
1479 known_bitorders.insert({{m, pg}, src_bitorder});
1487 const std::string& export_filepath)
1489 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_inwards;
1490 std::map<std::pair<MPG, Net*>, std::vector<std::pair<MPG, std::set<Net*>>>> connectivity_outwards;
1492 std::set<MPG> relevant_pin_groups = unknown_bitorders;
1493 for (
const auto& [kb, _] : known_bitorders)
1495 relevant_pin_groups.insert(kb);
1498 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_outwards;
1499 std::map<std::tuple<Endpoint*, const bool, const Module*>, std::map<MPG, std::set<Net*>>> cache_inwards;
1502 for (
const auto& [m, pg] : relevant_pin_groups)
1504 bool successors = pg->get_direction() == PinDirection::output;
1506 for (
const auto& p : pg->get_pins())
1508 const auto starting_net = p->get_net();
1510 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_outwards;
1511 const auto res_outwards = gather_connected_neighbors(starting_net, successors, relevant_pin_groups,
false,
nullptr, visited_outwards, cache_outwards);
1512 if (res_outwards.is_error())
1515 "cannot porpagate bitorder: failed to gather bit indices outwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
1518 const auto connected_outwards = res_outwards.get();
1520 std::set<std::tuple<Endpoint*, const bool, const Module*>> visited_inwards;
1522 const auto res_inwards = gather_connected_neighbors(starting_net, !successors, relevant_pin_groups,
true, m, visited_inwards, cache_inwards);
1523 if (res_inwards.is_error())
1526 "cannot porpagate bitorder: failed to gather bit indices inwwards starting from the module with ID " + std::to_string(m->get_id()) +
" and pin group "
1529 const auto connected_inwards = res_inwards.get();
1531 for (
const auto& [org_mpg, nets] : connected_outwards)
1533 connectivity_outwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
1536 for (
const auto& [org_mpg, nets] : connected_inwards)
1538 connectivity_inwards[{{m, pg}, starting_net}].push_back({org_mpg, nets});
1543 nlohmann::json info;
1546 std::vector<MPG> mpgs;
1547 std::map<MPG, u32> mpg_to_idx;
1548 std::vector<std::vector<Net*>> words;
1549 std::map<std::string, std::vector<std::string>> word_definitions;
1551 for (
const auto& [m, pg] : relevant_pin_groups)
1553 std::vector<Net*> nets;
1554 std::vector<std::string> nets_str;
1556 for (
const auto& p : pg->get_pins())
1558 const auto& n = p->get_net();
1563 word_definitions.insert({std::to_string(words.size()), nets_str});
1564 mpg_to_idx.insert({{m, pg}, (
unsigned int)mpg_to_idx.size()});
1565 mpgs.push_back({m, pg});
1566 words.push_back(nets);
1569 info[
"word_definitions"] = word_definitions;
1572 std::map<std::string, std::vector<std::string>> known_word_orders;
1574 for (
u32 i = 0; i < mpgs.size(); i++)
1576 const auto& mpg = mpgs.at(i);
1578 if (
const auto it = known_bitorders.find(mpg); it != known_bitorders.end())
1580 std::vector<std::string> ordered_nets_str;
1582 std::vector<std::pair<Net*, u32>> net_index_vec = {it->second.begin(), it->second.end()};
1583 std::sort(net_index_vec.begin(), net_index_vec.end(), [](
const auto& p1,
const auto& p2) { return p1.second < p2.second; });
1584 for (
const auto& [n, _idx] : net_index_vec)
1589 known_word_orders.insert({std::to_string(i), ordered_nets_str});
1593 info[
"known_bit_order"] = known_word_orders;
1596 std::map<std::string, std::vector<std::pair<u32, std::string>>> connected_words;
1597 std::map<std::string, std::vector<std::pair<u32, std::string>>> connected_words_forward;
1598 std::map<std::string, std::vector<std::pair<u32, std::string>>> connected_words_backward;
1600 for (
u32 i = 0; i < mpgs.size(); i++)
1602 const auto& mpg = mpgs.at(i);
1603 const auto& nets = words.at(i);
1605 for (
const auto& src_net : nets)
1607 std::vector<std::pair<u32, std::string>> connections;
1608 std::vector<std::pair<u32, std::string>> connections_forward;
1609 std::vector<std::pair<u32, std::string>> connections_backward;
1611 const auto it_in = connectivity_inwards.find({mpg, src_net});
1612 if (it_in != connectivity_inwards.end())
1614 for (
const auto& [dst_mpg, dst_nets] : it_in->second)
1616 for (
const auto& dst_net : dst_nets)
1624 const auto it_out = connectivity_outwards.find({mpg, src_net});
1625 if (it_out != connectivity_outwards.end())
1627 for (
const auto& [dst_mpg, dst_nets] : it_out->second)
1629 for (
const auto& dst_net : dst_nets)
1637 if (!connections.empty())
1641 connected_words.insert({
identifier, connections});
1643 if (!connections_backward.empty())
1645 connected_words_backward.insert({
identifier, connections_backward});
1648 if (!connections_forward.empty())
1650 connected_words_forward.insert({
identifier, connections_forward});
1656 info[
"connected_words"] = connected_words;
1657 info[
"connected_words_backward"] = connected_words_backward;
1658 info[
"connected_words_forward"] = connected_words_forward;
1661 std::ofstream json_file(export_filepath);
1664 if (json_file.is_open())
1666 json_file << info.dump(4);
1670 return ERR(
"cannot export bitorder information: failed to open file at path " + export_filepath +
" for writing");
1673 return OK(mpg_to_idx);
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< std::map< std::pair< Module *, PinGroup< ModulePin > * >, std::map< Net *, u32 > > > 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< std::map< std::pair< Module *, PinGroup< ModulePin > * >, u32 > > 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...
Result< std::map< MPG, std::map< Net *, u32 > > > propagate_module_pingroup_bitorder(const std::map< MPG, std::map< Net *, u32 >> &known_bitorders, const std::set< MPG > &unknown_bitorders, const bool enforce_continuous_bitorders)
Result< std::map< std::pair< Module *, PinGroup< ModulePin > * >, std::map< Net *, u32 > > > propagate_module_pingroup_bitorder(const std::map< std::pair< Module *, PinGroup< ModulePin > * >, std::map< Net *, u32 >> &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::monostate > reorder_module_pin_groups(const std::map< MPG, std::map< Net *, u32 >> &ordered_module_pin_groups)
std::string enum_to_string(T e)