openfpga/src/fpga_spice/spice_memory.cpp
/*********************************************************************
 * Generate Verilog modules for 
 * the memories that are affiliated to multiplexers and other programmable
 * circuit models, such as IOPADs, LUTs, etc.
 *
 * We keep the memory modules separated from the multiplexers and other 
 * programmable circuit models, for the sake of supporting
 * various configuration schemes.
 * By following such organiztion, the Verilog modules of the circuit models
 * implements the functionality (circuit logic) only, while the memory Verilog
 * modules implements the memory circuits as well as configuration protocols.
 * For example, the local decoders of multiplexers are implemented in the
 * memory modules. 
 * Take another example, the memory circuit can implement the scan-chain or 
 * memory-bank organization for the memories.
 ********************************************************************/
Generate Verilog modules for
the memories that are affiliated to multiplexers and other programmable
circuit models, such as IOPADs, LUTs, etc.

We keep the memory modules separated from the multiplexers and other
programmable circuit models, for the sake of supporting
various configuration schemes.
By following such organiztion, the Verilog modules of the circuit models
implements the functionality (circuit logic) only, while the memory Verilog
modules implements the memory circuits as well as configuration protocols.
For example, the local decoders of multiplexers are implemented in the
memory modules.
Take another example, the memory circuit can implement the scan-chain or
memory-bank organization for the memories.
Generate Verilog modules for the memories that are affiliated to multiplexers and other programmable circuit models such as IOPADs LUTs etc . We keep the memory modules separated from the multiplexers and other programmable circuit models for the sake of supporting various configuration schemes . By following such organiztion the Verilog modules of the circuit models implements the functionality ( circuit logic ) only while the memory Verilog modules implements the memory circuits as well as configuration protocols . For example the local decoders of multiplexers are implemented in the memory modules . Take another example the memory circuit can implement the scan - chain or memory - bank organization for the memories .
int print_spice_submodule_memories(NetlistManager& netlist_manager,
                                   const ModuleManager& module_manager,
                                   const MuxLibrary& mux_lib,
                                   const CircuitLibrary& circuit_lib,
                                   const std::string& submodule_dir) {
  int status = CMD_EXEC_SUCCESS;
  std::string spice_fname(submodule_dir + std::string(MEMORIES_SPICE_FILE_NAME));
  std::fstream fp;
  fp.open(spice_fname, std::fstream::out | std::fstream::trunc);
  check_file_stream(spice_fname.c_str(), fp);
  VTR_LOG("Writing SPICE netlist for memories '%s' ...",
          spice_fname.c_str()); 
  print_spice_file_header(fp, "Memories used in FPGA"); 
  for (auto mux : mux_lib.muxes()) {
    const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
    CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); 
    if (CIRCUIT_MODEL_MUX != circuit_lib.model_type(mux_model)) {
      continue;
    }
    print_spice_mux_memory_module(module_manager, circuit_lib, fp, mux_model, mux_graph);
  }
  for (const auto& model : circuit_lib.models()) {
    if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) {
      continue;
    }
    std::vector<CircuitPortId> sram_ports = circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true);
    if (0 == sram_ports.size()) {
      continue;
    }
    size_t num_mems = 0; 
    for (const auto& port : sram_ports) {
      num_mems += circuit_lib.port_size(port);
    }
    std::vector<CircuitModelId> sram_models;
    for (const auto& port : sram_ports) {
      CircuitModelId sram_model = circuit_lib.port_tri_state_model(port);
      VTR_ASSERT(CircuitModelId::INVALID() != sram_model);
      if (sram_models.end() != std::find(sram_models.begin(), sram_models.end(), sram_model)) {
        continue;
      }
      sram_models.push_back(sram_model);
    }
    VTR_ASSERT( 1 == sram_models.size() );
    std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(SPICE_MEM_POSTFIX));
    ModuleId mem_module = module_manager.find_module(module_name);
    VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
    write_spice_subckt_to_file(fp, module_manager, mem_module);
    fp << std::endl;
  }
  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::SUBMODULE_NETLIST);
  VTR_LOG("Done\n");
  return status;
}
int print_spice_submodule_memories ( NetlistManager & netlist_manager , const ModuleManager & module_manager , const MuxLibrary & mux_lib , const CircuitLibrary & circuit_lib , const std :: string & submodule_dir ) { int status = CMD_EXEC_SUCCESS ; std :: string spice_fname ( submodule_dir + std :: string ( MEMORIES_SPICE_FILE_NAME ) ) ; std :: fstream fp ; fp . open ( spice_fname , std :: fstream :: out | std :: fstream :: trunc ) ; check_file_stream ( spice_fname . c_str ( ) , fp ) ; VTR_LOG ( " " , spice_fname . c_str ( ) ) ; print_spice_file_header ( fp , " " ) ; for ( auto mux : mux_lib . muxes ( ) ) { const MuxGraph & mux_graph = mux_lib . mux_graph ( mux ) ; CircuitModelId mux_model = mux_lib . mux_circuit_model ( mux ) ; if ( CIRCUIT_MODEL_MUX != circuit_lib . model_type ( mux_model ) ) { continue ; } print_spice_mux_memory_module ( module_manager , circuit_lib , fp , mux_model , mux_graph ) ; } for ( const auto & model : circuit_lib . models ( ) ) { if ( CIRCUIT_MODEL_MUX == circuit_lib . model_type ( model ) ) { continue ; } std :: vector < CircuitPortId > sram_ports = circuit_lib . model_ports_by_type ( model , CIRCUIT_MODEL_PORT_SRAM , true ) ; if ( 0 == sram_ports . size ( ) ) { continue ; } size_t num_mems = 0 ; for ( const auto & port : sram_ports ) { num_mems += circuit_lib . port_size ( port ) ; } std :: vector < CircuitModelId > sram_models ; for ( const auto & port : sram_ports ) { CircuitModelId sram_model = circuit_lib . port_tri_state_model ( port ) ; VTR_ASSERT ( CircuitModelId :: INVALID ( ) != sram_model ) ; if ( sram_models . end ( ) != std :: find ( sram_models . begin ( ) , sram_models . end ( ) , sram_model ) ) { continue ; } sram_models . push_back ( sram_model ) ; } VTR_ASSERT ( 1 == sram_models . size ( ) ) ; std :: string module_name = generate_memory_module_name ( circuit_lib , model , sram_models [ 0 ] , std :: string ( SPICE_MEM_POSTFIX ) ) ; ModuleId mem_module = module_manager . find_module ( module_name ) ; VTR_ASSERT ( true == module_manager . valid_module_id ( mem_module ) ) ; write_spice_subckt_to_file ( fp , module_manager , mem_module ) ; fp << std :: endl ; } 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 :: SUBMODULE_NETLIST ) ; VTR_LOG ( " \n " ) ; return status ; }
Generate Verilog modules for
 the memories that are affiliated to multiplexers and other programmable
 circuit models, such as IOPADs, LUTs, etc.
Generate Verilog modules for the memories that are affiliated to multiplexers and other programmable circuit models such as IOPADs LUTs etc .
/* Plug in with the mux subckt */ /* Create the file stream */ /* Print out debugging information for if the file is not opened/created properly */ /* Create the memory circuits for the multiplexer */ /* Bypass the non-MUX circuit models (i.e., LUTs). 
     * They should be handled in a different way 
     * Memory circuits of LUT includes both regular and mode-select ports
     */ /* Create a Verilog module for the memories used by the multiplexer */ /* Create the memory circuits for non-MUX circuit models.
   * In this case, the memory modules are designed to interface
   * the mode-select ports 
   */ /* Bypass MUXes, they have already been considered */ /* Bypass those modules without any SRAM ports */ /* Find the name of memory module */ /* Get the total number of SRAMs */ /* Get the circuit model for the memory circuit used by the multiplexer */ /* Found in the vector of sram_models, do not update and go to the next */ /* sram_model not found in the vector, update the sram_models */ /* Should have only 1 SRAM model */ /* Create the module name for the memory block */ /* Write the module content in Verilog format */ /* Add an empty line as a splitter */ /* Close the file stream */ /* Add fname to the netlist name list */