openfpga/src/fpga_spice/spice_grid.cpp
/********************************************************************
 * Print SPICE subckts of physical blocks inside a grid (CLB, I/O. etc.)
 * This function will traverse the graph of complex logic block (t_pb_graph_node)
 * in a recursive way, using a Depth First Search (DFS) algorithm.
 * As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of the pb_graph
 * will be printed out first, while the top-level will be printed out in the last
 *
 * Note: this function will print a unique SPICE subckt for each type of 
 * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly 
 * hierarchical Verilog organization as well as simplify the Verilog file sizes.
 *
 * Note: DFS is the right way. Do NOT use BFS.
 * DFS can guarantee that all the sub-modules can be registered properly
 * to its parent in module manager  
 *******************************************************************/
Print SPICE subckts of physical blocks inside a grid (CLB, I/O. etc.)
This function will traverse the graph of complex logic block (t_pb_graph_node)
in a recursive way, using a Depth First Search (DFS) algorithm.
As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of the pb_graph
will be printed out first, while the top-level will be printed out in the last

this function will print a unique SPICE subckt for each type of
t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly
hierarchical Verilog organization as well as simplify the Verilog file sizes.

DFS is the right way. Do NOT use BFS.
DFS can guarantee that all the sub-modules can be registered properly
to its parent in module manager
Print SPICE subckts of physical blocks inside a grid ( CLB I / O . etc . ) This function will traverse the graph of complex logic block ( t_pb_graph_node ) in a recursive way using a Depth First Search ( DFS ) algorithm . As such primitive physical blocks ( LUTs FFs etc . ) leaf node of the pb_graph will be printed out first while the top - level will be printed out in the last this function will print a unique SPICE subckt for each type of t_pb_graph_node i . e . t_pb_type in the graph in order to enable highly hierarchical Verilog organization as well as simplify the Verilog file sizes . DFS is the right way . Do NOT use BFS . DFS can guarantee that all the sub - modules can be registered properly to its parent in module manager
static 
void rec_print_spice_logical_tile(NetlistManager& netlist_manager,
                                  const ModuleManager& module_manager,
                                  const VprDeviceAnnotation& device_annotation,
                                  const std::string& subckt_dir,
                                  t_pb_graph_node* physical_pb_graph_node,
                                  const bool& verbose) {
  if (nullptr == physical_pb_graph_node) {
    VTR_LOGF_ERROR(__FILE__, __LINE__,
                   "Invalid physical_pb_graph_node\n"); 
    exit(1);
  }
  t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; 
  t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type);
  if (false == is_primitive_pb_type(physical_pb_type)) { 
    for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) {
      rec_print_spice_logical_tile(netlist_manager,
                                   module_manager, device_annotation,
                                   subckt_dir, 
                                   &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]),
                                   verbose);
    }
  }
  if (true == is_primitive_pb_type(physical_pb_type)) { 
    print_spice_primitive_block(netlist_manager,
                                module_manager,
                                subckt_dir,
                                physical_pb_graph_node, 
                                verbose);
    return;
  }
  std::string spice_fname(subckt_dir 
                          + generate_logical_tile_netlist_name(std::string(), physical_pb_graph_node, std::string(SPICE_NETLIST_FILE_POSTFIX))
                           );
  VTR_LOG("Writing SPICE netlist '%s' for pb_type '%s' ...",
          spice_fname.c_str(), physical_pb_type->name);
  VTR_LOGV(verbose, "\n");
  std::fstream fp;
  fp.open(spice_fname, std::fstream::out | std::fstream::trunc);
  check_file_stream(spice_fname.c_str(), fp);
  print_spice_file_header(fp, std::string("SPICE subckts for pb_type: " + std::string(physical_pb_type->name))); 
  std::string pb_module_name = generate_physical_block_module_name(physical_pb_type);
  ModuleId pb_module = module_manager.find_module(pb_module_name);
  VTR_ASSERT(true == module_manager.valid_module_id(pb_module));
  VTR_LOGV(verbose,
          "Writing SPICE codes of pb_type '%s'...",
           module_manager.module_name(pb_module).c_str());
  print_spice_comment(fp, std::string("BEGIN Physical programmable logic block SPICE subckt: " + std::string(physical_pb_type->name)));
  write_spice_subckt_to_file(fp, module_manager, pb_module);
  print_spice_comment(fp, std::string("END Physical programmable logic block SPICE subckt: " + std::string(physical_pb_type->name)));
  fp.close();
  NetlistId nlist_id = netlist_manager.add_netlist(spice_fname);
  VTR_ASSERT(NetlistId::INVALID() != nlist_id);
  netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST);
  VTR_LOGV(verbose, "Done\n");
}
static void rec_print_spice_logical_tile ( NetlistManager & netlist_manager , const ModuleManager & module_manager , const VprDeviceAnnotation & device_annotation , const std :: string & subckt_dir , t_pb_graph_node * physical_pb_graph_node , const bool & verbose ) { if ( nullptr == physical_pb_graph_node ) { VTR_LOGF_ERROR ( __FILE__ , __LINE__ , " \n " ) ; exit ( 1 ) ; } t_pb_type * physical_pb_type = physical_pb_graph_node -> pb_type ; t_mode * physical_mode = device_annotation . physical_mode ( physical_pb_type ) ; if ( false == is_primitive_pb_type ( physical_pb_type ) ) { for ( int ipb = 0 ; ipb < physical_mode -> num_pb_type_children ; ++ ipb ) { rec_print_spice_logical_tile ( netlist_manager , module_manager , device_annotation , subckt_dir , & ( physical_pb_graph_node -> child_pb_graph_nodes [ physical_mode -> index ] [ ipb ] [ 0 ] ) , verbose ) ; } } if ( true == is_primitive_pb_type ( physical_pb_type ) ) { print_spice_primitive_block ( netlist_manager , module_manager , subckt_dir , physical_pb_graph_node , verbose ) ; return ; } std :: string spice_fname ( subckt_dir + generate_logical_tile_netlist_name ( std :: string ( ) , physical_pb_graph_node , std :: string ( SPICE_NETLIST_FILE_POSTFIX ) ) ) ; VTR_LOG ( " " , spice_fname . c_str ( ) , physical_pb_type -> name ) ; VTR_LOGV ( verbose , " \n " ) ; std :: fstream fp ; fp . open ( spice_fname , std :: fstream :: out | std :: fstream :: trunc ) ; check_file_stream ( spice_fname . c_str ( ) , fp ) ; print_spice_file_header ( fp , std :: string ( " " + std :: string ( physical_pb_type -> name ) ) ) ; std :: string pb_module_name = generate_physical_block_module_name ( physical_pb_type ) ; ModuleId pb_module = module_manager . find_module ( pb_module_name ) ; VTR_ASSERT ( true == module_manager . valid_module_id ( pb_module ) ) ; VTR_LOGV ( verbose , " " , module_manager . module_name ( pb_module ) . c_str ( ) ) ; print_spice_comment ( fp , std :: string ( " " + std :: string ( physical_pb_type -> name ) ) ) ; write_spice_subckt_to_file ( fp , module_manager , pb_module ) ; print_spice_comment ( fp , std :: string ( " " + std :: string ( physical_pb_type -> name ) ) ) ; fp . close ( ) ; NetlistId nlist_id = netlist_manager . add_netlist ( spice_fname ) ; VTR_ASSERT ( NetlistId :: INVALID ( ) != nlist_id ) ; netlist_manager . set_netlist_type ( nlist_id , NetlistManager :: LOGIC_BLOCK_NETLIST ) ; VTR_LOGV ( verbose , " \n " ) ; }
Print SPICE subckts of physical blocks inside a grid (CLB, I/O.
Print SPICE subckts of physical blocks inside a grid ( CLB I / O .
/* Check cur_pb_graph_node*/ /* Get the pb_type definition related to the node */ /* Find the mode that physical implementation of a pb_type */ /* For non-leaf node in the pb_type graph: 
   * Recursively Depth-First Generate all the child pb_type at the level 
   */ /* Go recursive to visit the children */ /* For leaf node, a primitive SPICE subckt will be generated.
   * Note that the primitive may be mapped to a standard cell, we force to use 
   * explict port mapping. This aims to avoid any port sequence issues!!!
   */ /* Finish for primitive node, return */ /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ /* Create the file stream */ /* Generate the name of the SPICE subckt for this pb_type */ /* Register the SPICE subckt in module manager */ /* Comment lines */ /* Write the spice module */ /* Close file handler */ /* Add fname to the netlist name list */