update FPGA_SPICE to support max width for transistors and multi-bin
This commit is contained in:
parent
c3fd817bae
commit
fd3e947c6d
|
@ -5,6 +5,7 @@
|
||||||
* logic gates etc.
|
* logic gates etc.
|
||||||
***********************************************/
|
***********************************************/
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <cmath>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
/* Headers from vtrutil library */
|
/* Headers from vtrutil library */
|
||||||
|
@ -125,15 +126,15 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
||||||
* an inverter. Any preprocessing or subckt definition should not be included!
|
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static
|
static
|
||||||
int print_spice_powergated_inverter_modeling(std::fstream& fp,
|
int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp,
|
||||||
const std::string& trans_name_postfix,
|
const std::string& trans_name_postfix,
|
||||||
const std::string& input_port_name,
|
const std::string& input_port_name,
|
||||||
const std::string& output_port_name,
|
const std::string& output_port_name,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const CircuitPortId& enb_port,
|
const CircuitPortId& enb_port,
|
||||||
const CircuitPortId& en_port,
|
|
||||||
const TechnologyLibrary& tech_lib,
|
const TechnologyLibrary& tech_lib,
|
||||||
const TechnologyModelId& tech_model) {
|
const TechnologyModelId& tech_model,
|
||||||
|
const float& trans_width) {
|
||||||
|
|
||||||
if (false == valid_file_stream(fp)) {
|
if (false == valid_file_stream(fp)) {
|
||||||
return CMD_EXEC_FATAL_ERROR;
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
@ -162,11 +163,52 @@ int print_spice_powergated_inverter_modeling(std::fstream& fp,
|
||||||
fp << "LVDD ";
|
fp << "LVDD ";
|
||||||
}
|
}
|
||||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||||
|
fp << "W=" << trans_width;
|
||||||
|
fp << "\n";
|
||||||
|
|
||||||
/* Cache the last pin*/
|
/* Cache the last pin*/
|
||||||
last_enb_pin = power_gate_pin;
|
last_enb_pin = power_gate_pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write transistor pairs using the technology model */
|
||||||
|
fp << "Xpmos_" << trans_name_postfix << " ";
|
||||||
|
fp << output_port_name << " ";
|
||||||
|
fp << input_port_name << " ";
|
||||||
|
fp << output_port_name << "_pmos_pg_" << circuit_lib.pins(enb_port).back() << " ";
|
||||||
|
fp << "LVDD ";
|
||||||
|
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||||
|
fp << "W=" << trans_width;
|
||||||
|
fp << "\n";
|
||||||
|
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Generate the SPICE modeling for the NMOS part of a power-gated inverter
|
||||||
|
*
|
||||||
|
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* - This function does NOT create a file
|
||||||
|
* but requires a file stream created
|
||||||
|
* - This function only output SPICE modeling for
|
||||||
|
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp,
|
||||||
|
const std::string& trans_name_postfix,
|
||||||
|
const std::string& input_port_name,
|
||||||
|
const std::string& output_port_name,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitPortId& en_port,
|
||||||
|
const TechnologyLibrary& tech_lib,
|
||||||
|
const TechnologyModelId& tech_model,
|
||||||
|
const float& trans_width) {
|
||||||
|
|
||||||
|
if (false == valid_file_stream(fp)) {
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
bool first_en_pin = true;
|
bool first_en_pin = true;
|
||||||
size_t last_en_pin;
|
size_t last_en_pin;
|
||||||
for (const auto& power_gate_pin : circuit_lib.pins(en_port)) {
|
for (const auto& power_gate_pin : circuit_lib.pins(en_port)) {
|
||||||
|
@ -180,32 +222,28 @@ int print_spice_powergated_inverter_modeling(std::fstream& fp,
|
||||||
fp << "LGND ";
|
fp << "LGND ";
|
||||||
first_en_pin = false;
|
first_en_pin = false;
|
||||||
} else {
|
} else {
|
||||||
VTR_ASSERT_SAFE(false == first_enb_pin);
|
VTR_ASSERT_SAFE(false == first_en_pin);
|
||||||
fp << output_port_name << "_nmos_pg_" << last_en_pin << " ";
|
fp << output_port_name << "_nmos_pg_" << last_en_pin << " ";
|
||||||
fp << circuit_lib.port_prefix(en_port) << " ";
|
fp << circuit_lib.port_prefix(en_port) << " ";
|
||||||
fp << output_port_name << "_nmos_pg_" << power_gate_pin << " ";
|
fp << output_port_name << "_nmos_pg_" << power_gate_pin << " ";
|
||||||
fp << "LGND ";
|
fp << "LGND ";
|
||||||
}
|
}
|
||||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||||
|
fp << "W=" << trans_width;
|
||||||
|
fp << "\n";
|
||||||
|
|
||||||
/* Cache the last pin*/
|
/* Cache the last pin*/
|
||||||
last_enb_pin = power_gate_pin;
|
last_en_pin = power_gate_pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write transistor pairs using the technology model */
|
|
||||||
fp << "Xpmos_" << trans_name_postfix << " ";
|
|
||||||
fp << output_port_name << " ";
|
|
||||||
fp << input_port_name << " ";
|
|
||||||
fp << output_port_name << "_pmos_pg_" << circuit_lib.pins(enb_port).back() << " ";
|
|
||||||
fp << "LVDD ";
|
|
||||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
|
||||||
|
|
||||||
fp << "Xnmos_" << trans_name_postfix << " ";
|
fp << "Xnmos_" << trans_name_postfix << " ";
|
||||||
fp << output_port_name << " ";
|
fp << output_port_name << " ";
|
||||||
fp << input_port_name << " ";
|
fp << input_port_name << " ";
|
||||||
fp << output_port_name << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " ";
|
fp << output_port_name << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " ";
|
||||||
fp << "LGND ";
|
fp << "LGND ";
|
||||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||||
|
fp << "W=" << trans_width;
|
||||||
|
fp << "\n";
|
||||||
|
|
||||||
return CMD_EXEC_SUCCESS;
|
return CMD_EXEC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -294,17 +332,58 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
||||||
|
|
||||||
int status = CMD_EXEC_SUCCESS;
|
int status = CMD_EXEC_SUCCESS;
|
||||||
|
|
||||||
/* TODO: may consider use size/bin to compact layout etc. */
|
/* Consider use size/bin to compact layout:
|
||||||
for (size_t width = 0; width < circuit_lib.buffer_size(circuit_model); ++width) {
|
* Try to size transistors to the max width for each bin
|
||||||
status = print_spice_powergated_inverter_modeling(fp,
|
* The last bin may not reach the max width
|
||||||
std::to_string(width),
|
*/
|
||||||
|
int total_pmos_width = circuit_lib.buffer_size(circuit_model) * tech_lib.model_pn_ratio(tech_model);
|
||||||
|
int regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||||
|
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||||
|
float last_pmos_bin_width = total_pmos_width % regular_pmos_bin_width;
|
||||||
|
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_pmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_pmos_bins - 1) {
|
||||||
|
curr_bin_width = last_pmos_bin_width;
|
||||||
|
}
|
||||||
|
status = print_spice_powergated_inverter_pmos_modeling(fp,
|
||||||
|
std::to_string(ibin),
|
||||||
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
|
circuit_lib,
|
||||||
|
enb_port,
|
||||||
|
tech_lib,
|
||||||
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consider use size/bin to compact layout:
|
||||||
|
* Try to size transistors to the max width for each bin
|
||||||
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_nmos_width = circuit_lib.buffer_size(circuit_model);
|
||||||
|
int regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||||
|
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||||
|
float last_nmos_bin_width = total_nmos_width % regular_nmos_bin_width;
|
||||||
|
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_nmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_nmos_bins - 1) {
|
||||||
|
curr_bin_width = last_nmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = print_spice_powergated_inverter_nmos_modeling(fp,
|
||||||
|
std::to_string(ibin),
|
||||||
circuit_lib.port_prefix(input_ports[0]),
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
circuit_lib.port_prefix(output_ports[0]),
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
circuit_lib,
|
circuit_lib,
|
||||||
en_port,
|
en_port,
|
||||||
enb_port,
|
|
||||||
tech_lib,
|
tech_lib,
|
||||||
tech_model);
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -316,7 +395,7 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Generate the SPICE modeling for a regular inverter
|
* Generate the SPICE modeling for the PMOS part of a regular inverter
|
||||||
*
|
*
|
||||||
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||||
*
|
*
|
||||||
|
@ -327,12 +406,13 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
||||||
* an inverter. Any preprocessing or subckt definition should not be included!
|
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static
|
static
|
||||||
int print_spice_regular_inverter_modeling(std::fstream& fp,
|
int print_spice_regular_inverter_pmos_modeling(std::fstream& fp,
|
||||||
const std::string& trans_name_postfix,
|
const std::string& trans_name_postfix,
|
||||||
const std::string& input_port_name,
|
const std::string& input_port_name,
|
||||||
const std::string& output_port_name,
|
const std::string& output_port_name,
|
||||||
const TechnologyLibrary& tech_lib,
|
const TechnologyLibrary& tech_lib,
|
||||||
const TechnologyModelId& tech_model) {
|
const TechnologyModelId& tech_model,
|
||||||
|
const float& trans_width) {
|
||||||
|
|
||||||
if (false == valid_file_stream(fp)) {
|
if (false == valid_file_stream(fp)) {
|
||||||
return CMD_EXEC_FATAL_ERROR;
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
@ -345,6 +425,35 @@ int print_spice_regular_inverter_modeling(std::fstream& fp,
|
||||||
fp << "LVDD ";
|
fp << "LVDD ";
|
||||||
fp << "LVDD ";
|
fp << "LVDD ";
|
||||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||||
|
fp << "W=" << trans_width;
|
||||||
|
fp << "\n";
|
||||||
|
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Generate the SPICE modeling for the NMOS part of a regular inverter
|
||||||
|
*
|
||||||
|
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* - This function does NOT create a file
|
||||||
|
* but requires a file stream created
|
||||||
|
* - This function only output SPICE modeling for
|
||||||
|
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
int print_spice_regular_inverter_nmos_modeling(std::fstream& fp,
|
||||||
|
const std::string& trans_name_postfix,
|
||||||
|
const std::string& input_port_name,
|
||||||
|
const std::string& output_port_name,
|
||||||
|
const TechnologyLibrary& tech_lib,
|
||||||
|
const TechnologyModelId& tech_model,
|
||||||
|
const float& trans_width) {
|
||||||
|
|
||||||
|
if (false == valid_file_stream(fp)) {
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
fp << "Xnmos_" << trans_name_postfix << " ";
|
fp << "Xnmos_" << trans_name_postfix << " ";
|
||||||
fp << output_port_name << " ";
|
fp << output_port_name << " ";
|
||||||
|
@ -352,6 +461,8 @@ int print_spice_regular_inverter_modeling(std::fstream& fp,
|
||||||
fp << "LGND ";
|
fp << "LGND ";
|
||||||
fp << "LGND ";
|
fp << "LGND ";
|
||||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||||
|
fp << "W=" << trans_width;
|
||||||
|
fp << "\n";
|
||||||
|
|
||||||
return CMD_EXEC_SUCCESS;
|
return CMD_EXEC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -409,14 +520,56 @@ int print_spice_regular_inverter_subckt(std::fstream& fp,
|
||||||
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
|
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
|
||||||
|
|
||||||
int status = CMD_EXEC_SUCCESS;
|
int status = CMD_EXEC_SUCCESS;
|
||||||
/* TODO: may consider use size/bin to compact layout etc. */
|
|
||||||
for (size_t width = 0; width < circuit_lib.buffer_size(circuit_model); ++width) {
|
/* Consider use size/bin to compact layout:
|
||||||
status = print_spice_regular_inverter_modeling(fp,
|
* Try to size transistors to the max width for each bin
|
||||||
std::to_string(width),
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_pmos_width = circuit_lib.buffer_size(circuit_model) * tech_lib.model_pn_ratio(tech_model);
|
||||||
|
int regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||||
|
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||||
|
float last_pmos_bin_width = total_pmos_width % regular_pmos_bin_width;
|
||||||
|
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_pmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_pmos_bins - 1) {
|
||||||
|
curr_bin_width = last_pmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = print_spice_regular_inverter_pmos_modeling(fp,
|
||||||
|
std::to_string(ibin),
|
||||||
circuit_lib.port_prefix(input_ports[0]),
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
circuit_lib.port_prefix(output_ports[0]),
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
tech_lib,
|
tech_lib,
|
||||||
tech_model);
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consider use size/bin to compact layout:
|
||||||
|
* Try to size transistors to the max width for each bin
|
||||||
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_nmos_width = circuit_lib.buffer_size(circuit_model);
|
||||||
|
int regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||||
|
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||||
|
float last_nmos_bin_width = total_nmos_width % regular_nmos_bin_width;
|
||||||
|
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_nmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_nmos_bins - 1) {
|
||||||
|
curr_bin_width = last_nmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = print_spice_regular_inverter_nmos_modeling(fp,
|
||||||
|
std::to_string(ibin),
|
||||||
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
|
tech_lib,
|
||||||
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +697,13 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp,
|
||||||
/* Buffers must have >= 2 stages */
|
/* Buffers must have >= 2 stages */
|
||||||
VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model));
|
VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model));
|
||||||
|
|
||||||
/* TODO: may consider use size/bin to compact layout etc. */
|
/* Build the array denoting width of inverters per stage */
|
||||||
|
std::vector<float> buffer_widths(circuit_lib.buffer_num_levels(circuit_model), 1);
|
||||||
|
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||||
|
buffer_widths[level] = circuit_lib.buffer_size(circuit_model)
|
||||||
|
* std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||||
std::string input_port_name = circuit_lib.port_prefix(input_ports[0]);
|
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 output_port_name = circuit_lib.port_prefix(output_ports[0]);
|
||||||
|
@ -559,18 +718,65 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp,
|
||||||
input_port_name += std::string("_level") + std::to_string(level - 1);
|
input_port_name += std::string("_level") + std::to_string(level - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t width = 0; width < circuit_lib.buffer_size(circuit_model); ++width) {
|
/* Consider use size/bin to compact layout:
|
||||||
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(width);
|
* Try to size transistors to the max width for each bin
|
||||||
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_pmos_width = buffer_widths[level] * tech_lib.model_pn_ratio(tech_model);
|
||||||
|
int regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||||
|
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||||
|
float last_pmos_bin_width = total_pmos_width % regular_pmos_bin_width;
|
||||||
|
|
||||||
status = print_spice_powergated_inverter_modeling(fp,
|
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_pmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_pmos_bins - 1) {
|
||||||
|
curr_bin_width = last_pmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||||
|
|
||||||
|
status = print_spice_powergated_inverter_pmos_modeling(fp,
|
||||||
|
name_postfix,
|
||||||
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
|
circuit_lib,
|
||||||
|
enb_port,
|
||||||
|
tech_lib,
|
||||||
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consider use size/bin to compact layout:
|
||||||
|
* Try to size transistors to the max width for each bin
|
||||||
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_nmos_width = buffer_widths[level] ;
|
||||||
|
int regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||||
|
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||||
|
float last_nmos_bin_width = total_nmos_width % regular_nmos_bin_width;
|
||||||
|
|
||||||
|
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_nmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_nmos_bins - 1) {
|
||||||
|
curr_bin_width = last_nmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||||
|
|
||||||
|
status = print_spice_powergated_inverter_nmos_modeling(fp,
|
||||||
name_postfix,
|
name_postfix,
|
||||||
circuit_lib.port_prefix(input_ports[0]),
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
circuit_lib.port_prefix(output_ports[0]),
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
circuit_lib,
|
circuit_lib,
|
||||||
en_port,
|
en_port,
|
||||||
enb_port,
|
|
||||||
tech_lib,
|
tech_lib,
|
||||||
tech_model);
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -642,7 +848,13 @@ int print_spice_regular_buffer_subckt(std::fstream& fp,
|
||||||
/* Buffers must have >= 2 stages */
|
/* Buffers must have >= 2 stages */
|
||||||
VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model));
|
VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model));
|
||||||
|
|
||||||
/* TODO: may consider use size/bin to compact layout etc. */
|
/* Build the array denoting width of inverters per stage */
|
||||||
|
std::vector<float> buffer_widths(circuit_lib.buffer_num_levels(circuit_model), 1);
|
||||||
|
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||||
|
buffer_widths[level] = circuit_lib.buffer_size(circuit_model)
|
||||||
|
* std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||||
std::string input_port_name = circuit_lib.port_prefix(input_ports[0]);
|
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 output_port_name = circuit_lib.port_prefix(output_ports[0]);
|
||||||
|
@ -657,14 +869,61 @@ int print_spice_regular_buffer_subckt(std::fstream& fp,
|
||||||
input_port_name += std::string("_level") + std::to_string(level - 1);
|
input_port_name += std::string("_level") + std::to_string(level - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t width = 0; width < circuit_lib.buffer_size(circuit_model); ++width) {
|
/* Consider use size/bin to compact layout:
|
||||||
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(width);
|
* Try to size transistors to the max width for each bin
|
||||||
status = print_spice_regular_inverter_modeling(fp,
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_pmos_width = buffer_widths[level] * tech_lib.model_pn_ratio(tech_model);
|
||||||
|
int regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||||
|
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||||
|
float last_pmos_bin_width = total_pmos_width % regular_pmos_bin_width;
|
||||||
|
|
||||||
|
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_pmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_pmos_bins - 1) {
|
||||||
|
curr_bin_width = last_pmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||||
|
|
||||||
|
status = print_spice_regular_inverter_pmos_modeling(fp,
|
||||||
name_postfix,
|
name_postfix,
|
||||||
input_port_name,
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
output_port_name,
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
tech_lib,
|
tech_lib,
|
||||||
tech_model);
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consider use size/bin to compact layout:
|
||||||
|
* Try to size transistors to the max width for each bin
|
||||||
|
* The last bin may not reach the max width
|
||||||
|
*/
|
||||||
|
int total_nmos_width = buffer_widths[level] ;
|
||||||
|
int regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||||
|
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||||
|
float last_nmos_bin_width = total_nmos_width % regular_nmos_bin_width;
|
||||||
|
|
||||||
|
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||||
|
int curr_bin_width = regular_nmos_bin_width;
|
||||||
|
/* For last bin, we need an irregular width */
|
||||||
|
if (ibin == num_nmos_bins - 1) {
|
||||||
|
curr_bin_width = last_nmos_bin_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||||
|
|
||||||
|
status = print_spice_regular_inverter_nmos_modeling(fp,
|
||||||
|
name_postfix,
|
||||||
|
circuit_lib.port_prefix(input_ports[0]),
|
||||||
|
circuit_lib.port_prefix(output_ports[0]),
|
||||||
|
tech_lib,
|
||||||
|
tech_model,
|
||||||
|
curr_bin_width);
|
||||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue