diff --git a/openfpga/src/base/io_location_map.cpp b/openfpga/src/base/io_location_map.cpp index 7e0c07dfa..460ba080d 100644 --- a/openfpga/src/base/io_location_map.cpp +++ b/openfpga/src/base/io_location_map.cpp @@ -29,15 +29,15 @@ size_t IoLocationMap::io_index(const size_t& x, const size_t& y, const size_t& z void IoLocationMap::set_io_index(const size_t& x, const size_t& y, const size_t& z, const size_t& io_index) { if (x >= io_indices_.size()) { - io_indices_.resize(x); + io_indices_.resize(x + 1); } if (y >= io_indices_[x].size()) { - io_indices_[x].resize(y); + io_indices_[x].resize(y + 1); } if (z >= io_indices_[x][y].size()) { - io_indices_[x][y].resize(z); + io_indices_[x][y].resize(z + 1); } io_indices_[x][y][z] = io_index; diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 5c3d8a69d..a1e90055b 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -21,43 +21,43 @@ namespace openfpga { * This function should only be called after the GSB builder is done *******************************************************************/ static -void compress_routing_hierarchy(OpenfpgaContext& openfpga_context, +void compress_routing_hierarchy(OpenfpgaContext& openfpga_ctx, const bool& verbose_output) { vtr::ScopedStartFinishTimer timer("Identify unique General Switch Blocks (GSBs)"); /* Build unique module lists */ - openfpga_context.mutable_device_rr_gsb().build_unique_module(g_vpr_ctx.device().rr_graph); + openfpga_ctx.mutable_device_rr_gsb().build_unique_module(g_vpr_ctx.device().rr_graph); /* 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)); + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANX), + 100 * (openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX) / find_device_rr_gsb_num_cb_modules(openfpga_ctx.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)); + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANY), + 100 * (openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY) / find_device_rr_gsb_num_cb_modules(openfpga_ctx.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)); + openfpga_ctx.device_rr_gsb().get_num_sb_unique_module(), + find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()), + 100 * (openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() / find_device_rr_gsb_num_sb_modules(openfpga_ctx.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)); + openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module(), + find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()), + 100 * (openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() / find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()) - 1)); } /******************************************************************** * Build the module graph for FPGA device *******************************************************************/ -void build_fabric(OpenfpgaContext& openfpga_context, +void build_fabric(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_compress_routing = cmd.option("compress_routing"); @@ -65,16 +65,17 @@ void build_fabric(OpenfpgaContext& openfpga_context, CommandOptionId opt_verbose = cmd.option("verbose"); if (true == cmd_context.option_enable(cmd, opt_compress_routing)) { - compress_routing_hierarchy(openfpga_context, cmd_context.option_enable(cmd, opt_verbose)); + compress_routing_hierarchy(openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); } VTR_LOG("\n"); - openfpga_context.mutable_module_graph() = build_device_module_graph(g_vpr_ctx.device(), - const_cast(openfpga_context), - cmd_context.option_enable(cmd, opt_compress_routing), - cmd_context.option_enable(cmd, opt_duplicate_grid_pin), - cmd_context.option_enable(cmd, opt_verbose)); + openfpga_ctx.mutable_module_graph() = build_device_module_graph(openfpga_ctx.mutable_io_location_map(), + g_vpr_ctx.device(), + const_cast(openfpga_ctx), + cmd_context.option_enable(cmd, opt_compress_routing), + cmd_context.option_enable(cmd, opt_duplicate_grid_pin), + cmd_context.option_enable(cmd, opt_verbose)); } } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_build_fabric.h b/openfpga/src/base/openfpga_build_fabric.h index 44aa3632c..824ed63a1 100644 --- a/openfpga/src/base/openfpga_build_fabric.h +++ b/openfpga/src/base/openfpga_build_fabric.h @@ -15,7 +15,7 @@ /* begin namespace openfpga */ namespace openfpga { -void build_fabric(OpenfpgaContext& openfpga_context, +void build_fabric(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index a137407ed..9680285fa 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -26,7 +26,8 @@ namespace openfpga { * The main function to be called for building module graphs * for a FPGA fabric *******************************************************************/ -ModuleManager build_device_module_graph(const DeviceContext& vpr_device_ctx, +ModuleManager build_device_module_graph(IoLocationMap& io_location_map, + const DeviceContext& vpr_device_ctx, const OpenfpgaContext& openfpga_ctx, const bool& compress_routing, const bool& duplicate_grid_pin, @@ -97,7 +98,8 @@ ModuleManager build_device_module_graph(const DeviceContext& vpr_device_ctx, } /* Build FPGA fabric top-level module */ - build_top_module(module_manager, openfpga_ctx.arch().circuit_lib, + build_top_module(module_manager, io_location_map, + openfpga_ctx.arch().circuit_lib, vpr_device_ctx.grid, vpr_device_ctx.rr_graph, openfpga_ctx.device_rr_gsb(), diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index fd585d986..b8f8c0ac8 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -14,7 +14,8 @@ /* begin namespace openfpga */ namespace openfpga { -ModuleManager build_device_module_graph(const DeviceContext& vpr_device_ctx, +ModuleManager build_device_module_graph(IoLocationMap& io_location_map, + const DeviceContext& vpr_device_ctx, const OpenfpgaContext& openfpga_ctx, const bool& compress_routing, const bool& duplicate_grid_pin, diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 3357b2b95..7af79d46c 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -89,6 +89,7 @@ size_t add_top_module_grid_instance(ModuleManager& module_manager, static vtr::Matrix add_top_module_grid_instances(ModuleManager& module_manager, const ModuleId& top_module, + IoLocationMap& io_location_map, const DeviceGrid& grids) { /* Reserve an array for the instance ids */ vtr::Matrix grid_instance_ids({grids.width(), grids.height()}); @@ -142,6 +143,7 @@ vtr::Matrix add_top_module_grid_instances(ModuleManager& module_manager, } /* Add instances of I/O grids to top_module */ + size_t io_counter = 0; for (const e_side& io_side : io_sides) { for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { /* Bypass EMPTY grid */ @@ -157,6 +159,21 @@ vtr::Matrix add_top_module_grid_instances(ModuleManager& module_manager, VTR_ASSERT(true == is_io_type(grids[io_coordinate.x()][io_coordinate.y()].type)); /* Add a grid module to top_module*/ grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = add_top_module_grid_instance(module_manager, top_module, grids[io_coordinate.x()][io_coordinate.y()].type, io_side, io_coordinate); + + /* MUST DO: register in io location mapping! + * I/O location mapping is a critical look-up for testbench generators + * As we add the I/O grid instances to top module by following order: + * TOP -> RIGHT -> BOTTOM -> LEFT + * The I/O index will increase in this way as well. + * This organization I/O indices is also consistent to the way + * that GPIOs are wired in function connect_gpio_module() + * + * Note: if you change the GPIO function, you should update here as well! + */ + for (int z = 0; z < grids[io_coordinate.x()][io_coordinate.y()].type->capacity; ++z) { + io_location_map.set_io_index(io_coordinate.x(), io_coordinate.y(), z, io_counter); + } + io_counter++; } } @@ -280,6 +297,7 @@ vtr::Matrix add_top_module_connection_block_instances(ModuleManager& mod * 5. Add module nets/submodules to connect configuration ports *******************************************************************/ void build_top_module(ModuleManager& module_manager, + IoLocationMap& io_location_map, const CircuitLibrary& circuit_lib, const DeviceGrid& grids, const RRGraph& rr_graph, @@ -301,7 +319,7 @@ void build_top_module(ModuleManager& module_manager, /* Add sub modules, which are grid, SB and CBX/CBY modules as instances */ /* Add all the grids across the fabric */ - vtr::Matrix grid_instance_ids = add_top_module_grid_instances(module_manager, top_module, grids); + vtr::Matrix grid_instance_ids = add_top_module_grid_instances(module_manager, top_module, io_location_map, grids); /* Add all the SBs across the fabric */ vtr::Matrix sb_instance_ids = add_top_module_switch_block_instances(module_manager, top_module, device_rr_gsb, compact_routing_hierarchy); /* Add all the CBX and CBYs across the fabric */ diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index 3b6badfb2..4ced0735b 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -14,6 +14,7 @@ #include "tile_direct.h" #include "arch_direct.h" #include "module_manager.h" +#include "io_location_map.h" /******************************************************************** * Function declaration @@ -23,6 +24,7 @@ namespace openfpga { void build_top_module(ModuleManager& module_manager, + IoLocationMap& io_location_map, const CircuitLibrary& circuit_lib, const DeviceGrid& grids, const RRGraph& rr_graph,