diff --git a/openfpga/src/annotation/annotate_rr_gsb.cpp b/openfpga/src/annotation/annotate_rr_gsb.cpp index 8050110e5..dca399abd 100644 --- a/openfpga/src/annotation/annotate_rr_gsb.cpp +++ b/openfpga/src/annotation/annotate_rr_gsb.cpp @@ -374,7 +374,7 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, const RRGSB& rr_gsb = build_rr_gsb(vpr_device_ctx, vtr::Point(vpr_device_ctx.grid.width() - 2, vpr_device_ctx.grid.height() - 2), vtr::Point(ix, iy)); - /* TODO: sort drive_rr_nodes should be done when building the tileable rr_graph? */ + /* TODO: sort drive_rr_nodes should be done when building the tileable rr_graph */ //sort_rr_gsb_drive_rr_nodes(rr_gsb); /* Add to device_rr_gsb */ diff --git a/openfpga/src/annotation/device_rr_gsb.cpp b/openfpga/src/annotation/device_rr_gsb.cpp index 9152f209c..6fa808823 100644 --- a/openfpga/src/annotation/device_rr_gsb.cpp +++ b/openfpga/src/annotation/device_rr_gsb.cpp @@ -53,6 +53,29 @@ size_t DeviceRRGSB::get_num_cb_unique_module(const t_rr_type& cb_type) const { } } +/* Identify if a GSB actually exists at a location */ +bool DeviceRRGSB::is_gsb_exist(const vtr::Point coord) const { + /* Out of range, does not exist */ + if (false == validate_coordinate(coord)) { + return false; + } + + /* If the GSB is empty, it does not exist */ + if (true == get_gsb(coord).is_cb_exist(CHANX)) { + return true; + } + + if (true == get_gsb(coord).is_cb_exist(CHANY)) { + return true; + } + + if (true == get_gsb(coord).is_sb_exist()) { + return true; + } + + return false; +} + /* get the number of unique mirrors of switch blocks */ size_t DeviceRRGSB::get_num_sb_unique_module() const { return sb_unique_module_.size(); diff --git a/openfpga/src/annotation/device_rr_gsb.h b/openfpga/src/annotation/device_rr_gsb.h index 624492124..eae0afa1d 100644 --- a/openfpga/src/annotation/device_rr_gsb.h +++ b/openfpga/src/annotation/device_rr_gsb.h @@ -37,6 +37,7 @@ class DeviceRRGSB { const RRGSB& get_cb_unique_module(const t_rr_type& cb_type, const size_t& index) const; /* Get a rr switch block which a unique mirror */ const RRGSB& get_cb_unique_module(const t_rr_type& cb_type, const vtr::Point& coordinate) const; size_t get_num_cb_unique_module(const t_rr_type& cb_type) const; /* get the number of unique mirrors of CBs */ + bool is_gsb_exist(const vtr::Point coord) const; public: /* Mutators */ void reserve(const vtr::Point& coordinate); /* Pre-allocate the rr_switch_block array that the device requires */ void reserve_sb_unique_submodule_id(const vtr::Point& coordinate); /* Pre-allocate the rr_sb_unique_module_id matrix that the device requires */ diff --git a/openfpga/src/annotation/rr_gsb.cpp b/openfpga/src/annotation/rr_gsb.cpp index 6b8cd5236..cd57d8e6b 100644 --- a/openfpga/src/annotation/rr_gsb.cpp +++ b/openfpga/src/annotation/rr_gsb.cpp @@ -348,6 +348,21 @@ bool RRGSB::is_cb_exist(const t_rr_type& cb_type) const { return (0 != get_cb_chan_width(cb_type)); } +/* check if the SB exist in this GSB */ +bool RRGSB::is_sb_exist() const { + /* if all the channel width is zero and number of OPINs are zero, there is no SB */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + if (0 != get_chan_width(side_manager.get_side())) { + return true; + } + if (0 != get_num_opin_nodes(side_manager.get_side())) { + return true; + } + } + + return false; +} /************************************************************************ * Check if the node indicates a passing wire across the Switch Block part of the GSB diff --git a/openfpga/src/annotation/rr_gsb.h b/openfpga/src/annotation/rr_gsb.h index 4f3af9552..4541c88dd 100644 --- a/openfpga/src/annotation/rr_gsb.h +++ b/openfpga/src/annotation/rr_gsb.h @@ -114,9 +114,12 @@ class RRGSB { /* check if the candidate SB is a mirror of the current one */ bool is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const; - /* check if the candidate SB is a mirror of the current one */ + /* check if the connect block exists in the GSB */ bool is_cb_exist(const t_rr_type& cb_type) const; + /* check if the switch block exists in the GSB */ + bool is_sb_exist() const; + /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */ bool is_sb_node_passing_wire(const RRGraph& rr_graph, const e_side& node_side, const size_t& track_id) const; diff --git a/openfpga/src/base/compact_routing_hierarchy.cpp b/openfpga/src/base/compact_routing_hierarchy.cpp new file mode 100644 index 000000000..e520b5e3f --- /dev/null +++ b/openfpga/src/base/compact_routing_hierarchy.cpp @@ -0,0 +1,60 @@ +/******************************************************************** + * This file includes functions to compress the hierachy of routing architecture + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_time.h" +#include "vtr_log.h" + +#include "device_rr_gsb.h" +#include "device_rr_gsb_utils.h" +#include "compact_routing_hierarchy.h" + +/* Include global variables of VPR */ +#include "globals.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Identify the unique GSBs from the Device RR GSB arrays + * This function should only be called after the GSB builder is done + *******************************************************************/ +void compact_routing_hierarchy(OpenfpgaContext& openfpga_context, + const Command& cmd, const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer("Identify unique General Switch Blocks (GSBs)"); + + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* Build unique module lists */ + openfpga_context.mutable_device_rr_gsb().build_unique_module(g_vpr_ctx.device().rr_graph); + + bool verbose_output = cmd_context.option_enable(cmd, opt_verbose); + + /* Report the stats */ + VTR_LOGV(verbose_output, + "Detected %lu unique X-direction connection blocks from a total of %d (compression rate=%d%)\n", + openfpga_context.device_rr_gsb().get_num_cb_unique_module(CHANX), + find_device_rr_gsb_num_cb_modules(openfpga_context.device_rr_gsb(), CHANX), + 100 * (openfpga_context.device_rr_gsb().get_num_cb_unique_module(CHANX) / find_device_rr_gsb_num_cb_modules(openfpga_context.device_rr_gsb(), CHANX) - 1)); + + VTR_LOGV(verbose_output, + "Detected %lu unique Y-direction connection blocks from a total of %d (compression rate=%d%)\n", + openfpga_context.device_rr_gsb().get_num_cb_unique_module(CHANY), + find_device_rr_gsb_num_cb_modules(openfpga_context.device_rr_gsb(), CHANY), + 100 * (openfpga_context.device_rr_gsb().get_num_cb_unique_module(CHANY) / find_device_rr_gsb_num_cb_modules(openfpga_context.device_rr_gsb(), CHANY) - 1)); + + VTR_LOGV(verbose_output, + "Detected %lu unique switch blocks from a total of %d (compression rate=%d%)\n", + openfpga_context.device_rr_gsb().get_num_sb_unique_module(), + find_device_rr_gsb_num_sb_modules(openfpga_context.device_rr_gsb()), + 100 * (openfpga_context.device_rr_gsb().get_num_sb_unique_module() / find_device_rr_gsb_num_sb_modules(openfpga_context.device_rr_gsb()) - 1)); + + VTR_LOGV(verbose_output, + "Detected %lu unique general switch blocks from a total of %d (compression rate=%d%)\n", + openfpga_context.device_rr_gsb().get_num_gsb_unique_module(), + find_device_rr_gsb_num_gsb_modules(openfpga_context.device_rr_gsb()), + 100 * (openfpga_context.device_rr_gsb().get_num_gsb_unique_module() / find_device_rr_gsb_num_gsb_modules(openfpga_context.device_rr_gsb()) - 1)); + +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/base/compact_routing_hierarchy.h b/openfpga/src/base/compact_routing_hierarchy.h new file mode 100644 index 000000000..bd3eeefe2 --- /dev/null +++ b/openfpga/src/base/compact_routing_hierarchy.h @@ -0,0 +1,23 @@ +#ifndef COMPACT_ROUTING_HIERARCHY_H +#define COMPACT_ROUTING_HIERARCHY_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "command.h" +#include "command_context.h" +#include "openfpga_context.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void compact_routing_hierarchy(OpenfpgaContext& openfpga_context, + const Command& cmd, const CommandContext& cmd_context); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/base/openfpga_setup_command.cpp b/openfpga/src/base/openfpga_setup_command.cpp index 629300bf2..2d08ec38c 100644 --- a/openfpga/src/base/openfpga_setup_command.cpp +++ b/openfpga/src/base/openfpga_setup_command.cpp @@ -8,6 +8,8 @@ #include "openfpga_pb_pin_fixup.h" #include "openfpga_lut_truth_table_fixup.h" #include "check_netlist_naming_conflict.h" +#include "annotate_rr_gsb.h" +#include "compact_routing_hierarchy.h" #include "openfpga_setup_command.h" /* begin namespace openfpga */ @@ -113,11 +115,27 @@ void add_openfpga_setup_commands(openfpga::Shell& shell) { ShellCommandId shell_cmd_lut_truth_table_fixup_id = shell.add_command(shell_cmd_lut_truth_table_fixup, "Fix up the truth table of Look-Up Tables due to pin swapping during packing stage"); shell.set_command_class(shell_cmd_lut_truth_table_fixup_id, openfpga_setup_cmd_class); shell.set_command_execute_function(shell_cmd_lut_truth_table_fixup_id, lut_truth_table_fixup); - /* The 'pb_pin_fixup' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */ + /* The 'lut_truth_table_fixup' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */ std::vector cmd_dependency_lut_truth_table_fixup; cmd_dependency_lut_truth_table_fixup.push_back(shell_cmd_read_arch_id); cmd_dependency_lut_truth_table_fixup.push_back(shell_cmd_vpr_id); shell.set_command_dependency(shell_cmd_lut_truth_table_fixup_id, cmd_dependency_lut_truth_table_fixup); + + /******************************** + * Command 'compact_routing_hierarchy' + */ + Command shell_cmd_compact_routing_hierarchy("compact_routing_hierarchy"); + /* Add an option '--verbose' */ + shell_cmd_compact_routing_hierarchy.add_option("verbose", false, "Show verbose outputs"); + + /* Add command 'compact_routing_hierarchy' to the Shell */ + ShellCommandId shell_cmd_compact_routing_hierarchy_id = shell.add_command(shell_cmd_compact_routing_hierarchy, "Identify the unique GSBs in the routing architecture so that the routing hierarchy of fabric can be compressed"); + shell.set_command_class(shell_cmd_compact_routing_hierarchy_id, openfpga_setup_cmd_class); + shell.set_command_execute_function(shell_cmd_compact_routing_hierarchy_id, compact_routing_hierarchy); + /* The 'compact_routing_hierarchy' command should NOT be executed before 'link_openfpga_arch' */ + std::vector cmd_dependency_compact_routing_hierarchy; + cmd_dependency_lut_truth_table_fixup.push_back(shell_cmd_link_openfpga_arch_id); + shell.set_command_dependency(shell_cmd_compact_routing_hierarchy_id, cmd_dependency_compact_routing_hierarchy); } } /* end namespace openfpga */ diff --git a/openfpga/src/utils/device_rr_gsb_utils.cpp b/openfpga/src/utils/device_rr_gsb_utils.cpp new file mode 100644 index 000000000..dfda5618a --- /dev/null +++ b/openfpga/src/utils/device_rr_gsb_utils.cpp @@ -0,0 +1,68 @@ +/******************************************************************** + * This file includes most utilized functions for data structure + * DeviceRRGSB + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "device_rr_gsb_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function aims to find out the number of connection block + * modules in the device rr_gsb array + *******************************************************************/ +size_t find_device_rr_gsb_num_cb_modules(const DeviceRRGSB& device_rr_gsb, + const t_rr_type& cb_type) { + size_t counter = 0; + for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { + for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(x, y); + if (true == rr_gsb.is_cb_exist(cb_type)) { + counter++; + } + } + } + + return counter; +} + +/******************************************************************** + * This function aims to find out the number of switch block + * modules in the device rr_gsb array + *******************************************************************/ +size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb) { + size_t counter = 0; + for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { + for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(x, y); + if (true == rr_gsb.is_sb_exist()) { + counter++; + } + } + } + + return counter; +} + +/******************************************************************** + * This function aims to find out the number of GSBs + *******************************************************************/ +size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb) { + size_t counter = 0; + for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { + for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { + if (true == device_rr_gsb.is_gsb_exist(vtr::Point(x, y))) { + counter++; + } + } + } + + return counter; + +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/utils/device_rr_gsb_utils.h b/openfpga/src/utils/device_rr_gsb_utils.h new file mode 100644 index 000000000..7b49839a9 --- /dev/null +++ b/openfpga/src/utils/device_rr_gsb_utils.h @@ -0,0 +1,27 @@ +#ifndef DEVICE_RR_GSB_UTILS_H +#define DEVICE_RR_GSB_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include +#include "device_rr_gsb.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +size_t find_device_rr_gsb_num_cb_modules(const DeviceRRGSB& device_rr_gsb, + const t_rr_type& cb_type); + +size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb); + +size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/test_script/s298_k6_frac.openfpga b/openfpga/test_script/s298_k6_frac.openfpga index f4a5bc979..dd87c77df 100644 --- a/openfpga/test_script/s298_k6_frac.openfpga +++ b/openfpga/test_script/s298_k6_frac.openfpga @@ -16,5 +16,8 @@ pb_pin_fixup --verbose # Apply fix-up to Look-Up Table truth tables based on packing results lut_truth_table_fixup --verbose +# Compress the routing hierarchy +compact_routing_hierarchy --verbose + # Finish and exit OpenFPGA exit