From a3d22c56e35c6a83d34fda9e51688e399f7eb311 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Jul 2020 19:51:32 -0600 Subject: [PATCH] bug fix in FPGA-SPICE --- .../src/read_xml_technology_library.cpp | 6 +- .../src/fpga_spice/spice_essential_gates.cpp | 123 +++++++++++------- 2 files changed, 79 insertions(+), 50 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp b/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp index 2437a1089..e2871a638 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp @@ -124,7 +124,11 @@ void read_xml_device_transistor(pugi::xml_node& xml_device_transistor, /* Parse the transistor maximum width, by default we consider the same as minimum width */ tech_lib.set_transistor_model_max_width(device_model, transistor_type, - get_attribute(xml_device_transistor, "max_width", loc_data, pugiutil::ReqOpt::OPTIONAL).as_float(tech_lib.transistor_model_min_width(device_model, transistor_type))); + get_attribute(xml_device_transistor, "max_width", loc_data, pugiutil::ReqOpt::OPTIONAL).as_float(0.)); + /* If the max_width is default value, we set it to be the same as min_width */ + if (0. == tech_lib.transistor_model_max_width(device_model, transistor_type)) { + tech_lib.set_transistor_model_max_width(device_model, transistor_type, tech_lib.transistor_model_min_width(device_model, transistor_type)); + } /* Parse the transistor variation name */ tech_lib.set_transistor_model_variation_name(device_model, transistor_type, diff --git a/openfpga/src/fpga_spice/spice_essential_gates.cpp b/openfpga/src/fpga_spice/spice_essential_gates.cpp index af32d980d..7fd144f33 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.cpp +++ b/openfpga/src/fpga_spice/spice_essential_gates.cpp @@ -86,9 +86,11 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); /* Create file */ - VTR_LOG("Generating SPICE netlist '%s' for essential gates...", + VTR_LOG("Generating SPICE netlist '%s' for transistors...", spice_fname.c_str()); + print_spice_file_header(fp, std::string("Transistor wrappers")); + /* Iterate over the transistor models */ for (const TechnologyModelId& model : tech_lib.models()) { /* Focus on transistor model */ @@ -163,7 +165,7 @@ int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp, fp << "LVDD "; } fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; - fp << "W=" << trans_width; + fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; /* Cache the last pin*/ @@ -177,7 +179,7 @@ int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp, 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 << " W=" << std::setprecision(10) << trans_width; fp << "\n"; return CMD_EXEC_SUCCESS; @@ -229,7 +231,7 @@ int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, fp << "LGND "; } fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; - fp << "W=" << trans_width; + fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; /* Cache the last pin*/ @@ -242,7 +244,7 @@ int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, fp << output_port_name << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " "; fp << "LGND "; fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; - fp << "W=" << trans_width; + fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; return CMD_EXEC_SUCCESS; @@ -336,14 +338,17 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, * Try to size transistors to the max width for each bin * 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); + float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = circuit_lib.buffer_size(circuit_model) + * tech_lib.model_pn_ratio(tech_model) + * tech_lib.transistor_model_min_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; + float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { - int curr_bin_width = regular_pmos_bin_width; + float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_pmos_bins - 1) { + if ((ibin == num_pmos_bins - 1) + && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } status = print_spice_powergated_inverter_pmos_modeling(fp, @@ -364,14 +369,16 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, * 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); + float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = circuit_lib.buffer_size(circuit_model) + * tech_lib.transistor_model_min_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; + float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { - int curr_bin_width = regular_nmos_bin_width; + float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_nmos_bins - 1) { + if ((ibin == num_nmos_bins - 1) + && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } @@ -425,7 +432,7 @@ int print_spice_regular_inverter_pmos_modeling(std::fstream& fp, fp << "LVDD "; fp << "LVDD "; fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; - fp << "W=" << trans_width; + fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; return CMD_EXEC_SUCCESS; @@ -461,7 +468,7 @@ int print_spice_regular_inverter_nmos_modeling(std::fstream& fp, fp << "LGND "; fp << "LGND "; fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; - fp << "W=" << trans_width; + fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; return CMD_EXEC_SUCCESS; @@ -525,14 +532,17 @@ int print_spice_regular_inverter_subckt(std::fstream& fp, * Try to size transistors to the max width for each bin * 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); + float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = circuit_lib.buffer_size(circuit_model) + * tech_lib.model_pn_ratio(tech_model) + * tech_lib.transistor_model_min_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; + float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { - int curr_bin_width = regular_pmos_bin_width; + float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_pmos_bins - 1) { + if ((ibin == num_pmos_bins - 1) + && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } @@ -552,14 +562,17 @@ int print_spice_regular_inverter_subckt(std::fstream& fp, * 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); + float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = circuit_lib.buffer_size(circuit_model) + * tech_lib.transistor_model_min_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; + float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { - int curr_bin_width = regular_nmos_bin_width; + float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_nmos_bins - 1) { + if ((ibin == num_nmos_bins - 1) + && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } @@ -722,15 +735,18 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp, * 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); + float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = buffer_widths[level] + * tech_lib.model_pn_ratio(tech_model) + * tech_lib.transistor_model_min_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; + float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { - int curr_bin_width = regular_pmos_bin_width; + float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_pmos_bins - 1) { + if ((ibin == num_pmos_bins - 1) + && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } @@ -754,15 +770,17 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp, * 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); + float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = buffer_widths[level] + * tech_lib.transistor_model_min_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; + float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { - int curr_bin_width = regular_nmos_bin_width; + float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_nmos_bins - 1) { + if ((ibin == num_nmos_bins - 1) + && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } @@ -873,15 +891,18 @@ int print_spice_regular_buffer_subckt(std::fstream& fp, * 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); + float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = buffer_widths[level] + * tech_lib.model_pn_ratio(tech_model) + * tech_lib.transistor_model_min_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; + float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { - int curr_bin_width = regular_pmos_bin_width; + float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_pmos_bins - 1) { + if ((ibin == num_pmos_bins - 1) + && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } @@ -903,15 +924,17 @@ int print_spice_regular_buffer_subckt(std::fstream& fp, * 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); + float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = buffer_widths[level] + * tech_lib.transistor_model_min_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; + float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { - int curr_bin_width = regular_nmos_bin_width; + float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if (ibin == num_nmos_bins - 1) { + if ((ibin == num_nmos_bins - 1) + && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } @@ -987,15 +1010,17 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); /* Create file */ - VTR_LOG("Generating SPICE netlist '%s' for transistor wrappers...", + VTR_LOG("Generating SPICE netlist '%s' for essential gates...", spice_fname.c_str()); + print_spice_file_header(fp, std::string("Essential gates")); + int status = CMD_EXEC_SUCCESS; /* Iterate over the circuit models */ for (const CircuitModelId& circuit_model : circuit_lib.models()) { /* Bypass models require extern netlists */ - if (true == circuit_lib.model_circuit_netlist(circuit_model).empty()) { + if (!circuit_lib.model_circuit_netlist(circuit_model).empty()) { continue; }