openfpga/src/repack/build_physical_truth_table.cpp
/***************************************************************************************
 * This function will iterate over all the inputs and outputs of the LUT pb 
 * and find truth tables that are mapped to each output pins
 * Note that a physical LUT may have multiple truth tables to be considered
 * as they may be fracturable
 ***************************************************************************************/
This function will iterate over all the inputs and outputs of the LUT pb
and find truth tables that are mapped to each output pins
Note that a physical LUT may have multiple truth tables to be considered
as they may be fracturable
This function will iterate over all the inputs and outputs of the LUT pb and find truth tables that are mapped to each output pins Note that a physical LUT may have multiple truth tables to be considered as they may be fracturable
static 
void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
                                        const PhysicalPbId& lut_pb_id,
                                        const AtomContext& atom_ctx,
                                        const VprDeviceAnnotation& device_annotation,
                                        const CircuitLibrary& circuit_lib,
                                        const bool& verbose) {
  const t_pb_graph_node* pb_graph_node = physical_pb.pb_graph_node(lut_pb_id);
  CircuitModelId lut_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(lut_pb_id)->pb_type);
  VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model));
  std::vector<AtomNetId> input_nets;
  for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) {
    for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) {
      CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port);
      if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) {
        continue;
      }
      input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[iport][ipin]))); 
    }
  }
  for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) {
    for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) {
      const t_pb_graph_pin* output_pin = &(pb_graph_node->output_pins[iport][ipin]);
      CircuitPortId circuit_port = device_annotation.pb_circuit_port(output_pin->port);
      if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) {
        continue;
      }
      AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin); 
      if (AtomNetId::INVALID() == output_net) {
        continue;
      }
      AtomNetlist::TruthTable adapt_tt;
      if (true == physical_pb.is_wire_lut_output(lut_pb_id, output_pin)) {
        VTR_ASSERT(true == is_wired_lut(input_nets, output_net));
        adapt_tt = build_wired_lut_truth_table(input_nets.size(), std::find(input_nets.begin(), input_nets.end(), output_net) - input_nets.begin()); 
      } else {
        const AtomBlockId& atom_blk = atom_ctx.nlist.net_driver_block(output_net); 
        VTR_ASSERT(true == atom_ctx.nlist.valid_block_id(atom_blk));
        const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk);
        std::vector<int> rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, device_annotation, circuit_lib, pb_graph_node);
        adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map);
        VTR_LOGV(verbose, "Driver atom block: '%ld'\n", size_t(atom_blk));
        VTR_LOGV(verbose, "Pb atom blocks:");
        for (const AtomBlockId& pb_atom_blk : physical_pb.atom_blocks(lut_pb_id)) {
          VTR_LOGV(verbose, "'%ld', ", size_t(pb_atom_blk));
        }
        VTR_LOGV(verbose, "\n");
      }
      CircuitPortId lut_model_output_port = device_annotation.pb_circuit_port(output_pin->port);
      size_t lut_frac_level = circuit_lib.port_lut_frac_level(lut_model_output_port);
      if (size_t(-1) == lut_frac_level) {
        lut_frac_level = input_nets.size();
      }
      size_t lut_output_mask = circuit_lib.port_lut_output_mask(lut_model_output_port)[output_pin->pin_number];
      const AtomNetlist::TruthTable& frac_lut_tt = adapt_truth_table_for_frac_lut(lut_frac_level, lut_output_mask, adapt_tt);
      physical_pb.set_truth_table(lut_pb_id, output_pin, frac_lut_tt);
      VTR_LOGV(verbose, "Input nets: ");
      for (const AtomNetId& net : input_nets) {
        if (AtomNetId::INVALID() == net) {
          VTR_LOGV(verbose, "unconn  ");
        } else {
          VTR_ASSERT(AtomNetId::INVALID() != net);
          VTR_LOGV(verbose, "%s  ", atom_ctx.nlist.net_name(net).c_str());
        }
      }
      VTR_LOGV(verbose, "\n");
      VTR_ASSERT(AtomNetId::INVALID() != output_net);
      VTR_LOGV(verbose, "Output net: %s\n", atom_ctx.nlist.net_name(output_net).c_str());
      VTR_LOGV(verbose,
               "Truth table before adaption to fracturable LUT'\n");
      for (const std::string& tt_line : truth_table_to_string(adapt_tt)) {
        VTR_LOGV(verbose, "\t%s\n", tt_line.c_str());
      }
      VTR_LOGV(verbose,
               "Add following truth table to pb_graph_pin '%s[%d]'\n", 
               output_pin->port->name, output_pin->pin_number);
      for (const std::string& tt_line : truth_table_to_string(frac_lut_tt)) {
        VTR_LOGV(verbose, "\t%s\n", tt_line.c_str());
      }
      VTR_LOGV(verbose, "\n");
    }
  }
}
static void build_physical_pb_lut_truth_tables ( PhysicalPb & physical_pb , const PhysicalPbId & lut_pb_id , const AtomContext & atom_ctx , const VprDeviceAnnotation & device_annotation , const CircuitLibrary & circuit_lib , const bool & verbose ) { const t_pb_graph_node * pb_graph_node = physical_pb . pb_graph_node ( lut_pb_id ) ; CircuitModelId lut_model = device_annotation . pb_type_circuit_model ( physical_pb . pb_graph_node ( lut_pb_id ) -> pb_type ) ; VTR_ASSERT ( CIRCUIT_MODEL_LUT == circuit_lib . model_type ( lut_model ) ) ; std :: vector < AtomNetId > input_nets ; for ( int iport = 0 ; iport < pb_graph_node -> num_input_ports ; ++ iport ) { for ( int ipin = 0 ; ipin < pb_graph_node -> num_input_pins [ iport ] ; ++ ipin ) { CircuitPortId circuit_port = device_annotation . pb_circuit_port ( pb_graph_node -> input_pins [ iport ] [ ipin ] . port ) ; if ( true == circuit_lib . port_is_harden_lut_port ( circuit_port ) ) { continue ; } input_nets . push_back ( physical_pb . pb_graph_pin_atom_net ( lut_pb_id , & ( pb_graph_node -> input_pins [ iport ] [ ipin ] ) ) ) ; } } for ( int iport = 0 ; iport < pb_graph_node -> num_output_ports ; ++ iport ) { for ( int ipin = 0 ; ipin < pb_graph_node -> num_output_pins [ iport ] ; ++ ipin ) { const t_pb_graph_pin * output_pin = & ( pb_graph_node -> output_pins [ iport ] [ ipin ] ) ; CircuitPortId circuit_port = device_annotation . pb_circuit_port ( output_pin -> port ) ; if ( true == circuit_lib . port_is_harden_lut_port ( circuit_port ) ) { continue ; } AtomNetId output_net = physical_pb . pb_graph_pin_atom_net ( lut_pb_id , output_pin ) ; if ( AtomNetId :: INVALID ( ) == output_net ) { continue ; } AtomNetlist :: TruthTable adapt_tt ; if ( true == physical_pb . is_wire_lut_output ( lut_pb_id , output_pin ) ) { VTR_ASSERT ( true == is_wired_lut ( input_nets , output_net ) ) ; adapt_tt = build_wired_lut_truth_table ( input_nets . size ( ) , std :: find ( input_nets . begin ( ) , input_nets . end ( ) , output_net ) - input_nets . begin ( ) ) ; } else { const AtomBlockId & atom_blk = atom_ctx . nlist . net_driver_block ( output_net ) ; VTR_ASSERT ( true == atom_ctx . nlist . valid_block_id ( atom_blk ) ) ; const AtomNetlist :: TruthTable & orig_tt = atom_ctx . nlist . block_truth_table ( atom_blk ) ; std :: vector < int > rotated_pin_map = generate_lut_rotated_input_pin_map ( input_nets , atom_ctx , atom_blk , device_annotation , circuit_lib , pb_graph_node ) ; adapt_tt = lut_truth_table_adaption ( orig_tt , rotated_pin_map ) ; VTR_LOGV ( verbose , " \n " , size_t ( atom_blk ) ) ; VTR_LOGV ( verbose , " " ) ; for ( const AtomBlockId & pb_atom_blk : physical_pb . atom_blocks ( lut_pb_id ) ) { VTR_LOGV ( verbose , " " , size_t ( pb_atom_blk ) ) ; } VTR_LOGV ( verbose , " \n " ) ; } CircuitPortId lut_model_output_port = device_annotation . pb_circuit_port ( output_pin -> port ) ; size_t lut_frac_level = circuit_lib . port_lut_frac_level ( lut_model_output_port ) ; if ( size_t ( -1 ) == lut_frac_level ) { lut_frac_level = input_nets . size ( ) ; } size_t lut_output_mask = circuit_lib . port_lut_output_mask ( lut_model_output_port ) [ output_pin -> pin_number ] ; const AtomNetlist :: TruthTable & frac_lut_tt = adapt_truth_table_for_frac_lut ( lut_frac_level , lut_output_mask , adapt_tt ) ; physical_pb . set_truth_table ( lut_pb_id , output_pin , frac_lut_tt ) ; VTR_LOGV ( verbose , " " ) ; for ( const AtomNetId & net : input_nets ) { if ( AtomNetId :: INVALID ( ) == net ) { VTR_LOGV ( verbose , " " ) ; } else { VTR_ASSERT ( AtomNetId :: INVALID ( ) != net ) ; VTR_LOGV ( verbose , " " , atom_ctx . nlist . net_name ( net ) . c_str ( ) ) ; } } VTR_LOGV ( verbose , " \n " ) ; VTR_ASSERT ( AtomNetId :: INVALID ( ) != output_net ) ; VTR_LOGV ( verbose , " \n " , atom_ctx . nlist . net_name ( output_net ) . c_str ( ) ) ; VTR_LOGV ( verbose , " \n " ) ; for ( const std :: string & tt_line : truth_table_to_string ( adapt_tt ) ) { VTR_LOGV ( verbose , " \t \n " , tt_line . c_str ( ) ) ; } VTR_LOGV ( verbose , " \n " , output_pin -> port -> name , output_pin -> pin_number ) ; for ( const std :: string & tt_line : truth_table_to_string ( frac_lut_tt ) ) { VTR_LOGV ( verbose , " \t \n " , tt_line . c_str ( ) ) ; } VTR_LOGV ( verbose , " \n " ) ; } } }
This function will iterate over all the inputs and outputs of the LUT pb
 and find truth tables that are mapped to each output pins
 Note that a physical LUT may have multiple truth tables to be considered
 as they may be fracturable
This function will iterate over all the inputs and outputs of the LUT pb and find truth tables that are mapped to each output pins Note that a physical LUT may have multiple truth tables to be considered as they may be fracturable
/* Find all the nets mapped to each inputs */ /* Skip the input pin that do not drive by LUT MUXes */ /* Find all the nets mapped to each outputs */ /* Skip the output ports that are not driven by LUT MUXes */ /* Bypass unmapped pins */ /* Check if this is a LUT used as wiring */ /* Double check: ensure that the output nets appear in the input net !!! */ /* Find the truth table from atom block which drives the atom net */ /* Adapt the truth table for fracturable lut implementation and add to physical pb */ /* Print debug information */