| #include "pack_report.h" |
| |
| #include "vtr_ostream_guard.h" |
| |
| #include "vpr_types.h" |
| #include "vpr_utils.h" |
| #include "histogram.h" |
| |
| #include <iostream> |
| #include <iomanip> |
| |
| void report_packing_pin_usage(std::ostream& os, const VprContext& ctx) { |
| os << "#Packing pin usage report\n"; |
| |
| auto& cluster_ctx = ctx.clustering(); |
| auto& device_ctx = ctx.device(); |
| |
| std::map<t_physical_tile_type_ptr, size_t> total_input_pins; |
| std::map<t_physical_tile_type_ptr, size_t> total_output_pins; |
| for (auto const& type : device_ctx.physical_tile_types) { |
| if (is_empty_type(&type)) continue; |
| |
| t_pb_type* pb_type = logical_block_type(&type)->pb_type; |
| |
| total_input_pins[&type] = pb_type->num_input_pins + pb_type->num_clock_pins; |
| total_output_pins[&type] = pb_type->num_output_pins; |
| } |
| |
| std::map<t_physical_tile_type_ptr, std::vector<float>> inputs_used; |
| std::map<t_physical_tile_type_ptr, std::vector<float>> outputs_used; |
| |
| for (auto blk : cluster_ctx.clb_nlist.blocks()) { |
| t_physical_tile_type_ptr type = physical_tile_type(blk); |
| |
| inputs_used[type].push_back(cluster_ctx.clb_nlist.block_input_pins(blk).size() + cluster_ctx.clb_nlist.block_clock_pins(blk).size()); |
| outputs_used[type].push_back(cluster_ctx.clb_nlist.block_output_pins(blk).size()); |
| } |
| |
| vtr::OsFormatGuard os_guard(os); |
| |
| os << std::fixed << std::setprecision(2); |
| |
| for (auto const& physical_type : device_ctx.physical_tile_types) { |
| auto type = &physical_type; |
| if (is_empty_type(type)) continue; |
| if (!inputs_used.count(type)) continue; |
| |
| float max_inputs = *std::max_element(inputs_used[type].begin(), inputs_used[type].end()); |
| float min_inputs = *std::min_element(inputs_used[type].begin(), inputs_used[type].end()); |
| float avg_inputs = std::accumulate(inputs_used[type].begin(), inputs_used[type].end(), 0) / float(inputs_used[type].size()); |
| |
| float max_outputs = *std::max_element(outputs_used[type].begin(), outputs_used[type].end()); |
| float min_outputs = *std::min_element(outputs_used[type].begin(), outputs_used[type].end()); |
| float avg_outputs = std::accumulate(outputs_used[type].begin(), outputs_used[type].end(), 0) / float(outputs_used[type].size()); |
| |
| os << "Type: " << type->name << "\n"; |
| |
| os << "\tInput Pin Usage:\n"; |
| os << "\t\tMax: " << max_inputs << " (" << max_inputs / float(total_input_pins[type]) << ")" |
| << "\n"; |
| os << "\t\tAvg: " << avg_inputs << " (" << avg_inputs / float(total_input_pins[type]) << ")" |
| << "\n"; |
| os << "\t\tMin: " << min_inputs << " (" << min_inputs / float(total_input_pins[type]) << ")" |
| << "\n"; |
| |
| if (total_input_pins[type] != 0) { |
| os << "\t\tHistogram:\n"; |
| auto input_histogram = build_histogram(inputs_used[type], 10, 0, total_input_pins[type]); |
| for (auto line : format_histogram(input_histogram)) { |
| os << "\t\t" << line << "\n"; |
| } |
| } |
| |
| os << "\tOutput Pin Usage:\n"; |
| os << "\t\tMax: " << max_outputs << " (" << max_outputs / float(total_output_pins[type]) << ")" |
| << "\n"; |
| os << "\t\tAvg: " << avg_outputs << " (" << avg_outputs / float(total_output_pins[type]) << ")" |
| << "\n"; |
| os << "\t\tMin: " << min_outputs << " (" << min_outputs / float(total_output_pins[type]) << ")" |
| << "\n"; |
| |
| if (total_output_pins[type] != 0) { |
| os << "\t\tHistogram:\n"; |
| |
| auto output_histogram = build_histogram(outputs_used[type], 10, 0, total_output_pins[type]); |
| for (auto line : format_histogram(output_histogram)) { |
| os << "\t\t" << line << "\n"; |
| } |
| } |
| os << "\n"; |
| } |
| } |