[Tool] Support superLUT circuit model in core engine

This commit is contained in:
tangxifan 2021-02-09 20:23:05 -07:00
parent 7dcc14d73f
commit 6a0f4f354f
8 changed files with 186 additions and 51 deletions

View File

@ -45,8 +45,13 @@ void build_lut_module(ModuleManager& module_manager,
std::vector<CircuitPortId> lut_global_ports = circuit_lib.model_global_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, false, true); std::vector<CircuitPortId> 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 */ /* Get the input ports from the mux */
std::vector<CircuitPortId> lut_input_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true); std::vector<CircuitPortId> 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<CircuitPortId> lut_mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, lut_model, false);
/* Get the output ports from the mux */ /* Get the output ports from the mux */
std::vector<CircuitPortId> lut_output_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_OUTPUT, false); std::vector<CircuitPortId> 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<CircuitPortId> 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 */ /* Classify SRAM ports into two categories: regular (not for mode select) and mode-select */
std::vector<CircuitPortId> lut_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, lut_model); std::vector<CircuitPortId> 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: /* Single-output LUTs:
* We should have only 1 input port, 1 output port and 1 SRAM port * 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_mux_input_ports.size());
VTR_ASSERT (1 == lut_output_ports.size()); VTR_ASSERT (1 == lut_mux_output_ports.size());
VTR_ASSERT (1 == lut_regular_sram_ports.size()); VTR_ASSERT (1 == lut_regular_sram_ports.size());
VTR_ASSERT (0 == lut_mode_select_sram_ports.size()); VTR_ASSERT (0 == lut_mode_select_sram_ports.size());
} else { } 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) * We should have only 1 input port, a few output ports (fracturable outputs)
* and two SRAM ports * and two SRAM ports
*/ */
VTR_ASSERT (1 == lut_input_ports.size()); VTR_ASSERT (1 == lut_mux_input_ports.size());
VTR_ASSERT (1 <= lut_output_ports.size()); VTR_ASSERT (1 <= lut_mux_output_ports.size());
VTR_ASSERT (1 == lut_regular_sram_ports.size()); VTR_ASSERT (1 == lut_regular_sram_ports.size());
VTR_ASSERT ( (0 == lut_mode_select_sram_ports.size()) VTR_ASSERT ( (0 == lut_mode_select_sram_ports.size())
|| (1 == 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*/ /* 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; size_t mode_select_port_lsb = 0;
for (const auto& pin : circuit_lib.pins(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_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)); VTR_ASSERT(true == module_manager.valid_module_port_id(lut_module, lut_module_input_port_id));
/* Create a module net for the connection */ /* 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; required_gate_type = CIRCUIT_MODEL_GATE_OR;
} }
/* Get the circuit model of the gate */ /* 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 ! */ /* Check this is the gate we want ! */
VTR_ASSERT (required_gate_type == circuit_lib.gate_type(gate_model)); VTR_ASSERT (required_gate_type == circuit_lib.gate_type(gate_model));
@ -290,7 +295,7 @@ void build_lut_module(ModuleManager& module_manager,
std::vector<ModuleNetId> lut_mux_sram_inv_nets; std::vector<ModuleNetId> lut_mux_sram_inv_nets;
/* Now we need to add inverters by instanciating the modules */ /* 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, ModuleNetId lut_mux_sram_inv_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module,
circuit_lib, input_inverter_model, circuit_lib, input_inverter_model,
mode_selected_nets[pin]); mode_selected_nets[pin]);
@ -308,7 +313,7 @@ void build_lut_module(ModuleManager& module_manager,
std::vector<ModuleNetId> lut_mux_sram_nets; std::vector<ModuleNetId> lut_mux_sram_nets;
/* Now we need to add inverters by instanciating the modules and add module 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, ModuleNetId lut_mux_sram_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module,
circuit_lib, input_buffer_model, circuit_lib, input_buffer_model,
mode_selected_nets[pin]); 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])); 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); 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); 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()); VTR_ASSERT(lut_mux_input_port.get_width() == lut_sram_port.get_width());
/* Wire the port to lut_mux_sram_net */ /* 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]); 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)); 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); 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)); 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)) { if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(lut_model)) {
continue; 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); build_lut_module(module_manager, circuit_lib, lut_model);
} }
} }

View File

@ -734,8 +734,18 @@ vtr::vector<MuxInputId, ModuleNetId> build_mux_module_input_buffers(ModuleManage
const MuxGraph& mux_graph) { const MuxGraph& mux_graph) {
vtr::vector<MuxInputId, ModuleNetId> mux_input_nets(mux_graph.num_inputs(), ModuleNetId::INVALID()); vtr::vector<MuxInputId, ModuleNetId> mux_input_nets(mux_graph.num_inputs(), ModuleNetId::INVALID());
/* Get the input ports from the mux */ /* Get the input ports from the mux:
std::vector<CircuitPortId> mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); * - LUT may have ports that are driven by harden logic,
* which should not be included when building the mux graph
*/
std::vector<CircuitPortId> 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! */ /* We should have only 1 input port! */
VTR_ASSERT(1 == mux_input_ports.size()); VTR_ASSERT(1 == mux_input_ports.size());
@ -849,8 +859,18 @@ vtr::vector<MuxOutputId, ModuleNetId> build_mux_module_output_buffers(ModuleMana
/* Create module nets for output ports */ /* Create module nets for output ports */
vtr::vector<MuxOutputId, ModuleNetId> mux_output_nets(mux_graph.num_outputs(), ModuleNetId::INVALID()); vtr::vector<MuxOutputId, ModuleNetId> mux_output_nets(mux_graph.num_outputs(), ModuleNetId::INVALID());
/* Get the output ports from the mux */ /* Get the output ports from the mux:
std::vector<CircuitPortId> mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); * - 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<CircuitPortId> 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 */ /* Iterate over all the outputs in the MUX module */
for (const auto& output_port : mux_output_ports) { for (const auto& output_port : mux_output_ports) {
@ -1096,10 +1116,32 @@ void build_cmos_mux_module(ModuleManager& module_manager,
const MuxGraph& mux_graph) { const MuxGraph& mux_graph) {
/* Get the global ports required by MUX (and any submodules) */ /* Get the global ports required by MUX (and any submodules) */
std::vector<CircuitPortId> mux_global_ports = circuit_lib.model_global_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true, true); std::vector<CircuitPortId> 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<CircuitPortId> mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Get the input ports from the mux:
/* Get the output ports from the mux */ * - LUT may have ports that are driven by harden logic,
std::vector<CircuitPortId> mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); * which should not be included when building the mux graph
*/
std::vector<CircuitPortId> 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<CircuitPortId> 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 /* Get the sram ports from the mux
* Multiplexing structure does not mode_sram_ports, they are handled in LUT modules * Multiplexing structure does not mode_sram_ports, they are handled in LUT modules
* Here we just bypass it. * Here we just bypass it.

View File

@ -407,7 +407,7 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager,
VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model)); 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! */ /* Find the input ports for LUT size, this is used to decode the LUT memory bits! */
std::vector<CircuitPortId> model_input_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true); std::vector<CircuitPortId> model_input_ports = find_lut_circuit_model_input_port(circuit_lib, lut_model, false);
VTR_ASSERT(1 == model_input_ports.size()); VTR_ASSERT(1 == model_input_ports.size());
size_t lut_size = circuit_lib.port_size(model_input_ports[0]); size_t lut_size = circuit_lib.port_size(model_input_ports[0]);

View File

@ -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; 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 == if (CMD_EXEC_FATAL_ERROR ==
rec_print_sdc_disable_timing_for_module_ports(fp, rec_print_sdc_disable_timing_for_module_ports(fp,
flatten_names, flatten_names,

View File

@ -11,6 +11,7 @@
/* Headers from readarchopenfpga library */ /* Headers from readarchopenfpga library */
#include "circuit_types.h" #include "circuit_types.h"
#include "circuit_library.h" #include "circuit_library.h"
#include "circuit_library_utils.h"
#include "mux_utils.h" #include "mux_utils.h"
#include "pb_type_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 */ /* Find the MUX size required by the LUT */
/* Get input ports which are not global ports! */ /* Get input ports which are not global ports! */
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); std::vector<CircuitPortId> input_ports = find_lut_circuit_model_input_port(circuit_lib, circuit_model, false);
VTR_ASSERT(1 == input_ports.size()); VTR_ASSERT(1 == input_ports.size());
/* MUX size = 2^lut_size */ /* MUX size = 2^lut_size */
size_t lut_mux_size = (size_t)pow(2., (double)(circuit_lib.port_size(input_ports[0]))); size_t lut_mux_size = (size_t)pow(2., (double)(circuit_lib.port_size(input_ports[0])));

View File

@ -50,39 +50,47 @@ static
std::vector<int> generate_lut_rotated_input_pin_map(const std::vector<AtomNetId>& input_nets, std::vector<int> generate_lut_rotated_input_pin_map(const std::vector<AtomNetId>& input_nets,
const AtomContext& atom_ctx, const AtomContext& atom_ctx,
const AtomBlockId& atom_blk, const AtomBlockId& atom_blk,
const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib,
const t_pb_graph_node* pb_graph_node) { const t_pb_graph_node* pb_graph_node) {
/* Find the pin rotation status and record it , /* 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 * Note that some LUT inputs may not be used, we set them to be open by default
*/ */
std::vector<int> rotated_pin_map(input_nets.size(), -1); std::vector<int> 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
/* The lut pb_graph_node may not be the primitive node * because VPR adds two default modes to its LUT pb_type
* because VPR adds two default modes to its LUT pb_type * If so, we will use the LUT mode of the pb_graph node
* 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;
t_port* lut_pb_type_in_port = pb_graph_node->input_pins[0][ipin].port; if (0 != pb_graph_node->pb_type->num_modes) {
if (0 != pb_graph_node->pb_type->num_modes) { VTR_ASSERT(2 == 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);
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]);
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[iport][ipin].port->name));
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[iport][ipin].port->num_pins);
VTR_ASSERT(lut_pb_type_in_port->num_pins == pb_graph_node->input_pins[0][ipin].port->num_pins); }
}
/* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ /* 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); AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, lut_pb_type_in_port->model_port);
if (!atom_port) { if (!atom_port) {
continue; continue;
} }
for (AtomPinId atom_pin : atom_ctx.nlist.port_pins(atom_port)) { for (AtomPinId atom_pin : atom_ctx.nlist.port_pins(atom_port)) {
AtomNetId atom_pin_net = atom_ctx.nlist.pin_net(atom_pin); AtomNetId atom_pin_net = atom_ctx.nlist.pin_net(atom_pin);
if (atom_pin_net == input_nets[ipin]) { if (atom_pin_net == input_nets[ipin]) {
rotated_pin_map[ipin] = atom_ctx.nlist.pin_port_bit(atom_pin); rotated_pin_map[ipin] = atom_ctx.nlist.pin_port_bit(atom_pin);
break; break;
}
} }
} }
} }
@ -109,15 +117,27 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
/* Find all the nets mapped to each inputs */ /* Find all the nets mapped to each inputs */
std::vector<AtomNetId> input_nets; std::vector<AtomNetId> input_nets;
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[0]; ++ipin) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) {
input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[0][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 */ /* Find all the nets mapped to each outputs */
for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { 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) { 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]); 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); AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin);
/* Bypass unmapped pins */ /* Bypass unmapped pins */
if (AtomNetId::INVALID() == output_net) { 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)); VTR_ASSERT(true == atom_ctx.nlist.valid_block_id(atom_blk));
const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk); const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk);
std::vector<int> rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, pb_graph_node); std::vector<int> 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); adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map);
} }

View File

@ -368,4 +368,54 @@ CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circu
return enb_port; 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<CircuitPortId> 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<CircuitPortId> 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<CircuitPortId> 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<CircuitPortId> 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 */ } /* end namespace openfpga */

View File

@ -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, CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model); const CircuitModelId& circuit_model);
std::vector<CircuitPortId> 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<CircuitPortId> 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 */ } /* end namespace openfpga */
#endif #endif