openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp
/********************************************************************
 * Recursively visit all the pb_types in the hierarchy 
 * and disable all the unused resources, including:
 * 1. input ports
 * 2. output ports
 * 3. unused inputs of routing multiplexers
 *
 * As this function is executed in a recursive way. 
 * To avoid repeated disable timing for ports, during each run of this function,
 * only the unused input ports, output ports of the parent module will be disabled.
 * In addition, we will cache all the net ids mapped to the input ports of 
 * child modules, and the net ids mapped to the output ports of parent module.
 * As such, we can trace from 
 * 1. the input ports of parent module to disable unused inputs of routing multiplexer
 *    which drives the inputs of child modules
 *                      
 *                          Parent_module
 *                         +---------------------------------------------
 *                         |          MUX                  child_module
 *                         |         +-------------+       +--------
 *    input_pin0(netA) --->|-------->| Routing     |------>|
 *    input_pin1(netB) --->|----x--->| Multiplexer | netA  |
 *                         |         +-------------+       |
 *                         |                               |
 *
 * 2. the output ports of child module to disable unused inputs of routing multiplexer
 *    which drives the outputs of parent modules
 *
 *   Case 1: 
 *                                  parent_module
 *         --------------------------------------+
 *         child_module                          |
 *        -------------+                         |
 *                     |    +-------------+      |
 *  output_pin0 (netA) |--->| Routing     |----->|---->
 *  output_pin1 (netB) |-x->| Multiplexer | netA |
 *                     |    +-------------+      |
 *
 *    Case 2: 
 *
 *                         Parent_module
 *                         +---------------------------------------------
 *                         |
 *                         |    +--------------------------------------------+
 *                         |    |     MUX                  child_module      |
 *                         |    |    +-------------+       +-----------+     |
 *                         |    +--->| Routing     |------>|           |     |
 *    input_pin0(netA) --->|----x--->| Multiplexer | netA  | output_pin|-----+
 *                         |         +-------------+       |           | netA
 *                         |                               |           |
 *
 *
 * 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!!!
 *******************************************************************/
Recursively visit all the pb_types in the hierarchy
and disable all the unused resources, including:
1. input ports
2. output ports
3. unused inputs of routing multiplexers

As this function is executed in a recursive way.
To avoid repeated disable timing for ports, during each run of this function,
only the unused input ports, output ports of the parent module will be disabled.
In addition, we will cache all the net ids mapped to the input ports of
child modules, and the net ids mapped to the output ports of parent module.
As such, we can trace from
1. the input ports of parent module to disable unused inputs of routing multiplexer
which drives the inputs of child modules



2. the output ports of child module to disable unused inputs of routing multiplexer
which drives the outputs of parent modules



Case 2.



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
Recursively visit all the pb_types in the hierarchy and disable all the unused resources including : 1 . input ports 2 . output ports 3 . unused inputs of routing multiplexers As this function is executed in a recursive way . To avoid repeated disable timing for ports during each run of this function only the unused input ports output ports of the parent module will be disabled . In addition we will cache all the net ids mapped to the input ports of child modules and the net ids mapped to the output ports of parent module . As such we can trace from 1 . the input ports of parent module to disable unused inputs of routing multiplexer which drives the inputs of child modules 2 . the output ports of child module to disable unused inputs of routing multiplexer which drives the outputs of parent modules Case 2 . 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_pb_graph_node_unused_resources(std::fstream& fp, 
                                                                   const VprDeviceAnnotation& device_annotation,
                                                                   const ModuleManager& module_manager,
                                                                   const ModuleId& parent_module,
                                                                   const std::string& hierarchy_name,
                                                                   t_pb_graph_node* physical_pb_graph_node,
                                                                   const PhysicalPb& physical_pb) {
  t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type;
  disable_pb_graph_node_unused_pins(fp, module_manager, parent_module,
                                    hierarchy_name, physical_pb_graph_node, physical_pb); 
  if (true == is_primitive_pb_type(physical_pb_type)) {
    return;
  }
  disable_pb_graph_node_unused_mux_inputs(fp, device_annotation,
                                          module_manager, parent_module, 
                                          hierarchy_name, physical_pb_graph_node,
                                          physical_pb);
  t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type);
  for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) {
    std::string child_module_name = generate_physical_block_module_name(&(physical_mode->pb_type_children[ichild]));
    ModuleId child_module = module_manager.find_module(child_module_name);
    VTR_ASSERT(true == module_manager.valid_module_id(child_module));
    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]);
      VTR_ASSERT(false == child_instance_name.empty()); 
      std::string updated_hierarchy_name = hierarchy_name + child_instance_name + std::string("/");
      rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(fp, device_annotation,
                                                                    module_manager, child_module, updated_hierarchy_name, 
                                                                    &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst]), 
                                                                    physical_pb); 
    }
  }
}
static void rec_print_analysis_sdc_disable_pb_graph_node_unused_resources ( std :: fstream & fp , const VprDeviceAnnotation & device_annotation , const ModuleManager & module_manager , const ModuleId & parent_module , const std :: string & hierarchy_name , t_pb_graph_node * physical_pb_graph_node , const PhysicalPb & physical_pb ) { t_pb_type * physical_pb_type = physical_pb_graph_node -> pb_type ; disable_pb_graph_node_unused_pins ( fp , module_manager , parent_module , hierarchy_name , physical_pb_graph_node , physical_pb ) ; if ( true == is_primitive_pb_type ( physical_pb_type ) ) { return ; } disable_pb_graph_node_unused_mux_inputs ( fp , device_annotation , module_manager , parent_module , hierarchy_name , physical_pb_graph_node , physical_pb ) ; t_mode * physical_mode = device_annotation . physical_mode ( physical_pb_type ) ; for ( int ichild = 0 ; ichild < physical_mode -> num_pb_type_children ; ++ ichild ) { std :: string child_module_name = generate_physical_block_module_name ( & ( physical_mode -> pb_type_children [ ichild ] ) ) ; ModuleId child_module = module_manager . find_module ( child_module_name ) ; VTR_ASSERT ( true == module_manager . valid_module_id ( child_module ) ) ; 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 ] ) ; VTR_ASSERT ( false == child_instance_name . empty ( ) ) ; std :: string updated_hierarchy_name = hierarchy_name + child_instance_name + std :: string ( " " ) ; rec_print_analysis_sdc_disable_pb_graph_node_unused_resources ( fp , device_annotation , module_manager , child_module , updated_hierarchy_name , & ( physical_pb_graph_node -> child_pb_graph_nodes [ physical_mode -> index ] [ ichild ] [ inst ] ) , physical_pb ) ; } } }
Recursively visit all the pb_types in the hierarchy
 and disable all the unused resources, including:
 1. input ports
 2. output ports
 3. unused inputs of routing multiplexers
Recursively visit all the pb_types in the hierarchy and disable all the unused resources including : 1 . input ports 2 . output ports 3 . unused inputs of routing multiplexers
/* Disable unused input ports and output ports of this pb_graph_node (parent_module) */ /* Return if this is the primitive pb_type 
   * Note: this must return before we disable any unused inputs of routing multiplexer!
   * This is due to that primitive pb_type does NOT contain any routing multiplexers inside!!!   
   */ /* Disable unused inputs of routing multiplexers of this pb_graph_node */ /* Disable all the ports by iterating over its instance in the parent module */ /* Generate the name of the Verilog module for this child */ /* Each child may exist multiple times in the hierarchy*/ /* Must have a valid instance name!!! */