From 6a0f4f354f28344123fb041139995f7d52a169dc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 9 Feb 2021 20:23:05 -0700 Subject: [PATCH] [Tool] Support superLUT circuit model in core engine --- openfpga/src/fabric/build_lut_modules.cpp | 34 ++++++--- openfpga/src/fabric/build_mux_modules.cpp | 58 ++++++++++++-- .../fpga_bitstream/build_grid_bitstream.cpp | 2 +- .../fpga_sdc/configure_port_sdc_writer.cpp | 4 +- openfpga/src/mux_lib/mux_library_builder.cpp | 3 +- .../src/repack/build_physical_truth_table.cpp | 76 ++++++++++++------- openfpga/src/utils/circuit_library_utils.cpp | 50 ++++++++++++ openfpga/src/utils/circuit_library_utils.h | 10 +++ 8 files changed, 186 insertions(+), 51 deletions(-) diff --git a/openfpga/src/fabric/build_lut_modules.cpp b/openfpga/src/fabric/build_lut_modules.cpp index 142c2369f..a8442f62f 100644 --- a/openfpga/src/fabric/build_lut_modules.cpp +++ b/openfpga/src/fabric/build_lut_modules.cpp @@ -45,8 +45,13 @@ void build_lut_module(ModuleManager& module_manager, std::vector lut_global_ports = circuit_lib.model_global_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, false, true); /* Get the input ports from the mux */ std::vector lut_input_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true); + /* Find the inputs that drive the internal LUT MUX */ + std::vector lut_mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, lut_model, false); + /* Get the output ports from the mux */ std::vector lut_output_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + /* Find the outputs that are driven the internal LUT MUX */ + std::vector lut_mux_output_ports = find_lut_circuit_model_output_port(circuit_lib, lut_model, false); /* Classify SRAM ports into two categories: regular (not for mode select) and mode-select */ std::vector lut_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, lut_model); @@ -60,8 +65,8 @@ void build_lut_module(ModuleManager& module_manager, /* Single-output LUTs: * We should have only 1 input port, 1 output port and 1 SRAM port */ - VTR_ASSERT (1 == lut_input_ports.size()); - VTR_ASSERT (1 == lut_output_ports.size()); + VTR_ASSERT (1 == lut_mux_input_ports.size()); + VTR_ASSERT (1 == lut_mux_output_ports.size()); VTR_ASSERT (1 == lut_regular_sram_ports.size()); VTR_ASSERT (0 == lut_mode_select_sram_ports.size()); } else { @@ -70,8 +75,8 @@ void build_lut_module(ModuleManager& module_manager, * We should have only 1 input port, a few output ports (fracturable outputs) * and two SRAM ports */ - VTR_ASSERT (1 == lut_input_ports.size()); - VTR_ASSERT (1 <= lut_output_ports.size()); + VTR_ASSERT (1 == lut_mux_input_ports.size()); + VTR_ASSERT (1 <= lut_mux_output_ports.size()); VTR_ASSERT (1 == lut_regular_sram_ports.size()); VTR_ASSERT ( (0 == lut_mode_select_sram_ports.size()) || (1 == lut_mode_select_sram_ports.size())); @@ -155,10 +160,10 @@ void build_lut_module(ModuleManager& module_manager, * +--------------------------------------+ */ /* Get the tri-state port map for the input ports*/ - std::string tri_state_map = circuit_lib.port_tri_state_map(lut_input_ports[0]); + std::string tri_state_map = circuit_lib.port_tri_state_map(lut_mux_input_ports[0]); size_t mode_select_port_lsb = 0; - for (const auto& pin : circuit_lib.pins(lut_input_ports[0])) { - ModulePortId lut_module_input_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(lut_input_ports[0])); + for (const auto& pin : circuit_lib.pins(lut_mux_input_ports[0])) { + ModulePortId lut_module_input_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(lut_mux_input_ports[0])); VTR_ASSERT(true == module_manager.valid_module_port_id(lut_module, lut_module_input_port_id)); /* Create a module net for the connection */ @@ -200,7 +205,7 @@ void build_lut_module(ModuleManager& module_manager, required_gate_type = CIRCUIT_MODEL_GATE_OR; } /* Get the circuit model of the gate */ - CircuitModelId gate_model = circuit_lib.port_tri_state_model(lut_input_ports[0]); + CircuitModelId gate_model = circuit_lib.port_tri_state_model(lut_mux_input_ports[0]); /* Check this is the gate we want ! */ VTR_ASSERT (required_gate_type == circuit_lib.gate_type(gate_model)); @@ -290,7 +295,7 @@ void build_lut_module(ModuleManager& module_manager, std::vector lut_mux_sram_inv_nets; /* Now we need to add inverters by instanciating the modules */ - for (size_t pin = 0; pin < circuit_lib.port_size(lut_input_ports[0]); ++pin) { + for (size_t pin = 0; pin < circuit_lib.port_size(lut_mux_input_ports[0]); ++pin) { ModuleNetId lut_mux_sram_inv_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module, circuit_lib, input_inverter_model, mode_selected_nets[pin]); @@ -308,7 +313,7 @@ void build_lut_module(ModuleManager& module_manager, std::vector lut_mux_sram_nets; /* Now we need to add inverters by instanciating the modules and add module nets */ - for (size_t pin = 0; pin < circuit_lib.port_size(lut_input_ports[0]); ++pin) { + for (size_t pin = 0; pin < circuit_lib.port_size(lut_mux_input_ports[0]); ++pin) { ModuleNetId lut_mux_sram_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module, circuit_lib, input_buffer_model, mode_selected_nets[pin]); @@ -362,7 +367,7 @@ void build_lut_module(ModuleManager& module_manager, */ ModulePortId lut_sram_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(lut_regular_sram_ports[0])); BasicPort lut_sram_port = module_manager.module_port(lut_module, lut_sram_port_id); - ModulePortId lut_mux_input_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_prefix(lut_input_ports[0])); + ModulePortId lut_mux_input_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_prefix(lut_mux_input_ports[0])); BasicPort lut_mux_input_port = module_manager.module_port(lut_mux_module, lut_mux_input_port_id); VTR_ASSERT(lut_mux_input_port.get_width() == lut_sram_port.get_width()); /* Wire the port to lut_mux_sram_net */ @@ -372,7 +377,7 @@ void build_lut_module(ModuleManager& module_manager, module_manager.add_module_net_sink(lut_module, net, lut_mux_module, lut_mux_instance, lut_mux_input_port_id, lut_mux_input_port.pins()[pin_id]); } - for (const auto& port : lut_output_ports) { + for (const auto& port : lut_mux_output_ports) { ModulePortId lut_output_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(port)); BasicPort lut_output_port = module_manager.module_port(lut_module, lut_output_port_id); ModulePortId lut_mux_output_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_prefix(port)); @@ -407,6 +412,11 @@ void build_lut_modules(ModuleManager& module_manager, if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(lut_model)) { continue; } + /* We skip user-defined models */ + if ( (false == circuit_lib.model_verilog_netlist(lut_model).empty()) + || (false == circuit_lib.model_spice_netlist(lut_model).empty()) ) { + continue; + } build_lut_module(module_manager, circuit_lib, lut_model); } } diff --git a/openfpga/src/fabric/build_mux_modules.cpp b/openfpga/src/fabric/build_mux_modules.cpp index fcf0db026..10b693cfc 100644 --- a/openfpga/src/fabric/build_mux_modules.cpp +++ b/openfpga/src/fabric/build_mux_modules.cpp @@ -734,8 +734,18 @@ vtr::vector build_mux_module_input_buffers(ModuleManage const MuxGraph& mux_graph) { vtr::vector mux_input_nets(mux_graph.num_inputs(), ModuleNetId::INVALID()); - /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + /* Get the input ports from the mux: + * - LUT may have ports that are driven by harden logic, + * which should not be included when building the mux graph + */ + std::vector mux_input_ports; + if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { + mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, mux_model, false); + } else { + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + } + /* We should have only 1 input port! */ VTR_ASSERT(1 == mux_input_ports.size()); @@ -849,8 +859,18 @@ vtr::vector build_mux_module_output_buffers(ModuleMana /* Create module nets for output ports */ vtr::vector mux_output_nets(mux_graph.num_outputs(), ModuleNetId::INVALID()); - /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + /* Get the output ports from the mux: + * - LUT may have ports that are driven by harden logic, + * which should not be included when building the mux graph + * - LUT may have global output ports that are wired directly to top-level module + */ + std::vector mux_output_ports; + if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { + mux_output_ports = find_lut_circuit_model_output_port(circuit_lib, mux_model, false, false); + } else { + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + } /* Iterate over all the outputs in the MUX module */ for (const auto& output_port : mux_output_ports) { @@ -1096,10 +1116,32 @@ void build_cmos_mux_module(ModuleManager& module_manager, const MuxGraph& mux_graph) { /* Get the global ports required by MUX (and any submodules) */ std::vector mux_global_ports = circuit_lib.model_global_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true, true); - /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); - /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + + /* Get the input ports from the mux: + * - LUT may have ports that are driven by harden logic, + * which should not be included when building the mux graph + */ + std::vector mux_input_ports; + if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { + mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, mux_model, false); + } else { + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + } + + /* Get the output ports from the mux: + * - LUT may have ports that are driven by harden logic, + * which should not be included when building the mux graph + * - LUT may have global output ports that are wired directly to top-level module + */ + std::vector mux_output_ports; + if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { + mux_output_ports = find_lut_circuit_model_output_port(circuit_lib, mux_model, false, false); + } else { + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + } + /* Get the sram ports from the mux * Multiplexing structure does not mode_sram_ports, they are handled in LUT modules * Here we just bypass it. diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 3062c126f..c7eca7aee 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -407,7 +407,7 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager, VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model)); /* Find the input ports for LUT size, this is used to decode the LUT memory bits! */ - std::vector model_input_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector model_input_ports = find_lut_circuit_model_input_port(circuit_lib, lut_model, false); VTR_ASSERT(1 == model_input_ports.size()); size_t lut_size = circuit_lib.port_size(model_input_ports[0]); diff --git a/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp b/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp index 42d5c030c..861dac33d 100644 --- a/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp @@ -89,7 +89,9 @@ int print_sdc_disable_lut_configure_ports(std::fstream& fp, } const std::string& sram_inv_port_name = circuit_lib.port_lib_name(sram_port) + INV_PORT_POSTFIX; - VTR_ASSERT(true == module_manager.valid_module_port_id(programmable_module, module_manager.find_module_port(programmable_module, sram_inv_port_name))); + if (false == module_manager.valid_module_port_id(programmable_module, module_manager.find_module_port(programmable_module, sram_inv_port_name))) { + continue; + } if (CMD_EXEC_FATAL_ERROR == rec_print_sdc_disable_timing_for_module_ports(fp, flatten_names, diff --git a/openfpga/src/mux_lib/mux_library_builder.cpp b/openfpga/src/mux_lib/mux_library_builder.cpp index 3657972ff..599914de8 100644 --- a/openfpga/src/mux_lib/mux_library_builder.cpp +++ b/openfpga/src/mux_lib/mux_library_builder.cpp @@ -11,6 +11,7 @@ /* Headers from readarchopenfpga library */ #include "circuit_types.h" #include "circuit_library.h" +#include "circuit_library_utils.h" #include "mux_utils.h" #include "pb_type_utils.h" @@ -182,7 +183,7 @@ void build_lut_mux_library(MuxLibrary& mux_lib, } /* Find the MUX size required by the LUT */ /* Get input ports which are not global ports! */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector input_ports = find_lut_circuit_model_input_port(circuit_lib, circuit_model, false); VTR_ASSERT(1 == input_ports.size()); /* MUX size = 2^lut_size */ size_t lut_mux_size = (size_t)pow(2., (double)(circuit_lib.port_size(input_ports[0]))); diff --git a/openfpga/src/repack/build_physical_truth_table.cpp b/openfpga/src/repack/build_physical_truth_table.cpp index 404911a2d..37dfa231c 100644 --- a/openfpga/src/repack/build_physical_truth_table.cpp +++ b/openfpga/src/repack/build_physical_truth_table.cpp @@ -50,39 +50,47 @@ static std::vector generate_lut_rotated_input_pin_map(const std::vector& input_nets, const AtomContext& atom_ctx, const AtomBlockId& atom_blk, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const t_pb_graph_node* pb_graph_node) { /* Find the pin rotation status and record it , * Note that some LUT inputs may not be used, we set them to be open by default */ std::vector rotated_pin_map(input_nets.size(), -1); - VTR_ASSERT(1 == pb_graph_node->num_input_ports); + for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { + /* Skip the input pin that do not drive by LUT MUXes */ + CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port); + if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { + continue; + } - for (int ipin = 0; ipin < pb_graph_node->num_input_pins[0]; ++ipin) { - /* The lut pb_graph_node may not be the primitive node - * because VPR adds two default modes to its LUT pb_type - * If so, we will use the LUT mode of the pb_graph node - */ - t_port* lut_pb_type_in_port = pb_graph_node->input_pins[0][ipin].port; - if (0 != pb_graph_node->pb_type->num_modes) { - VTR_ASSERT(2 == pb_graph_node->pb_type->num_modes); - VTR_ASSERT(1 == pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE].num_pb_type_children); - lut_pb_type_in_port = &(pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE].pb_type_children[0].ports[0]); - VTR_ASSERT(std::string(lut_pb_type_in_port->name) == std::string(pb_graph_node->input_pins[0][ipin].port->name)); - VTR_ASSERT(lut_pb_type_in_port->num_pins == pb_graph_node->input_pins[0][ipin].port->num_pins); - } + /* The lut pb_graph_node may not be the primitive node + * because VPR adds two default modes to its LUT pb_type + * If so, we will use the LUT mode of the pb_graph node + */ + t_port* lut_pb_type_in_port = pb_graph_node->input_pins[iport][ipin].port; + if (0 != pb_graph_node->pb_type->num_modes) { + VTR_ASSERT(2 == pb_graph_node->pb_type->num_modes); + VTR_ASSERT(1 == pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE].num_pb_type_children); + lut_pb_type_in_port = &(pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE].pb_type_children[0].ports[iport]); + VTR_ASSERT(std::string(lut_pb_type_in_port->name) == std::string(pb_graph_node->input_pins[iport][ipin].port->name)); + VTR_ASSERT(lut_pb_type_in_port->num_pins == pb_graph_node->input_pins[iport][ipin].port->num_pins); + } - /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ - AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, lut_pb_type_in_port->model_port); - if (!atom_port) { - continue; - } + /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ + AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, lut_pb_type_in_port->model_port); + if (!atom_port) { + continue; + } - for (AtomPinId atom_pin : atom_ctx.nlist.port_pins(atom_port)) { - AtomNetId atom_pin_net = atom_ctx.nlist.pin_net(atom_pin); - if (atom_pin_net == input_nets[ipin]) { - rotated_pin_map[ipin] = atom_ctx.nlist.pin_port_bit(atom_pin); - break; + for (AtomPinId atom_pin : atom_ctx.nlist.port_pins(atom_port)) { + AtomNetId atom_pin_net = atom_ctx.nlist.pin_net(atom_pin); + if (atom_pin_net == input_nets[ipin]) { + rotated_pin_map[ipin] = atom_ctx.nlist.pin_port_bit(atom_pin); + break; + } } } } @@ -109,15 +117,27 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, /* Find all the nets mapped to each inputs */ std::vector input_nets; - VTR_ASSERT(1 == pb_graph_node->num_input_ports); - for (int ipin = 0; ipin < pb_graph_node->num_input_pins[0]; ++ipin) { - input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[0][ipin]))); + for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { + /* Skip the input pin that do not drive by LUT MUXes */ + CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port); + if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { + continue; + } + input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[iport][ipin]))); + } } /* Find all the nets mapped to each outputs */ for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { const t_pb_graph_pin* output_pin = &(pb_graph_node->output_pins[iport][ipin]); + /* Skip the output ports that are not driven by LUT MUXes */ + CircuitPortId circuit_port = device_annotation.pb_circuit_port(output_pin->port); + if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { + continue; + } + AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin); /* Bypass unmapped pins */ if (AtomNetId::INVALID() == output_net) { @@ -135,7 +155,7 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, VTR_ASSERT(true == atom_ctx.nlist.valid_block_id(atom_blk)); const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk); - std::vector rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, pb_graph_node); + std::vector rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, device_annotation, circuit_lib, pb_graph_node); adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map); } diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index 8fb5aa7bc..197c873bd 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -368,4 +368,54 @@ CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circu return enb_port; } +/************************************************************************ + * Try to find the input ports for a LUT circuit model (EXCLUDE the global ports) + * which can optionally include those ports drives or is driven by hard logic + ***********************************************************************/ +std::vector find_lut_circuit_model_input_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const bool& include_harden_port, + const bool& include_global_port) { + VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)); + + std::vector input_ports; + + /* Find all the non-global input ports */ + for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, !include_global_port)) { + /* Skip harden ports if specified */ + if ( (true == circuit_lib.port_is_harden_lut_port(port)) + && (false == include_harden_port)) { + continue; + } + input_ports.push_back(port); + } + + return input_ports; +} + +/************************************************************************ + * Try to find the output ports for a LUT circuit model (EXCLUDE the global ports) + * which can optionally include those ports drives or is driven by hard logic + ***********************************************************************/ +std::vector find_lut_circuit_model_output_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const bool& include_harden_port, + const bool& include_global_port) { + VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)); + + std::vector output_ports; + + /* Find all the non-global input ports */ + for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, !include_global_port)) { + /* Skip harden ports if specified */ + if ( (true == circuit_lib.port_is_harden_lut_port(port)) + && (false == include_harden_port)) { + continue; + } + output_ports.push_back(port); + } + + return output_ports; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/circuit_library_utils.h b/openfpga/src/utils/circuit_library_utils.h index dc7fd0e34..758af9689 100644 --- a/openfpga/src/utils/circuit_library_utils.h +++ b/openfpga/src/utils/circuit_library_utils.h @@ -51,6 +51,16 @@ CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circui CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); +std::vector find_lut_circuit_model_input_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const bool& include_harden_port, + const bool& include_global_port = true); + +std::vector find_lut_circuit_model_output_port(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const bool& include_harden_port, + const bool& include_global_port = true); + } /* end namespace openfpga */ #endif