openfpga/src/fpga_spice/spice_wire.cpp
/********************************************************************
 * Generate the SPICE subckt for a regular wire
 *
 * Schematic
 *
 *                                 Middle output (only for routing track wires)
 *                                      ^
 *                                      |
 *      +--------------------+    +---------------+     +--------------------+
 * in ->| Inverter or buffer |--->|   RC Network  |---->| Inverter or buffer |---> out
 *      |  Optional          |    |               |     | Optional           |
 *      +---------------------    +---------------+     +--------------------+
 *     
 *******************************************************************/
Generate the SPICE subckt for a regular wire
Schematic


Generate the SPICE subckt for a regular wire Schematic
int print_spice_wire_subckt(std::fstream& fp,
                            const ModuleManager& module_manager,
                            const ModuleId& module_id,
                            const CircuitLibrary& circuit_lib,
                            const CircuitModelId& circuit_model) {
 if (false == valid_file_stream(fp)) {
    return CMD_EXEC_FATAL_ERROR;
  }
  std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
  std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
  VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) );
  VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
  int status = CMD_EXEC_SUCCESS;
  print_spice_subckt_definition(fp, module_manager, module_id); 
  std::string input_port_name = circuit_lib.port_prefix(input_ports[0]);
  std::string output_port_name = circuit_lib.port_prefix(output_ports[0]);
  std::string middle_output_port_name;
  if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(circuit_model)) {
    middle_output_port_name = std::string("middle") + output_port_name;
  }
  std::string rc_ntwk_input_port_name = std::string("rc_network_node") + std::to_string(0);
  std::string rc_ntwk_output_port_name = std::string("rc_network_node") + std::to_string(circuit_lib.wire_num_level(circuit_model) - 1);
  std::string rc_ntwk_middle_output_port_name;
  if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(circuit_model)) {
    rc_ntwk_middle_output_port_name = std::string("middle") + rc_ntwk_output_port_name;
  }
  ModulePortId wire_module_input_port = module_manager.find_module_port(module_id, input_port_name);
  ModulePortId wire_module_output_port = module_manager.find_module_port(module_id, output_port_name);
  ModulePortId wire_module_middle_output_port = ModulePortId::INVALID();
  if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(circuit_model)) {
    wire_module_middle_output_port = module_manager.find_module_port(module_id, output_port_name);
  }
  if (circuit_lib.input_buffer_model(circuit_model)) {
    std::string instance_name = std::string("input_buffer");
    std::map<std::string, BasicPort> port2port_name_map;
    ModuleId buffer_module = module_manager.find_module(circuit_lib.model_name(circuit_lib.input_buffer_model(circuit_model)));
    VTR_ASSERT(true == module_manager.valid_module_id(buffer_module));
    ModulePortId module_input_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT);
    ModulePortId module_output_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT);
    VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_input_port_id).get_width());
    VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_output_port_id).get_width());
    port2port_name_map[module_manager.module_port(buffer_module, module_input_port_id).get_name()] = module_manager.module_port(module_id, wire_module_input_port);
    port2port_name_map[module_manager.module_port(buffer_module, module_output_port_id).get_name()] = BasicPort(rc_ntwk_input_port_name, 1);
    print_spice_subckt_instance(fp, 
                                module_manager, 
                                buffer_module,
                                instance_name,
                                port2port_name_map);
  } else {
    print_spice_short_connection(fp, circuit_lib.port_prefix(input_ports[0]), rc_ntwk_input_port_name); 
  }
  switch (circuit_lib.wire_type(circuit_model)) {
  case WIRE_MODEL_PI:
   status = print_spice_wire_pi_type_rc_modeling(fp,
                                                 rc_ntwk_input_port_name,
                                                 rc_ntwk_output_port_name,
                                                 rc_ntwk_middle_output_port_name,
                                                 circuit_lib.wire_r(circuit_model), 
                                                 circuit_lib.wire_c(circuit_model), 
                                                 circuit_lib.wire_num_level(circuit_model)); 
    break;
  case WIRE_MODEL_T: 
    status = print_spice_wire_t_type_rc_modeling(fp,
                                                 rc_ntwk_input_port_name,
                                                 rc_ntwk_output_port_name,
                                                 rc_ntwk_middle_output_port_name,
                                                 circuit_lib.wire_r(circuit_model), 
                                                 circuit_lib.wire_c(circuit_model), 
                                                 circuit_lib.wire_num_level(circuit_model)); 
    break;
  default:
    VTR_LOGF_ERROR(__FILE__, __LINE__,
                   "Unsupport wire model type for circuit model '%s.\n",
                   circuit_lib.model_name(circuit_model).c_str());
    return CMD_EXEC_FATAL_ERROR;
  } 
  if (circuit_lib.output_buffer_model(circuit_model)) {
    std::string instance_name = std::string("output_buffer");
    std::map<std::string, BasicPort> port2port_name_map;
    ModuleId buffer_module = module_manager.find_module(circuit_lib.model_name(circuit_lib.output_buffer_model(circuit_model)));
    VTR_ASSERT(true == module_manager.valid_module_id(buffer_module));
    ModulePortId module_input_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT);
    ModulePortId module_output_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT);
    VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_input_port_id).get_width());
    VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_output_port_id).get_width());
    port2port_name_map[module_manager.module_port(buffer_module, module_input_port_id).get_name()] = BasicPort(rc_ntwk_output_port_name, 1);
    port2port_name_map[module_manager.module_port(buffer_module, module_output_port_id).get_name()] = module_manager.module_port(module_id, wire_module_output_port);
    print_spice_subckt_instance(fp, 
                                module_manager, 
                                buffer_module,
                                instance_name,
                                port2port_name_map);
    if (!rc_ntwk_middle_output_port_name.empty()) {
      instance_name = std::string("middle_output_buffer");
      port2port_name_map[module_manager.module_port(buffer_module, module_output_port_id).get_name()] = module_manager.module_port(module_id, wire_module_middle_output_port);
    print_spice_subckt_instance(fp, 
                                module_manager, 
                                buffer_module,
                                instance_name,
                                port2port_name_map);
    }
  } else {
    print_spice_short_connection(fp, rc_ntwk_output_port_name, circuit_lib.port_prefix(output_ports[0])); 
    if (!rc_ntwk_middle_output_port_name.empty()) {
      print_spice_short_connection(fp, rc_ntwk_middle_output_port_name, circuit_lib.port_prefix(output_ports[0])); 
    }
  }
  print_spice_subckt_end(fp, module_manager.module_name(module_id)); 
  return status;
}
int print_spice_wire_subckt ( std :: fstream & fp , const ModuleManager & module_manager , const ModuleId & module_id , const CircuitLibrary & circuit_lib , const CircuitModelId & circuit_model ) { if ( false == valid_file_stream ( fp ) ) { return CMD_EXEC_FATAL_ERROR ; } std :: vector < CircuitPortId > input_ports = circuit_lib . model_ports_by_type ( circuit_model , CIRCUIT_MODEL_PORT_INPUT , true ) ; std :: vector < CircuitPortId > output_ports = circuit_lib . model_ports_by_type ( circuit_model , CIRCUIT_MODEL_PORT_OUTPUT , true ) ; VTR_ASSERT ( ( 1 == input_ports . size ( ) ) && ( 1 == circuit_lib . port_size ( input_ports [ 0 ] ) ) ) ; VTR_ASSERT ( ( 1 == output_ports . size ( ) ) && ( 1 == circuit_lib . port_size ( output_ports [ 0 ] ) ) ) ; int status = CMD_EXEC_SUCCESS ; print_spice_subckt_definition ( fp , module_manager , module_id ) ; std :: string input_port_name = circuit_lib . port_prefix ( input_ports [ 0 ] ) ; std :: string output_port_name = circuit_lib . port_prefix ( output_ports [ 0 ] ) ; std :: string middle_output_port_name ; if ( CIRCUIT_MODEL_CHAN_WIRE == circuit_lib . model_type ( circuit_model ) ) { middle_output_port_name = std :: string ( " " ) + output_port_name ; } std :: string rc_ntwk_input_port_name = std :: string ( " " ) + std :: to_string ( 0 ) ; std :: string rc_ntwk_output_port_name = std :: string ( " " ) + std :: to_string ( circuit_lib . wire_num_level ( circuit_model ) - 1 ) ; std :: string rc_ntwk_middle_output_port_name ; if ( CIRCUIT_MODEL_CHAN_WIRE == circuit_lib . model_type ( circuit_model ) ) { rc_ntwk_middle_output_port_name = std :: string ( " " ) + rc_ntwk_output_port_name ; } ModulePortId wire_module_input_port = module_manager . find_module_port ( module_id , input_port_name ) ; ModulePortId wire_module_output_port = module_manager . find_module_port ( module_id , output_port_name ) ; ModulePortId wire_module_middle_output_port = ModulePortId :: INVALID ( ) ; if ( CIRCUIT_MODEL_CHAN_WIRE == circuit_lib . model_type ( circuit_model ) ) { wire_module_middle_output_port = module_manager . find_module_port ( module_id , output_port_name ) ; } if ( circuit_lib . input_buffer_model ( circuit_model ) ) { std :: string instance_name = std :: string ( " " ) ; std :: map < std :: string , BasicPort > port2port_name_map ; ModuleId buffer_module = module_manager . find_module ( circuit_lib . model_name ( circuit_lib . input_buffer_model ( circuit_model ) ) ) ; VTR_ASSERT ( true == module_manager . valid_module_id ( buffer_module ) ) ; ModulePortId module_input_port_id = find_inverter_buffer_module_port ( module_manager , buffer_module , circuit_lib , circuit_model , CIRCUIT_MODEL_PORT_INPUT ) ; ModulePortId module_output_port_id = find_inverter_buffer_module_port ( module_manager , buffer_module , circuit_lib , circuit_model , CIRCUIT_MODEL_PORT_OUTPUT ) ; VTR_ASSERT ( 1 == module_manager . module_port ( buffer_module , module_input_port_id ) . get_width ( ) ) ; VTR_ASSERT ( 1 == module_manager . module_port ( buffer_module , module_output_port_id ) . get_width ( ) ) ; port2port_name_map [ module_manager . module_port ( buffer_module , module_input_port_id ) . get_name ( ) ] = module_manager . module_port ( module_id , wire_module_input_port ) ; port2port_name_map [ module_manager . module_port ( buffer_module , module_output_port_id ) . get_name ( ) ] = BasicPort ( rc_ntwk_input_port_name , 1 ) ; print_spice_subckt_instance ( fp , module_manager , buffer_module , instance_name , port2port_name_map ) ; } else { print_spice_short_connection ( fp , circuit_lib . port_prefix ( input_ports [ 0 ] ) , rc_ntwk_input_port_name ) ; } switch ( circuit_lib . wire_type ( circuit_model ) ) { case WIRE_MODEL_PI : status = print_spice_wire_pi_type_rc_modeling ( fp , rc_ntwk_input_port_name , rc_ntwk_output_port_name , rc_ntwk_middle_output_port_name , circuit_lib . wire_r ( circuit_model ) , circuit_lib . wire_c ( circuit_model ) , circuit_lib . wire_num_level ( circuit_model ) ) ; break ; case WIRE_MODEL_T : status = print_spice_wire_t_type_rc_modeling ( fp , rc_ntwk_input_port_name , rc_ntwk_output_port_name , rc_ntwk_middle_output_port_name , circuit_lib . wire_r ( circuit_model ) , circuit_lib . wire_c ( circuit_model ) , circuit_lib . wire_num_level ( circuit_model ) ) ; break ; default : VTR_LOGF_ERROR ( __FILE__ , __LINE__ , " \n " , circuit_lib . model_name ( circuit_model ) . c_str ( ) ) ; return CMD_EXEC_FATAL_ERROR ; } if ( circuit_lib . output_buffer_model ( circuit_model ) ) { std :: string instance_name = std :: string ( " " ) ; std :: map < std :: string , BasicPort > port2port_name_map ; ModuleId buffer_module = module_manager . find_module ( circuit_lib . model_name ( circuit_lib . output_buffer_model ( circuit_model ) ) ) ; VTR_ASSERT ( true == module_manager . valid_module_id ( buffer_module ) ) ; ModulePortId module_input_port_id = find_inverter_buffer_module_port ( module_manager , buffer_module , circuit_lib , circuit_model , CIRCUIT_MODEL_PORT_INPUT ) ; ModulePortId module_output_port_id = find_inverter_buffer_module_port ( module_manager , buffer_module , circuit_lib , circuit_model , CIRCUIT_MODEL_PORT_OUTPUT ) ; VTR_ASSERT ( 1 == module_manager . module_port ( buffer_module , module_input_port_id ) . get_width ( ) ) ; VTR_ASSERT ( 1 == module_manager . module_port ( buffer_module , module_output_port_id ) . get_width ( ) ) ; port2port_name_map [ module_manager . module_port ( buffer_module , module_input_port_id ) . get_name ( ) ] = BasicPort ( rc_ntwk_output_port_name , 1 ) ; port2port_name_map [ module_manager . module_port ( buffer_module , module_output_port_id ) . get_name ( ) ] = module_manager . module_port ( module_id , wire_module_output_port ) ; print_spice_subckt_instance ( fp , module_manager , buffer_module , instance_name , port2port_name_map ) ; if ( ! rc_ntwk_middle_output_port_name . empty ( ) ) { instance_name = std :: string ( " " ) ; port2port_name_map [ module_manager . module_port ( buffer_module , module_output_port_id ) . get_name ( ) ] = module_manager . module_port ( module_id , wire_module_middle_output_port ) ; print_spice_subckt_instance ( fp , module_manager , buffer_module , instance_name , port2port_name_map ) ; } } else { print_spice_short_connection ( fp , rc_ntwk_output_port_name , circuit_lib . port_prefix ( output_ports [ 0 ] ) ) ; if ( ! rc_ntwk_middle_output_port_name . empty ( ) ) { print_spice_short_connection ( fp , rc_ntwk_middle_output_port_name , circuit_lib . port_prefix ( output_ports [ 0 ] ) ) ; } } print_spice_subckt_end ( fp , module_manager . module_name ( module_id ) ) ; return status ; }
Generate the SPICE subckt for a regular wire
 Schematic
Generate the SPICE subckt for a regular wire Schematic
/* Find the input and output ports:
   * we do NOT support global ports here, 
   * it should be handled in another type of inverter subckt (power-gated)
   */ /* Make sure:
   * There are 1 input ports and 1 output port, 
   * each size of which is 1
   */ /* Print the inverter subckt definition */ /* Add input buffer:
   * - There is a valid buffer model, instanciate it
   * - There is no buffer, set a short connection
   */ /* Port size should be 1 ! */ /* Determine which type of model to print*/ /* Add output buffer:
   * - There is a valid buffer model, instanciate it
   * - There is no buffer, set a short connection
   */ /* Port size should be 1 ! */