From 6c58a4dd9226a2892f88af0b8dfb1fad708f4649 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 12 Nov 2019 10:01:17 -0700 Subject: [PATCH] refactored unused grid block SDC analysis generation --- .../analysis_sdc_grid_writer.cpp | 124 +++++++++++++----- .../module_builder/build_grid_modules.cpp | 2 +- 2 files changed, 93 insertions(+), 33 deletions(-) diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp index 90a58c91c..2a491f129 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp @@ -8,58 +8,107 @@ #include "fpga_x2p_reserved_words.h" #include "fpga_x2p_naming.h" #include "fpga_x2p_utils.h" +#include "fpga_x2p_pbtypes_utils.h" #include "analysis_sdc_grid_writer.h" #include "globals.h" +/******************************************************************** + * Recursively visit all the pb_types in the hierarchy + * and disable all the ports + * + * Note: it is a must to disable all the ports in all the child pb_types! + * This can prohibit timing analyzer to consider any FF-to-FF path or + * combinatinal path inside an unused grid, when finding critical paths!!! + *******************************************************************/ +static +void rec_print_analysis_sdc_disable_unused_pb_graph_nodes(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& parent_module, + const std::string& hierarchy_name, + t_pb_graph_node* physical_pb_graph_node, + const e_side& border_side) { + t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; + + /* Disable all the ports of current module (parent_module)! + * Hierarchy name already includes the instance name of parent_module + */ + fp << "set_disable_timing "; + fp << hierarchy_name; + fp << "/*"; + fp << std::endl; + + /* Return if this is the primitive pb_type */ + if (TRUE == is_primitive_pb_type(physical_pb_type)) { + return; + } + + /* Go recursively */ + int physical_mode_index = find_pb_type_physical_mode_index(*physical_pb_type); + + /* Disable all the ports by iterating over its instance in the parent module */ + for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) { + /* Generate the name of the Verilog module for this child */ + std::string child_module_name_prefix = generate_grid_block_prefix(std::string(GRID_MODULE_NAME_PREFIX), border_side); + std::string child_module_name = generate_physical_block_module_name(child_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild])); + + ModuleId child_module = module_manager.find_module(child_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(child_module)); + + /* Each child may exist multiple times in the hierarchy*/ + for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) { + std::string child_instance_name = module_manager.instance_name(parent_module, child_module, module_manager.child_module_instances(parent_module, child_module)[inst]); + /* Must have a valid instance name!!! */ + VTR_ASSERT(false == child_instance_name.empty()); + + std::string updated_hierarchy_name = hierarchy_name + std::string("/") + child_instance_name + std::string("/"); + + rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, module_manager, child_module, hierarchy_name, + &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst]), + border_side); + } + } +} + /******************************************************************** * Disable the timing for a fully unused grid! * This is very straightforward! * Just walk through each pb_type and disable all the ports using wildcards *******************************************************************/ static -void print_analysis_sdc_disable_unused_pb_type(std::fstream& fp, - t_type_ptr grid_type, - const vtr::Point& grid_coordinate, - const ModuleManager& module_manager, - const size_t& grid_z, - const e_side& border_side) { +void print_analysis_sdc_disable_unused_pb_block(std::fstream& fp, + t_type_ptr grid_type, + const vtr::Point& grid_coordinate, + const ModuleManager& module_manager, + const std::string& grid_instance_name, + const size_t& grid_z, + const e_side& border_side) { /* Check code: if this is an IO block, the border side MUST be valid */ if (IO_TYPE == grid_type) { VTR_ASSERT(NUM_SIDES != border_side); } - /* Find an unique name to the grid instane - * Note: this must be consistent with the instance name we used in build_top_module()!!! - */ - std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_instance_name = generate_grid_block_instance_name(grid_module_name_prefix, std::string(grid_type->name), IO_TYPE == grid_type, border_side, grid_coordinate); - /* Find an unique name to the pb instance in this grid * Note: this must be consistent with the instance name we used in build_grid_module()!!! */ + /* TODO: validate that the instance name is used in module manager!!! */ std::string pb_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string pb_module_name = generate_grid_physical_block_module_name(pb_module_name_prefix, grid_type->pb_graph_head->pb_type, border_side); std::string pb_instance_name = generate_grid_physical_block_instance_name(pb_module_name_prefix, grid_type->pb_graph_head->pb_type, border_side, grid_z); + ModuleId pb_module = module_manager.find_module(pb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); + /* Print comments */ fp << "#######################################" << std::endl; fp << "# Disable Timing for unused grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "][" << grid_z << "]" << std::endl; fp << "#######################################" << std::endl; - - /* Disable everything under this level using wildcard */ - fp << "set_disable_timing "; - fp << grid_instance_name; - fp << "/"; - fp << pb_instance_name; - fp << "/*"; - fp << std::endl; - /* TODO: Go recursively through the pb_graph hierarchy, and disable all the ports level by level */ - /* - rec_verilog_generate_sdc_disable_unused_pb_types(fp, prefix, - cur_grid_type->pb_type); - */ + std::string hierarchy_name = grid_instance_name + std::string("/") + pb_instance_name + std::string("/"); + + /* Go recursively through the pb_graph hierarchy, and disable all the ports level by level */ + rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, module_manager, pb_module, hierarchy_name, grid_type->pb_graph_head, border_side); } /******************************************************************** @@ -77,19 +126,30 @@ void print_analysis_sdc_disable_unused_grid(std::fstream& fp, /* Validate file stream */ check_file_handler(fp); - t_type_ptr type = L_grids[grid_coordinate.x()][grid_coordinate.y()].type; + t_type_ptr grid_type = L_grids[grid_coordinate.x()][grid_coordinate.y()].type; /* Bypass conditions for grids : * 1. EMPTY type, which is by nature unused * 2. Offset > 0, which has already been processed when offset = 0 */ - if ( (NULL == type) - || (EMPTY_TYPE == type) + if ( (NULL == grid_type) + || (EMPTY_TYPE == grid_type) || (0 == L_grids[grid_coordinate.x()][grid_coordinate.y()].offset) ) { return; } + /* Find an unique name to the grid instane + * Note: this must be consistent with the instance name we used in build_top_module()!!! + */ + /* TODO: validate that the instance name is used in module manager!!! */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), IO_TYPE == grid_type, border_side); + std::string grid_instance_name = generate_grid_block_instance_name(grid_module_name_prefix, std::string(grid_type->name), IO_TYPE == grid_type, border_side, grid_coordinate); + + ModuleId grid_module = module_manager.find_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + /* Now we need to find the usage of this grid */ - std::vector grid_usage(type->capacity, false); + std::vector grid_usage(grid_type->capacity, false); /* Print comments */ fp << "#######################################" << std::endl; @@ -102,7 +162,7 @@ void print_analysis_sdc_disable_unused_grid(std::fstream& fp, */ for (int iblk = 0; iblk < L_grids[grid_coordinate.x()][grid_coordinate.y()].usage; ++iblk) { int blk_id = L_grids[grid_coordinate.x()][grid_coordinate.y()].blocks[iblk]; - VTR_ASSERT( (OPEN < L_blocks[blk_id].z) && (L_blocks[blk_id].z < type->capacity) ); + VTR_ASSERT( (OPEN < L_blocks[blk_id].z) && (L_blocks[blk_id].z < grid_type->capacity) ); /* Mark the grid_usage */ grid_usage[L_blocks[blk_id].z] = true; /* TODO: @@ -111,12 +171,12 @@ void print_analysis_sdc_disable_unused_grid(std::fstream& fp, } /* For unused grid, disable all the pins in the physical_pb_type */ - for (int iblk = 0; iblk < type->capacity; ++iblk) { + for (int iblk = 0; iblk < grid_type->capacity; ++iblk) { /* Bypass used blocks */ if (true == grid_usage[iblk]) { continue; } - print_analysis_sdc_disable_unused_pb_type(fp, type, grid_coordinate, module_manager, iblk, border_side); + print_analysis_sdc_disable_unused_pb_block(fp, grid_type, grid_coordinate, module_manager, grid_instance_name, iblk, border_side); } } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp index e23ec60f9..a05d6abf7 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp @@ -926,7 +926,7 @@ void rec_build_physical_block_modules(ModuleManager& module_manager, /* Add the memory module as a child of primitive module */ module_manager.add_child_module(pb_module, child_pb_module); - /* Set an instance name to bind to a block in bitstream generation */ + /* Set an instance name to bind to a block in bitstream generation and SDC generation! */ std::string child_pb_instance_name = generate_physical_block_instance_name(pb_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild]), inst); module_manager.set_child_instance_name(pb_module, child_pb_module, child_instance_id, child_pb_instance_name);