From 97cca725902e430b03ea030853c8cf6633842f89 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 18:21:11 -0600 Subject: [PATCH 01/11] add spice support on power gated inverters --- .../src/fpga_spice/spice_essential_gates.cpp | 191 +++++++++++++++++- 1 file changed, 183 insertions(+), 8 deletions(-) diff --git a/openfpga/src/fpga_spice/spice_essential_gates.cpp b/openfpga/src/fpga_spice/spice_essential_gates.cpp index e6230b531..9c0f8704b 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.cpp +++ b/openfpga/src/fpga_spice/spice_essential_gates.cpp @@ -112,7 +112,153 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, } /************************************************ - * Generate the SPICE subckt for an inverter + * Generate the SPICE subckt for a power gated inverter + * The Enable signal controlled the power gating + * Schematic + * LVDD + * | + * - + * ENb -o|| + * - + * | + * - + * +-o|| + * | - + * | | + * in-->+ +--> OUT + * | | + * | - + * +--|| + * - + * | + * - + * EN -|| + * - + * | + * LGND + * + ***********************************************/ +static +int print_spice_powergated_inverter_subckt(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { + if (false == valid_file_stream(fp)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Print the inverter subckt definition */ + print_spice_subckt_definition(fp, module_manager, module_id); + + /* 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) + */ + std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + + /* Make sure: + * There is only 1 input port and 1 output port, + * each size of which is 1 + */ + 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])) ); + + /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ + VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); + /* Check all the ports we have are good for a power-gated circuit model */ + size_t num_err = 0; + /* We need at least one global port */ + if (2 != global_ports.size()) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Expect two global ports (a pair of EN/Enb) for Inverter/buffer circuit model '%s' which is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); + num_err++; + } + /* All the global ports should be config_enable */ + for (const auto& port : global_ports) { + if (false == circuit_lib.port_is_config_enable(port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Inverter/buffer circuit model '%s' is power-gated. At least one config-enable global port is required!\n", + circuit_lib.model_name(circuit_model).c_str()); + num_err++; + } + } + /* Report errors if there are any */ + if (0 < num_err) { + exit(1); + } + + /* Try to find a pair of Enable and ENb ports from the global ports */ + VTR_ASSERT(2 == global_ports.size()); + CircuitPortId en_port = CircuitPortId::INVALID(); + CircuitPortId enb_port = CircuitPortId::INVALID(); + for (const auto& port : global_ports) { + if (0 == circuit_lib.port_default_value(port)) { + en_port = port; + } else { + VTR_ASSERT(1 == circuit_lib.port_default_value(port)); + enb_port = port; + } + } + /* We must have valid EN/ENb ports */ + if (false == circuit_lib.valid_circuit_port_id(en_port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Fail to find an enable port for the inverter/buffer circuit model '%s' is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); + } + if (false == circuit_lib.valid_circuit_port_id(enb_port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Fail to find an inverted enable port for the inverter/buffer circuit model '%s' is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); + } + + /* TODO: may consider use size/bin to compact layout etc. */ + for (size_t i = 0; i < circuit_lib.buffer_size(circuit_model); ++i) { + /* Write power-gateing transistor pairs using the technology model */ + fp << "Xpmos_powergate_" << i << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg "; + fp << circuit_lib.port_prefix(enb_port) << " "; + fp << "LVDD "; + fp << "LVDD "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + + fp << "Xnmos_powergate_" << i << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << " _nmos_pg "; + fp << circuit_lib.port_prefix(en_port) << " "; + fp << "LGND "; + fp << "LGND "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + + /* Write transistor pairs using the technology model */ + fp << "Xpmos_" << i << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << " "; + fp << circuit_lib.port_prefix(input_ports[0]) << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg "; + fp << "LVDD "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + + fp << "Xnmos_" << i << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << " "; + fp << circuit_lib.port_prefix(input_ports[0]) << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << " _nmos_pg "; + fp << "LGND "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + } + + print_spice_subckt_end(fp, module_manager.module_name(module_id)); + + return CMD_EXEC_SUCCESS; +} + +/************************************************ + * Generate the SPICE subckt for a regular inverter * Schematic * LVDD * | @@ -130,13 +276,13 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, * ***********************************************/ static -int print_spice_inverter_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +int print_spice_regular_inverter_subckt(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } @@ -181,6 +327,35 @@ int print_spice_inverter_subckt(std::fstream& fp, return CMD_EXEC_SUCCESS; } +/************************************************ + * Generate the SPICE subckt for an inverter + * Branch on the different circuit topologies + ***********************************************/ +static +int print_spice_inverter_subckt(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { + int status = CMD_EXEC_SUCCESS; + if (true == circuit_lib.is_power_gated(circuit_model)) { + status = print_spice_powergated_inverter_subckt(fp, + module_manager, module_id, + circuit_lib, circuit_model, + tech_lib, tech_model); + } else { + VTR_ASSERT_SAFE(false == circuit_lib.is_power_gated(circuit_model)); + status = print_spice_regular_inverter_subckt(fp, + module_manager, module_id, + circuit_lib, circuit_model, + tech_lib, tech_model); + } + + return status; +} + /************************************************ * Generate the SPICE netlist for essential gates: * - inverters and their templates From f573fa3ee0b6f1a1e046d05fbf4c7fe8c159f0b9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 18:47:12 -0600 Subject: [PATCH 02/11] move check codes on power gate ports to libarchopenfpga Try to report errors to users as early as possible --- .../src/check_circuit_library.cpp | 95 ++++++++++++++++++- .../src/fpga_spice/spice_essential_gates.cpp | 55 ++--------- .../fpga_verilog/verilog_essential_gates.cpp | 32 ++----- openfpga/src/utils/circuit_library_utils.cpp | 58 +++++++++++ openfpga/src/utils/circuit_library_utils.h | 6 ++ 5 files changed, 172 insertions(+), 74 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp index b38fbf1b6..ea6db0678 100644 --- a/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp @@ -302,7 +302,9 @@ size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib, return num_err; } -/* Check all the ports make sure, they satisfy the restriction */ +/************************************************************************ + * Check all the ports make sure, they satisfy the restriction + ***********************************************************************/ static size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { size_t num_err = 0; @@ -435,6 +437,94 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { return num_err; } +/************************************************************************ + * Check the port requirements for a power-gated circuit model + * - It must have at least 2 global ports and which are config enable signals + * - It must have an Enable port which control power gating + * - It must have an EnableB port which control power gating + ***********************************************************************/ +static +int check_power_gated_circuit_model(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + int num_err = 0; + + std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + + /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ + VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); + /* Check all the ports we have are good for a power-gated circuit model */ + /* We need at least one global port */ + if (2 > global_ports.size()) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Expect at least two global ports (a pair of EN/Enb) for circuit model '%s' which is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); + num_err++; + } + /* All the global ports should be config_enable */ + int num_config_enable_ports = 0; + for (const auto& port : global_ports) { + if (true == circuit_lib.port_is_config_enable(port)) { + num_config_enable_ports++; + } + } + + if (2 != num_config_enable_ports) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Circuit model '%s' is power-gated. Two config-enable global ports are required!\n", + circuit_lib.model_name(circuit_model).c_str()); + num_err++; + } + /* Report errors if there are any */ + if (0 < num_err) { + return num_err; + } + + /* Try to find a pair of Enable and ENb ports from the global ports */ + CircuitPortId en_port = CircuitPortId::INVALID(); + CircuitPortId enb_port = CircuitPortId::INVALID(); + for (const auto& port : global_ports) { + /* Focus on config_enable ports which are power-gate control signals */ + if (false == circuit_lib.port_is_config_enable(port)) { + continue; + } + if (0 == circuit_lib.port_default_value(port)) { + en_port = port; + } else { + VTR_ASSERT(1 == circuit_lib.port_default_value(port)); + enb_port = port; + } + } + /* We must have valid EN/ENb ports */ + if (false == circuit_lib.valid_circuit_port_id(en_port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Fail to find an enable port for the circuit model '%s' is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); + } + if (false == circuit_lib.valid_circuit_port_id(enb_port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Fail to find an inverted enable port for the circuit model '%s' is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); + } + + return num_err; +} + +/************************************************************************ + * Check the port requirements for each power-gated circuit model + ***********************************************************************/ +static +int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) { + int num_err = 0; + + for (const CircuitModelId& circuit_model : circuit_lib.models()) { + if (true == circuit_lib.is_power_gated(circuit_model)) { + num_err += check_power_gated_circuit_model(circuit_lib, circuit_model); + } + } + + return num_err; +} + /************************************************************************ * Check points to make sure we have a valid circuit library * Detailed checkpoints: @@ -541,6 +631,9 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_CHAN_WIRE); num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_WIRE); + /* 11. Check power-gated inverter/buffer models */ + num_err += check_power_gated_circuit_models(circuit_lib); + /* If we have any errors, exit */ if (0 < num_err) { diff --git a/openfpga/src/fpga_spice/spice_essential_gates.cpp b/openfpga/src/fpga_spice/spice_essential_gates.cpp index 9c0f8704b..7661045c9 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.cpp +++ b/openfpga/src/fpga_spice/spice_essential_gates.cpp @@ -17,6 +17,8 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" +#include "circuit_library_utils.h" + #include "spice_constants.h" #include "spice_writer_utils.h" #include "spice_essential_gates.h" @@ -159,7 +161,6 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, */ std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Make sure: * There is only 1 input port and 1 output port, @@ -170,54 +171,10 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); - /* Check all the ports we have are good for a power-gated circuit model */ - size_t num_err = 0; - /* We need at least one global port */ - if (2 != global_ports.size()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Expect two global ports (a pair of EN/Enb) for Inverter/buffer circuit model '%s' which is power-gated!\n", - circuit_lib.model_name(circuit_model).c_str()); - num_err++; - } - /* All the global ports should be config_enable */ - for (const auto& port : global_ports) { - if (false == circuit_lib.port_is_config_enable(port)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Inverter/buffer circuit model '%s' is power-gated. At least one config-enable global port is required!\n", - circuit_lib.model_name(circuit_model).c_str()); - num_err++; - } - } - /* Report errors if there are any */ - if (0 < num_err) { - exit(1); - } - - /* Try to find a pair of Enable and ENb ports from the global ports */ - VTR_ASSERT(2 == global_ports.size()); - CircuitPortId en_port = CircuitPortId::INVALID(); - CircuitPortId enb_port = CircuitPortId::INVALID(); - for (const auto& port : global_ports) { - if (0 == circuit_lib.port_default_value(port)) { - en_port = port; - } else { - VTR_ASSERT(1 == circuit_lib.port_default_value(port)); - enb_port = port; - } - } - /* We must have valid EN/ENb ports */ - if (false == circuit_lib.valid_circuit_port_id(en_port)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fail to find an enable port for the inverter/buffer circuit model '%s' is power-gated!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); - } - if (false == circuit_lib.valid_circuit_port_id(enb_port)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fail to find an inverted enable port for the inverter/buffer circuit model '%s' is power-gated!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); - } + CircuitPortId en_port = find_circuit_model_power_gate_en_port(circuit_lib, circuit_model); + CircuitPortId enb_port = find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model); + VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(en_port)); + VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(enb_port)); /* TODO: may consider use size/bin to compact layout etc. */ for (size_t i = 0; i < circuit_lib.buffer_size(circuit_model); ++i) { diff --git a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp index cb8eb9504..4893b5f49 100644 --- a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp +++ b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp @@ -48,6 +48,10 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, fp << "\talways @(" << std::endl; /* Power-gate port first*/ for (const auto& power_gate_port : power_gate_ports) { + /* Only config_enable signal will be considered */ + if (false == circuit_lib.port_is_config_enable(power_gate_port)) { + continue; + } /* Skip first comma to dump*/ if (0 < &power_gate_port - &power_gate_ports[0]) { fp << ","; @@ -61,6 +65,10 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, /* For the first pin, we skip output comma */ size_t port_cnt = 0; for (const auto& power_gate_port : power_gate_ports) { + /* Only config_enable signal will be considered */ + if (false == circuit_lib.port_is_config_enable(power_gate_port)) { + continue; + } for (const auto& power_gate_pin : circuit_lib.pins(power_gate_port)) { if (0 < port_cnt) { fp << std::endl << "\t\t&&"; @@ -161,30 +169,6 @@ void print_verilog_invbuf_module(const ModuleManager& module_manager, 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])) ); - /* TODO: move the check codes to check_circuit_library.h */ - /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ - if (true == circuit_lib.is_power_gated(circuit_model)) { - /* Check all the ports we have are good for a power-gated circuit model */ - size_t num_err = 0; - /* We need at least one global port */ - if (0 == global_ports.size()) { - num_err++; - } - /* All the global ports should be config_enable */ - for (const auto& port : global_ports) { - if (false == circuit_lib.port_is_config_enable(port)) { - num_err++; - } - } - /* Report errors if there are any */ - if (0 < num_err) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Inverter/buffer circuit model '%s' is power-gated. At least one config-enable global port is required!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); - } - } - /* Create a Verilog Module based on the circuit model, and add to module manager */ ModuleId module_id = module_manager.find_module(circuit_lib.model_name(circuit_model)); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index 07ef140a3..d336e5f2b 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -287,4 +287,62 @@ bool check_configurable_memory_circuit_model(const e_config_protocol_type& confi return (0 == num_err); } +/************************************************************************ + * Try to find the enable port control power-gate for a power-gated circuit model + * We will return the first port that meet the requirement: + * - a global port + * - its function is labelled as config_enable + * - default value is 0 + * Return invalid id if not found + ***********************************************************************/ +CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); + std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + + /* Try to find an ENABLE port from the global ports */ + CircuitPortId en_port = CircuitPortId::INVALID(); + for (const auto& port : global_ports) { + /* Focus on config_enable ports which are power-gate control signals */ + if (false == circuit_lib.port_is_config_enable(port)) { + continue; + } + if (0 == circuit_lib.port_default_value(port)) { + en_port = port; + break; + } + } + + return en_port; +} + +/************************************************************************ + * Try to find the enableB port control power-gate for a power-gated circuit model + * We will return the first port that meet the requirement: + * - a global port + * - its function is labelled as config_enable + * - default value is 1 + * Return invalid id if not found + ***********************************************************************/ +CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + CircuitPortId enb_port = CircuitPortId::INVALID(); + VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); + std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + + /* Try to find an ENABLE_B port from the global ports */ + for (const auto& port : global_ports) { + /* Focus on config_enable ports which are power-gate control signals */ + if (false == circuit_lib.port_is_config_enable(port)) { + continue; + } + if (1 == circuit_lib.port_default_value(port)) { + enb_port = port; + break; + } + } + + return enb_port; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/circuit_library_utils.h b/openfpga/src/utils/circuit_library_utils.h index 255da4f4f..584871868 100644 --- a/openfpga/src/utils/circuit_library_utils.h +++ b/openfpga/src/utils/circuit_library_utils.h @@ -43,6 +43,12 @@ bool check_configurable_memory_circuit_model(const e_config_protocol_type& confi const CircuitLibrary& circuit_lib, const CircuitModelId& config_mem_circuit_model); +CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); + +CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); + } /* end namespace openfpga */ #endif From a4a38f8156a4f361d62bed9de9a2ef69eda61a47 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 20:04:39 -0600 Subject: [PATCH 03/11] support multi-bit power gate ports in FPGA-SPICE --- .../src/fpga_spice/spice_essential_gates.cpp | 121 ++++++++++++------ openfpga/src/utils/circuit_library_utils.cpp | 4 +- 2 files changed, 87 insertions(+), 38 deletions(-) diff --git a/openfpga/src/fpga_spice/spice_essential_gates.cpp b/openfpga/src/fpga_spice/spice_essential_gates.cpp index 7661045c9..b5836a4b3 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.cpp +++ b/openfpga/src/fpga_spice/spice_essential_gates.cpp @@ -117,27 +117,38 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, * Generate the SPICE subckt for a power gated inverter * The Enable signal controlled the power gating * Schematic - * LVDD - * | - * - - * ENb -o|| - * - - * | - * - - * +-o|| - * | - - * | | - * in-->+ +--> OUT - * | | - * | - - * +--|| - * - - * | - * - - * EN -|| - * - - * | - * LGND + * LVDD + * | + * - + * ENb[0] -o|| + * - + * | + * - + * ENb[1] -o|| + * - + * | + * ... + * | + * - + * +-o|| + * | - + * | | + * in-->+ +--> OUT + * | | + * | - + * +--|| + * - + * ... + * | + * - + * EN[1] -|| + * - + * | + * - + * EN[0] -|| + * - + * | + * LGND * ***********************************************/ static @@ -178,33 +189,71 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, /* TODO: may consider use size/bin to compact layout etc. */ for (size_t i = 0; i < circuit_lib.buffer_size(circuit_model); ++i) { - /* Write power-gateing transistor pairs using the technology model */ - fp << "Xpmos_powergate_" << i << " "; - fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg "; - fp << circuit_lib.port_prefix(enb_port) << " "; - fp << "LVDD "; - fp << "LVDD "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + /* Write power-gating transistor pairs using the technology model + * Note that for a mulit-bit power gating port, we should cascade the transistors + */ + bool first_enb_pin = true; + size_t last_enb_pin; + for (const auto& power_gate_pin : circuit_lib.pins(enb_port)) { + BasicPort enb_pin(circuit_lib.port_prefix(enb_port), power_gate_pin, power_gate_pin); + fp << "Xpmos_powergate_" << i << "_pin_" << power_gate_pin << " "; + /* For the first pin, we should connect it to local VDD*/ + if (true == first_enb_pin) { + fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << power_gate_pin << " "; + fp << generate_spice_port(enb_pin) << " "; + fp << "LVDD "; + fp << "LVDD "; + first_enb_pin = false; + } else { + VTR_ASSERT_SAFE(false == first_enb_pin); + fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << last_enb_pin << " "; + fp << generate_spice_port(enb_pin) << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << power_gate_pin << " "; + fp << "LVDD "; + } + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; - fp << "Xnmos_powergate_" << i << " "; - fp << circuit_lib.port_prefix(output_ports[0]) << " _nmos_pg "; - fp << circuit_lib.port_prefix(en_port) << " "; - fp << "LGND "; - fp << "LGND "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + /* Cache the last pin*/ + last_enb_pin = power_gate_pin; + } + + bool first_en_pin = true; + size_t last_en_pin; + for (const auto& power_gate_pin : circuit_lib.pins(en_port)) { + BasicPort en_pin(circuit_lib.port_prefix(en_port), power_gate_pin, power_gate_pin); + fp << "Xnmos_powergate_" << i << "_pin_" << power_gate_pin << " "; + /* For the first pin, we should connect it to local VDD*/ + if (true == first_en_pin) { + fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << power_gate_pin << " "; + fp << generate_spice_port(en_pin) << " "; + fp << "LGND "; + fp << "LGND "; + first_en_pin = false; + } else { + VTR_ASSERT_SAFE(false == first_enb_pin); + fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << last_en_pin << " "; + fp << circuit_lib.port_prefix(en_port) << " "; + fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << power_gate_pin << " "; + fp << "LGND "; + } + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + + /* Cache the last pin*/ + last_enb_pin = power_gate_pin; + } /* Write transistor pairs using the technology model */ fp << "Xpmos_" << i << " "; fp << circuit_lib.port_prefix(output_ports[0]) << " "; fp << circuit_lib.port_prefix(input_ports[0]) << " "; - fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg "; + fp << circuit_lib.port_prefix(output_ports[0]) << "_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_" << i << " "; fp << circuit_lib.port_prefix(output_ports[0]) << " "; fp << circuit_lib.port_prefix(input_ports[0]) << " "; - fp << circuit_lib.port_prefix(output_ports[0]) << " _nmos_pg "; + fp << circuit_lib.port_prefix(output_ports[0]) << " _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; } diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index d336e5f2b..cd59545ae 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -307,7 +307,7 @@ CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circui if (false == circuit_lib.port_is_config_enable(port)) { continue; } - if (0 == circuit_lib.port_default_value(port)) { + if (1 == circuit_lib.port_default_value(port)) { en_port = port; break; } @@ -336,7 +336,7 @@ CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circu if (false == circuit_lib.port_is_config_enable(port)) { continue; } - if (1 == circuit_lib.port_default_value(port)) { + if (0 == circuit_lib.port_default_value(port)) { enb_port = port; break; } From 87ef7f9f997fef23157fe7779319aae0a554932b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 20:06:10 -0600 Subject: [PATCH 04/11] add power gate example architecture --- .../k4_N4_40nm_powergate_frame_openfpga.xml | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml new file mode 100644 index 000000000..567e7775f --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ca867ea6fada2541295a099f2295adaec5b17a0e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 20:09:52 -0600 Subject: [PATCH 05/11] add power gate inverter test case (full testbench) --- .../power_gated_inverter/config/task.conf | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 openfpga_flow/tasks/power_gated_design/power_gated_inverter/config/task.conf diff --git a/openfpga_flow/tasks/power_gated_design/power_gated_inverter/config/task.conf b/openfpga_flow/tasks/power_gated_design/power_gated_inverter/config/task.conf new file mode 100644 index 000000000..fd4e9ddc9 --- /dev/null +++ b/openfpga_flow/tasks/power_gated_design/power_gated_inverter/config/task.conf @@ -0,0 +1,33 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/fast_configuration_example_script.openfpga +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +external_fabric_key_file= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 22159531c5c1606b37096dd4b3238a6add6bd647 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 20:21:38 -0600 Subject: [PATCH 06/11] bug fix in power gating support of FPGA-Verilog --- openfpga/src/fpga_verilog/verilog_essential_gates.cpp | 9 +++------ .../k4_N4_40nm_powergate_frame_openfpga.xml | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp index 4893b5f49..d33407071 100644 --- a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp +++ b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp @@ -45,18 +45,15 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, /* Create a sensitive list */ fp << "\treg " << circuit_lib.port_prefix(output_port) << "_reg;" << std::endl; - fp << "\talways @(" << std::endl; + fp << "\talways @("; /* Power-gate port first*/ for (const auto& power_gate_port : power_gate_ports) { /* Only config_enable signal will be considered */ if (false == circuit_lib.port_is_config_enable(power_gate_port)) { continue; } - /* Skip first comma to dump*/ - if (0 < &power_gate_port - &power_gate_ports[0]) { - fp << ","; - } fp << circuit_lib.port_prefix(power_gate_port); + fp << ", "; } fp << circuit_lib.port_prefix(input_port) << ") begin" << std::endl; @@ -78,7 +75,7 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, /* Power-gated signal are disable during operating, enabled during configuration, * Therefore, we need to reverse them here */ - if (0 == circuit_lib.port_default_value(power_gate_port)) { + if (1 == circuit_lib.port_default_value(power_gate_port)) { fp << "~"; } diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml index 567e7775f..bf96e1aa0 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml @@ -36,8 +36,8 @@ - - + + 10e-12 From 8a79ff2c247dac0f53794c189be79db08364967b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 20:22:59 -0600 Subject: [PATCH 07/11] deploy power gating test cases to CI --- .travis/verilog_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis/verilog_reg_test.sh b/.travis/verilog_reg_test.sh index f49b6ab84..e5c6bbd40 100755 --- a/.travis/verilog_reg_test.sh +++ b/.travis/verilog_reg_test.sh @@ -75,6 +75,9 @@ python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/generate_vanilla_key - python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/generate_random_key --debug --show_thread_logs python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/load_external_key --debug --show_thread_logs +echo -e "Testing Power-gating designs"; +python3 openfpga_flow/scripts/run_fpga_task.py power_gated_design/power_gated_inverter --show_thread_logs --debug + # Verify MCNC big20 benchmark suite with ModelSim # Please make sure you have ModelSim installed in the environment # Otherwise, it will fail From fefcd88f142f156305793ebbf041407fb4bfe085 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Jul 2020 21:55:59 -0600 Subject: [PATCH 08/11] update openfpga architecture README for power-gating --- openfpga_flow/openfpga_arch/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/openfpga_arch/README.md b/openfpga_flow/openfpga_arch/README.md index 0799af78e..2e5dede96 100644 --- a/openfpga_flow/openfpga_arch/README.md +++ b/openfpga_flow/openfpga_arch/README.md @@ -23,5 +23,6 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f - stdcell: If circuit designs are built with standard cells only - tree\_mux: If routing multiplexers are built with a tree-like structure - : The technology node which the delay numbers are extracted from. +- powergate : The FPGA has power-gating techniques applied. If not defined, there is no power-gating. Other features are used in naming should be listed here. From be5966475e2d04f7d0a4591747345ffe97ebfd03 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Jul 2020 12:23:27 -0600 Subject: [PATCH 09/11] formulate file name, module name and instance name to be consistent --- openfpga/src/base/openfpga_naming.cpp | 5 +++-- openfpga/src/fpga_verilog/verilog_grid.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index f4a72ff61..ccf540eac 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -238,7 +238,7 @@ std::string generate_routing_block_netlist_name(const std::string& prefix, std::string generate_routing_block_netlist_name(const std::string& prefix, const vtr::Point& coordinate, const std::string& postfix) { - return std::string( prefix + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + postfix ); + return std::string( prefix + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") + postfix ); } /********************************************************************* @@ -1183,8 +1183,9 @@ std::string generate_grid_block_instance_name(const std::string& prefix, module_name += generate_grid_block_netlist_name(block_name, is_block_io, io_side, std::string()); module_name += std::string("_"); module_name += std::to_string(grid_coord.x()); - module_name += std::string("_"); + module_name += std::string("__"); module_name += std::to_string(grid_coord.y()); + module_name += std::string("_"); return module_name; } diff --git a/openfpga/src/fpga_verilog/verilog_grid.cpp b/openfpga/src/fpga_verilog/verilog_grid.cpp index d2917836b..9fc395769 100644 --- a/openfpga/src/fpga_verilog/verilog_grid.cpp +++ b/openfpga/src/fpga_verilog/verilog_grid.cpp @@ -270,7 +270,7 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager, /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ std::string verilog_fname(subckt_dir - + generate_grid_block_netlist_name(std::string(phy_block_type->name), + + generate_grid_block_netlist_name(std::string(GRID_MODULE_NAME_PREFIX) + std::string(phy_block_type->name), is_io_type(phy_block_type), border_side, std::string(VERILOG_NETLIST_FILE_POSTFIX)) From 26038361115e93b7ab6d8821faef28018e959e8c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Jul 2020 12:53:21 -0600 Subject: [PATCH 10/11] split logical tile netlists to keep good Verilog hierarchy --- openfpga/src/base/openfpga_naming.cpp | 5 +- openfpga/src/fpga_verilog/verilog_grid.cpp | 110 +++++++++++++-------- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index ccf540eac..f743ef3f6 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -968,10 +968,8 @@ std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib, std::string generate_logical_tile_netlist_name(const std::string& prefix, const t_pb_graph_node* pb_graph_head, const std::string& postfix) { - /* This must be the root node */ - VTR_ASSERT(true == pb_graph_head->is_root()); /* Add the name of physical block */ - std::string module_name = prefix + std::string(pb_graph_head->pb_type->name); + std::string module_name = prefix + generate_physical_block_module_name(pb_graph_head->pb_type); module_name += postfix; @@ -1245,7 +1243,6 @@ std::string generate_physical_block_module_name(t_pb_type* physical_pb_type) { return module_name; } - /********************************************************************* * Generate the instance name for physical block with a given index **********************************************************************/ diff --git a/openfpga/src/fpga_verilog/verilog_grid.cpp b/openfpga/src/fpga_verilog/verilog_grid.cpp index 9fc395769..35af744e6 100644 --- a/openfpga/src/fpga_verilog/verilog_grid.cpp +++ b/openfpga/src/fpga_verilog/verilog_grid.cpp @@ -63,14 +63,12 @@ namespace openfpga { * *******************************************************************/ static -void print_verilog_primitive_block(std::fstream& fp, +void print_verilog_primitive_block(NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, t_pb_graph_node* primitive_pb_graph_node, const bool& use_explicit_mapping, const bool& verbose) { - /* Ensure a valid file handler */ - VTR_ASSERT(true == valid_file_stream(fp)); - /* Ensure a valid pb_graph_node */ if (nullptr == primitive_pb_graph_node) { VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -78,6 +76,24 @@ void print_verilog_primitive_block(std::fstream& fp, exit(1); } + /* Give a name to the Verilog netlist */ + /* Create the file name for Verilog */ + std::string verilog_fname(subckt_dir + + generate_logical_tile_netlist_name(std::string(), primitive_pb_graph_node, std::string(VERILOG_NETLIST_FILE_POSTFIX)) + ); + + VTR_LOG("Writing Verilog netlist '%s' for primitive pb_type '%s' ...", + verilog_fname.c_str(), primitive_pb_graph_node->pb_type->name); + VTR_LOGV(verbose, "\n"); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); + + check_file_stream(verilog_fname.c_str(), fp); + + print_verilog_file_header(fp, std::string("Verilog modules for primitive pb_type: " + std::string(primitive_pb_graph_node->pb_type->name))); + /* Generate the module name for this primitive pb_graph_node*/ std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type); @@ -93,8 +109,13 @@ void print_verilog_primitive_block(std::fstream& fp, /* Write the verilog module */ write_verilog_module_to_file(fp, module_manager, primitive_module, use_explicit_mapping); - /* Add an empty line as a splitter */ - fp << std::endl; + /* Close file handler */ + fp.close(); + + /* Add fname to the netlist name list */ + NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname); + VTR_ASSERT(NetlistId::INVALID() != nlist_id); + netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOGV(verbose, "Done\n"); } @@ -115,14 +136,13 @@ void print_verilog_primitive_block(std::fstream& fp, * to its parent in module manager *******************************************************************/ static -void rec_print_verilog_logical_tile(std::fstream& fp, +void rec_print_verilog_logical_tile(NetlistManager& netlist_manager, const ModuleManager& module_manager, const VprDeviceAnnotation& device_annotation, + const std::string& subckt_dir, t_pb_graph_node* physical_pb_graph_node, const bool& use_explicit_mapping, const bool& verbose) { - /* Check the file handler*/ - VTR_ASSERT(true == valid_file_stream(fp)); /* Check cur_pb_graph_node*/ if (nullptr == physical_pb_graph_node) { @@ -143,8 +163,9 @@ void rec_print_verilog_logical_tile(std::fstream& fp, if (false == is_primitive_pb_type(physical_pb_type)) { for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Go recursive to visit the children */ - rec_print_verilog_logical_tile(fp, - module_manager, device_annotation, + rec_print_verilog_logical_tile(netlist_manager, + module_manager, device_annotation, + subckt_dir, &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]), use_explicit_mapping, verbose); @@ -156,7 +177,9 @@ void rec_print_verilog_logical_tile(std::fstream& fp, * explict port mapping. This aims to avoid any port sequence issues!!! */ if (true == is_primitive_pb_type(physical_pb_type)) { - print_verilog_primitive_block(fp, module_manager, + print_verilog_primitive_block(netlist_manager, + module_manager, + subckt_dir, physical_pb_graph_node, true, verbose); @@ -164,6 +187,24 @@ void rec_print_verilog_logical_tile(std::fstream& fp, return; } + /* Give a name to the Verilog netlist */ + /* Create the file name for Verilog */ + std::string verilog_fname(subckt_dir + + generate_logical_tile_netlist_name(std::string(), physical_pb_graph_node, std::string(VERILOG_NETLIST_FILE_POSTFIX)) + ); + + VTR_LOG("Writing Verilog netlist '%s' for pb_type '%s' ...", + verilog_fname.c_str(), physical_pb_type->name); + VTR_LOGV(verbose, "\n"); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); + + check_file_stream(verilog_fname.c_str(), fp); + + print_verilog_file_header(fp, std::string("Verilog modules for pb_type: " + std::string(physical_pb_type->name))); + /* Generate the name of the Verilog module for this pb_type */ std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); @@ -172,7 +213,7 @@ void rec_print_verilog_logical_tile(std::fstream& fp, VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); VTR_LOGV(verbose, - "Writing Verilog codes of logical tile block '%s'...", + "Writing Verilog codes of pb_type '%s'...", module_manager.module_name(pb_module).c_str()); /* Comment lines */ @@ -183,8 +224,13 @@ void rec_print_verilog_logical_tile(std::fstream& fp, print_verilog_comment(fp, std::string("----- END Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); - /* Add an empty line as a splitter */ - fp << std::endl; + /* Close file handler */ + fp.close(); + + /* Add fname to the netlist name list */ + NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname); + VTR_ASSERT(NetlistId::INVALID() != nlist_id); + netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOGV(verbose, "Done\n"); } @@ -201,23 +247,10 @@ void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager, t_pb_graph_node* pb_graph_head, const bool& use_explicit_mapping, const bool& verbose) { - /* Give a name to the Verilog netlist */ - /* Create the file name for Verilog */ - std::string verilog_fname(subckt_dir - + generate_logical_tile_netlist_name(std::string(LOGICAL_MODULE_VERILOG_FILE_NAME_PREFIX), pb_graph_head, std::string(VERILOG_NETLIST_FILE_POSTFIX)) - ); - VTR_LOG("Writing Verilog netlist '%s' for logic tile '%s' ...", - verilog_fname.c_str(), pb_graph_head->pb_type->name); - VTR_LOGV(verbose, "\n"); - - /* Create the file stream */ - std::fstream fp; - fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); - - check_file_stream(verilog_fname.c_str(), fp); - - print_verilog_file_header(fp, std::string("Verilog modules for logical tile: " + std::string(pb_graph_head->pb_type->name) + "]")); + VTR_LOG("Writing Verilog netlists for logic tile '%s' ...", + pb_graph_head->pb_type->name); + VTR_LOG("\n"); /* Print Verilog modules for all the pb_types/pb_graph_nodes * use a Depth-First Search Algorithm to print the sub-modules @@ -226,23 +259,14 @@ void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager, * to its parent in module manager */ /* Print Verilog modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ - rec_print_verilog_logical_tile(fp, module_manager, + rec_print_verilog_logical_tile(netlist_manager, + module_manager, device_annotation, + subckt_dir, pb_graph_head, use_explicit_mapping, verbose); - /* Add an empty line as a splitter */ - fp << std::endl; - - /* Close file handler */ - fp.close(); - - /* Add fname to the netlist name list */ - NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname); - VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); - VTR_LOG("Done\n"); VTR_LOG("\n"); } From 021fedbc12ccd43dcdd761e4262442683b3140f2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Jul 2020 12:55:40 -0600 Subject: [PATCH 11/11] update fabric key to synchronize with new module/instance naming --- .../fabric_keys/k4_N4_2x2_sample_key.xml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml index 7d4840e56..81716fb00 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml @@ -1,35 +1,35 @@ - + - - + + - + - - + + - + - + - + - + - - + +