openfpga/src/fabric/build_mux_modules.cpp
/********************************************************************
 * Generate the pass-transistor/transmission-gate -based internal logic 
 * (multiplexing structure) for a multiplexer or LUT in Verilog codes 
 * This function will : 
 * 1. build a multiplexing structure by instanciating the branch circuits
 *    generated before
 * 2. add intermediate buffers between multiplexing stages if specified.
 *******************************************************************/
Generate the pass-transistor/transmission-gate -based internal logic
(multiplexing structure) for a multiplexer or LUT in Verilog codes
This function will :
1. build a multiplexing structure by instanciating the branch circuits
generated before
2. add intermediate buffers between multiplexing stages if specified.
Generate the pass - transistor / transmission - gate - based internal logic ( multiplexing structure ) for a multiplexer or LUT in Verilog codes This function will : 1 . build a multiplexing structure by instanciating the branch circuits generated before 2 . add intermediate buffers between multiplexing stages if specified .
static 
void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_manager,
                                                        const CircuitLibrary& circuit_lib, 
                                                        const ModuleId& mux_module, 
                                                        const CircuitModelId& circuit_model, 
                                                        const vtr::vector<MuxInputId, ModuleNetId>& mux_module_input_nets, 
                                                        const vtr::vector<MuxOutputId, ModuleNetId>& mux_module_output_nets, 
                                                        const vtr::vector<MuxMemId, ModuleNetId>& mux_module_mem_nets, 
                                                        const vtr::vector<MuxMemId, ModuleNetId>& mux_module_mem_inv_nets, 
                                                        const MuxGraph& mux_graph) {
  std::vector<CircuitPortId> mux_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, circuit_model);
  VTR_ASSERT(1 == mux_regular_sram_ports.size());
  std::vector<std::vector<ModuleNetId>> module_nets_by_level;
  module_nets_by_level.resize(mux_graph.num_node_levels());
  for (size_t level = 0; level < mux_graph.num_node_levels(); ++level) {
    module_nets_by_level[level].resize(mux_graph.num_nodes_at_level(level));
  }
  std::vector<bool> inter_buffer_location_map = build_mux_intermediate_buffer_location_map(circuit_lib, circuit_model, mux_graph.num_node_levels());
  for (const auto& node : mux_graph.non_input_nodes()) {
    size_t branch_size = mux_graph.node_in_edges(node).size();
    std::vector<MuxMemId> mems; 
    for (const auto& edge : mux_graph.node_in_edges(node)) {
      MuxMemId mem = mux_graph.find_edge_mem(edge);
      if (mems.end() == std::find(mems.begin(), mems.end(), mem)) {
        mems.push_back(mem);
      }
    }
    std::string branch_module_name= generate_mux_branch_subckt_name(circuit_lib, circuit_model, branch_size, mems.size(), MUX_BASIS_MODULE_POSTFIX);
    ModuleId branch_module_id = module_manager.find_module(branch_module_name);
    VTR_ASSERT(ModuleId::INVALID() != branch_module_id);
    size_t branch_instance_id = module_manager.num_instance(mux_module, branch_module_id);
    module_manager.add_child_module(mux_module, branch_module_id);
    size_t output_node_level = mux_graph.node_level(node);
    size_t output_node_index_at_level = mux_graph.node_index_at_level(node);
    std::string branch_instance_name = generate_mux_branch_instance_name(output_node_level, output_node_index_at_level, false);
    module_manager.set_child_instance_name(mux_module, branch_module_id, branch_instance_id, branch_instance_name);
    ModulePortId branch_module_output_port_id = module_manager.find_module_port(branch_module_id, std::string("out")); 
    BasicPort branch_module_output_port = module_manager.module_port(branch_module_id, branch_module_output_port_id);
    ModuleNetId branch_net; 
    if (true == mux_graph.is_node_output(node)) {
      MuxOutputId output_id = mux_graph.output_id(node);
      branch_net = mux_module_output_nets[output_id];
    } else {
      VTR_ASSERT(false == mux_graph.is_node_output(node));
      branch_net = module_manager.create_module_net(mux_module);
    }
    module_manager.add_module_net_source(mux_module, branch_net, branch_module_id, branch_instance_id, branch_module_output_port_id, branch_module_output_port.get_lsb());
    module_nets_by_level[output_node_level][output_node_index_at_level] = branch_net;
    ModulePortId branch_module_mem_port_id = module_manager.find_module_port(branch_module_id, std::string("mem")); 
    BasicPort branch_module_mem_port = module_manager.module_port(branch_module_id, branch_module_mem_port_id);
    ModulePortId branch_module_mem_inv_port_id = module_manager.find_module_port(branch_module_id, std::string("mem_inv")); 
    BasicPort branch_module_mem_inv_port = module_manager.module_port(branch_module_id, branch_module_mem_inv_port_id);
    for (size_t mem_id = 0; mem_id < mems.size(); ++mem_id) {
      module_manager.add_module_net_sink(mux_module, mux_module_mem_nets[mems[mem_id]], branch_module_id, branch_instance_id, branch_module_mem_port_id, branch_module_mem_port.pins()[mem_id]);
      module_manager.add_module_net_sink(mux_module, mux_module_mem_inv_nets[mems[mem_id]], branch_module_id, branch_instance_id, branch_module_mem_inv_port_id, branch_module_mem_inv_port.pins()[mem_id]);
    }
    ModulePortId branch_module_input_port_id = module_manager.find_module_port(branch_module_id, std::string("in")); 
    BasicPort branch_module_input_port = module_manager.module_port(branch_module_id, branch_module_input_port_id);
    std::vector<MuxNodeId> input_nodes; 
    for (const auto& edge : mux_graph.node_in_edges(node)) {
      for (const auto& src_node : mux_graph.edge_src_nodes(edge)) {
        input_nodes.push_back(src_node);
      }
    }
    VTR_ASSERT(input_nodes.size() == branch_size);
    for (size_t node_id = 0; node_id < input_nodes.size(); ++node_id) {
      size_t input_node_level = mux_graph.node_level(input_nodes[node_id]);
      size_t input_node_index_at_level = mux_graph.node_index_at_level(input_nodes[node_id]);
      if (true == mux_graph.is_node_input(input_nodes[node_id])) {
        MuxInputId input_id = mux_graph.input_id(input_nodes[node_id]);
        module_manager.add_module_net_sink(mux_module, mux_module_input_nets[input_id], branch_module_id, branch_instance_id, branch_module_input_port_id, branch_module_input_port.pins()[node_id]);
      } else {
        VTR_ASSERT (false == mux_graph.is_node_input(input_nodes[node_id]));
        module_manager.add_module_net_sink(mux_module, module_nets_by_level[input_node_level][input_node_index_at_level], branch_module_id, branch_instance_id, branch_module_input_port_id, branch_module_input_port.pins()[node_id]);
      }
    }
    if (false == inter_buffer_location_map[output_node_level]) { 
      continue;
    }
    if (true == mux_graph.is_node_output(node)) {
      continue; 
    }
    CircuitModelId buffer_model = circuit_lib.lut_intermediate_buffer_model(circuit_model);
    VTR_ASSERT(CircuitModelId::INVALID() != buffer_model);
    ModuleNetId buffer_net = add_inverter_buffer_child_module_and_nets(module_manager, mux_module, circuit_lib, buffer_model, branch_net); 
    module_nets_by_level[output_node_level][output_node_index_at_level] = buffer_net;
  }
}
static void build_cmos_mux_module_tgate_multiplexing_structure ( ModuleManager & module_manager , const CircuitLibrary & circuit_lib , const ModuleId & mux_module , const CircuitModelId & circuit_model , const vtr :: vector < MuxInputId , ModuleNetId > & mux_module_input_nets , const vtr :: vector < MuxOutputId , ModuleNetId > & mux_module_output_nets , const vtr :: vector < MuxMemId , ModuleNetId > & mux_module_mem_nets , const vtr :: vector < MuxMemId , ModuleNetId > & mux_module_mem_inv_nets , const MuxGraph & mux_graph ) { std :: vector < CircuitPortId > mux_regular_sram_ports = find_circuit_regular_sram_ports ( circuit_lib , circuit_model ) ; VTR_ASSERT ( 1 == mux_regular_sram_ports . size ( ) ) ; std :: vector < std :: vector < ModuleNetId > > module_nets_by_level ; module_nets_by_level . resize ( mux_graph . num_node_levels ( ) ) ; for ( size_t level = 0 ; level < mux_graph . num_node_levels ( ) ; ++ level ) { module_nets_by_level [ level ] . resize ( mux_graph . num_nodes_at_level ( level ) ) ; } std :: vector < bool > inter_buffer_location_map = build_mux_intermediate_buffer_location_map ( circuit_lib , circuit_model , mux_graph . num_node_levels ( ) ) ; for ( const auto & node : mux_graph . non_input_nodes ( ) ) { size_t branch_size = mux_graph . node_in_edges ( node ) . size ( ) ; std :: vector < MuxMemId > mems ; for ( const auto & edge : mux_graph . node_in_edges ( node ) ) { MuxMemId mem = mux_graph . find_edge_mem ( edge ) ; if ( mems . end ( ) == std :: find ( mems . begin ( ) , mems . end ( ) , mem ) ) { mems . push_back ( mem ) ; } } std :: string branch_module_name = generate_mux_branch_subckt_name ( circuit_lib , circuit_model , branch_size , mems . size ( ) , MUX_BASIS_MODULE_POSTFIX ) ; ModuleId branch_module_id = module_manager . find_module ( branch_module_name ) ; VTR_ASSERT ( ModuleId :: INVALID ( ) != branch_module_id ) ; size_t branch_instance_id = module_manager . num_instance ( mux_module , branch_module_id ) ; module_manager . add_child_module ( mux_module , branch_module_id ) ; size_t output_node_level = mux_graph . node_level ( node ) ; size_t output_node_index_at_level = mux_graph . node_index_at_level ( node ) ; std :: string branch_instance_name = generate_mux_branch_instance_name ( output_node_level , output_node_index_at_level , false ) ; module_manager . set_child_instance_name ( mux_module , branch_module_id , branch_instance_id , branch_instance_name ) ; ModulePortId branch_module_output_port_id = module_manager . find_module_port ( branch_module_id , std :: string ( " " ) ) ; BasicPort branch_module_output_port = module_manager . module_port ( branch_module_id , branch_module_output_port_id ) ; ModuleNetId branch_net ; if ( true == mux_graph . is_node_output ( node ) ) { MuxOutputId output_id = mux_graph . output_id ( node ) ; branch_net = mux_module_output_nets [ output_id ] ; } else { VTR_ASSERT ( false == mux_graph . is_node_output ( node ) ) ; branch_net = module_manager . create_module_net ( mux_module ) ; } module_manager . add_module_net_source ( mux_module , branch_net , branch_module_id , branch_instance_id , branch_module_output_port_id , branch_module_output_port . get_lsb ( ) ) ; module_nets_by_level [ output_node_level ] [ output_node_index_at_level ] = branch_net ; ModulePortId branch_module_mem_port_id = module_manager . find_module_port ( branch_module_id , std :: string ( " " ) ) ; BasicPort branch_module_mem_port = module_manager . module_port ( branch_module_id , branch_module_mem_port_id ) ; ModulePortId branch_module_mem_inv_port_id = module_manager . find_module_port ( branch_module_id , std :: string ( " " ) ) ; BasicPort branch_module_mem_inv_port = module_manager . module_port ( branch_module_id , branch_module_mem_inv_port_id ) ; for ( size_t mem_id = 0 ; mem_id < mems . size ( ) ; ++ mem_id ) { module_manager . add_module_net_sink ( mux_module , mux_module_mem_nets [ mems [ mem_id ] ] , branch_module_id , branch_instance_id , branch_module_mem_port_id , branch_module_mem_port . pins ( ) [ mem_id ] ) ; module_manager . add_module_net_sink ( mux_module , mux_module_mem_inv_nets [ mems [ mem_id ] ] , branch_module_id , branch_instance_id , branch_module_mem_inv_port_id , branch_module_mem_inv_port . pins ( ) [ mem_id ] ) ; } ModulePortId branch_module_input_port_id = module_manager . find_module_port ( branch_module_id , std :: string ( " " ) ) ; BasicPort branch_module_input_port = module_manager . module_port ( branch_module_id , branch_module_input_port_id ) ; std :: vector < MuxNodeId > input_nodes ; for ( const auto & edge : mux_graph . node_in_edges ( node ) ) { for ( const auto & src_node : mux_graph . edge_src_nodes ( edge ) ) { input_nodes . push_back ( src_node ) ; } } VTR_ASSERT ( input_nodes . size ( ) == branch_size ) ; for ( size_t node_id = 0 ; node_id < input_nodes . size ( ) ; ++ node_id ) { size_t input_node_level = mux_graph . node_level ( input_nodes [ node_id ] ) ; size_t input_node_index_at_level = mux_graph . node_index_at_level ( input_nodes [ node_id ] ) ; if ( true == mux_graph . is_node_input ( input_nodes [ node_id ] ) ) { MuxInputId input_id = mux_graph . input_id ( input_nodes [ node_id ] ) ; module_manager . add_module_net_sink ( mux_module , mux_module_input_nets [ input_id ] , branch_module_id , branch_instance_id , branch_module_input_port_id , branch_module_input_port . pins ( ) [ node_id ] ) ; } else { VTR_ASSERT ( false == mux_graph . is_node_input ( input_nodes [ node_id ] ) ) ; module_manager . add_module_net_sink ( mux_module , module_nets_by_level [ input_node_level ] [ input_node_index_at_level ] , branch_module_id , branch_instance_id , branch_module_input_port_id , branch_module_input_port . pins ( ) [ node_id ] ) ; } } if ( false == inter_buffer_location_map [ output_node_level ] ) { continue ; } if ( true == mux_graph . is_node_output ( node ) ) { continue ; } CircuitModelId buffer_model = circuit_lib . lut_intermediate_buffer_model ( circuit_model ) ; VTR_ASSERT ( CircuitModelId :: INVALID ( ) != buffer_model ) ; ModuleNetId buffer_net = add_inverter_buffer_child_module_and_nets ( module_manager , mux_module , circuit_lib , buffer_model , branch_net ) ; module_nets_by_level [ output_node_level ] [ output_node_index_at_level ] = buffer_net ; } }
Generate the pass-transistor/transmission-gate -based internal logic
 (multiplexing structure) for a multiplexer or LUT in Verilog codes
 This function will :
 1. build a multiplexing structure by instanciating the branch circuits
    generated before
 2. add intermediate buffers between multiplexing stages if specified.
Generate the pass - transistor / transmission - gate - based internal logic ( multiplexing structure ) for a multiplexer or LUT in Verilog codes This function will : 1 . build a multiplexing structure by instanciating the branch circuits generated before 2 . add intermediate buffers between multiplexing stages if specified .
/* Get the regular (non-mode-select) sram ports from the mux */ /* Cache Net ids for each level of the multiplexer */ /* Print the internal wires located at this level */ /* Build the location map of intermediate buffers */ /* Add all the branch modules and intermediate buffers */ /* Get the size of branch circuit 
     * Instanciate an branch circuit by the size (fan-in) of the node 
     */ /* Get the mems in the branch circuits */ /* Get the mem control the edge */ /* Add the mem if it is not in the list */ /* Instanciate the branch module which is a tgate-based module */ /* Get the moduleId for the submodule */ /* We must have one */ /* Find the instance id */ /* Add the module to mux_module */ /* Get the node level and index in the current level */ /* Set a name for the instance */ /* Get the output port id of branch module */ /* Add module nets to wire to next stage modules */ /* This is an output node, we should use existing output nets */ /* Record the module net id in the cache */ /* Wire the branch module memory ports to the nets of MUX memory ports */ /* Get mem/mem_inv ports of branch module */ /* Note that we do NOT care inverted edge-to-mem connection. 
     * It is handled in branch module generation!!!
     */ /* Connect mem/mem_inv to mem/mem_inv net one by one */ /* Wire the branch module inputs to the nets in previous stage */ /* Get the input port id of branch module */ /* Get the nodes which drive the root_node */ /* Get the nodes drive the edge */ /* Number of inputs should match the branch_input_size!!! */ /* build the link between input_node and branch circuit input_port[0] 
     */ /* Find the port info of each input node */ /* For inputs of mux, the net id is reserved */ /* Get node input id */ /* Identify if an intermediate buffer is needed */ /* Add an intermediate buffer to mux_module if needed */ /* Output node does not need buffer addition here, it is handled outside this function */ /* Now we need to add intermediate buffers by instanciating the modules */ /* We must have a valid model id */ /* Record the module net id in the cache */