diff --git a/openfpga/src/repack/physical_pb.cpp b/openfpga/src/repack/physical_pb.cpp index 1b3760dcc..647c527af 100644 --- a/openfpga/src/repack/physical_pb.cpp +++ b/openfpga/src/repack/physical_pb.cpp @@ -36,6 +36,17 @@ PhysicalPbId PhysicalPb::parent(const PhysicalPbId& pb) const { return parent_pbs_[pb]; } +AtomNetId PhysicalPb::pb_graph_pin_atom_net(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin) const { + VTR_ASSERT(true == valid_pb_id(pb)); + if (pin_atom_nets_[pb].find(pb_graph_pin) != pin_atom_nets_[pb].end()) { + /* Find it, return the id */ + return pin_atom_nets_[pb].at(pb_graph_pin); + } + /* Not found, return an invalid id */ + return AtomNetId::INVALID(); +} + /****************************************************************************** * Private Mutators ******************************************************************************/ @@ -53,9 +64,12 @@ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) { /* Allocate other attributes */ names_.emplace_back(); pb_graph_nodes_.push_back(pb_graph_node); - mapped_atoms_.emplace_back(); + atom_blocks_.emplace_back(); + pin_atom_nets_.emplace_back(); + child_pbs_.emplace_back(); parent_pbs_.emplace_back(); + mode_bits_.emplace_back(); /* Register in the name2id map */ @@ -82,6 +96,34 @@ void PhysicalPb::add_child(const PhysicalPbId& parent, parent_pbs_[child] = parent; } +void PhysicalPb::set_mode_bits(const PhysicalPbId& pb, + const std::vector& mode_bits) { + VTR_ASSERT(true == valid_pb_id(pb)); + + mode_bits_[pb] = mode_bits; +} + +void PhysicalPb::add_atom_block(const PhysicalPbId& pb, + const AtomBlockId& atom_block) { + VTR_ASSERT(true == valid_pb_id(pb)); + + atom_blocks_[pb].push_back(atom_block); +} + +void PhysicalPb::set_pb_graph_pin_atom_net(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin, + const AtomNetId& atom_net) { + VTR_ASSERT(true == valid_pb_id(pb)); + if (pin_atom_nets_[pb].end() != pin_atom_nets_[pb].find(pb_graph_pin)) { + VTR_LOG_WARN("Overwrite pb_graph_pin '%s[%d]' atom net '%lu' with '%lu'\n", + pb_graph_pin->port->name, pb_graph_pin->pin_number, + size_t(pin_atom_nets_[pb][pb_graph_pin]), + size_t(atom_net)); + } + + pin_atom_nets_[pb][pb_graph_pin] = atom_net; +} + /****************************************************************************** * Private validators/invalidators ******************************************************************************/ diff --git a/openfpga/src/repack/physical_pb.h b/openfpga/src/repack/physical_pb.h index 8a9d3b20d..9e4dff206 100644 --- a/openfpga/src/repack/physical_pb.h +++ b/openfpga/src/repack/physical_pb.h @@ -42,11 +42,20 @@ class PhysicalPb { std::string name(const PhysicalPbId& pb) const; PhysicalPbId find_pb(const t_pb_graph_node* name) const; PhysicalPbId parent(const PhysicalPbId& pb) const; + AtomNetId pb_graph_pin_atom_net(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin) const; public: /* Public mutators */ PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node); void add_child(const PhysicalPbId& parent, const PhysicalPbId& child, const t_pb_type* child_type); + void add_atom_block(const PhysicalPbId& pb, + const AtomBlockId& atom_block); + void set_mode_bits(const PhysicalPbId& pb, + const std::vector& mode_bits); + void set_pb_graph_pin_atom_net(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin, + const AtomNetId& atom_net); public: /* Public validators/invalidators */ bool valid_pb_id(const PhysicalPbId& pb_id) const; bool empty() const; @@ -54,7 +63,8 @@ class PhysicalPb { vtr::vector pb_ids_; vtr::vector pb_graph_nodes_; vtr::vector names_; - vtr::vector> mapped_atoms_; + vtr::vector> atom_blocks_; + vtr::vector> pin_atom_nets_; /* Child pbs are organized as [0..num_child_pb_types-1][0..child_pb_type->num_pb-1] */ vtr::vector>> child_pbs_; diff --git a/openfpga/src/repack/repack.cpp b/openfpga/src/repack/repack.cpp index 578efd91f..e4df2986d 100644 --- a/openfpga/src/repack/repack.cpp +++ b/openfpga/src/repack/repack.cpp @@ -242,8 +242,7 @@ void add_lb_router_nets(LbRouter& lb_router, * - Output routing results to data structure PhysicalPb and store it in clustering annotation ***************************************************************************************/ static -void repack_cluster(const DeviceContext& device_ctx, - const AtomContext& atom_ctx, +void repack_cluster(const AtomContext& atom_ctx, const ClusteringContext& clustering_ctx, const VprDeviceAnnotation& device_annotation, VprClusteringAnnotation& clustering_annotation, @@ -288,7 +287,13 @@ void repack_cluster(const DeviceContext& device_ctx, /* Annotate routing results to physical pb */ PhysicalPb phy_pb; alloc_physical_pb_from_pb_graph(phy_pb, pb_graph_head, device_annotation); - rec_update_physical_pb_from_operating_pb(phy_pb, clustering_ctx.clb_nlist.block_pb(block_id)); + rec_update_physical_pb_from_operating_pb(phy_pb, + clustering_ctx.clb_nlist.block_pb(block_id), + clustering_ctx.clb_nlist.block_pb(block_id)->pb_route, + atom_ctx, + device_annotation); + /* TODO: save routing results */ + VTR_LOGV(verbose, "Saved results in physical pb\n"); /* Add the pb to clustering context */ clustering_annotation.add_physical_pb(block_id, phy_pb); @@ -300,8 +305,7 @@ void repack_cluster(const DeviceContext& device_ctx, * Repack each clustered blocks in the clustering context ***************************************************************************************/ static -void repack_clusters(const DeviceContext& device_ctx, - const AtomContext& atom_ctx, +void repack_clusters(const AtomContext& atom_ctx, const ClusteringContext& clustering_ctx, const VprDeviceAnnotation& device_annotation, VprClusteringAnnotation& clustering_annotation, @@ -309,7 +313,7 @@ void repack_clusters(const DeviceContext& device_ctx, vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile"); for (auto blk_id : clustering_ctx.clb_nlist.blocks()) { - repack_cluster(device_ctx, atom_ctx, clustering_ctx, + repack_cluster(atom_ctx, clustering_ctx, device_annotation, clustering_annotation, blk_id, verbose); } @@ -338,7 +342,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx, verbose); /* Call the LbRouter to re-pack each clustered block to physical implementation */ - repack_clusters(device_ctx, atom_ctx, clustering_ctx, + repack_clusters(atom_ctx, clustering_ctx, const_cast(device_annotation), clustering_annotation, verbose); } diff --git a/openfpga/src/utils/physical_pb_utils.cpp b/openfpga/src/utils/physical_pb_utils.cpp index 9502df674..ec668a7d3 100644 --- a/openfpga/src/utils/physical_pb_utils.cpp +++ b/openfpga/src/utils/physical_pb_utils.cpp @@ -21,7 +21,7 @@ namespace openfpga { ***********************************************************************/ static void rec_alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, - t_pb_graph_node* pb_graph_node, + const t_pb_graph_node* pb_graph_node, const VprDeviceAnnotation& device_annotation) { t_pb_type* pb_type = pb_graph_node->pb_type; @@ -57,7 +57,7 @@ void rec_alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, ***********************************************************************/ static void rec_build_physical_pb_children_from_pb_graph(PhysicalPb& phy_pb, - t_pb_graph_node* pb_graph_node, + const t_pb_graph_node* pb_graph_node, const VprDeviceAnnotation& device_annotation) { t_pb_type* pb_type = pb_graph_node->pb_type; @@ -101,7 +101,7 @@ void rec_build_physical_pb_children_from_pb_graph(PhysicalPb& phy_pb, * VTR_ASSERT(true == phy_pb.empty()); ***********************************************************************/ void alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, - t_pb_graph_node* pb_graph_head, + const t_pb_graph_node* pb_graph_head, const VprDeviceAnnotation& device_annotation) { VTR_ASSERT(true == phy_pb.empty()); @@ -109,11 +109,164 @@ void alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, rec_build_physical_pb_children_from_pb_graph(phy_pb, pb_graph_head, device_annotation); } +/************************************************************************ + * Update a mapping net from a pin of an operating primitive pb to a + * physical pb data base + ***********************************************************************/ +static +void update_primitive_physical_pb_pin_atom_net(PhysicalPb& phy_pb, + const PhysicalPbId& primitive_pb, + const t_pb_graph_pin* pb_graph_pin, + const t_pb_routes& pb_route, + const VprDeviceAnnotation& device_annotation) { + int node_index = pb_graph_pin->pin_count_in_cluster; + if (pb_route.count(node_index)) { + /* The pin is mapped to a net, find the original pin in the atom netlist */ + AtomNetId atom_net = pb_route[node_index].atom_net_id; + + VTR_ASSERT(atom_net); + + /* Find the physical pb_graph_pin */ + t_pb_graph_pin* physical_pb_graph_pin = device_annotation.physical_pb_graph_pin((t_pb_graph_pin*)pb_graph_pin); + VTR_ASSERT(nullptr != physical_pb_graph_pin); + + /* Check if the pin has been mapped to a net. + * If yes, the atom net must be the same + */ + if (AtomNetId::INVALID() == phy_pb.pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin)) { + phy_pb.set_pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin, atom_net); + } else { + VTR_ASSERT(atom_net == phy_pb.pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin)); + } + } +} + +/************************************************************************ + * Synchronize mapping nets from an operating primitive pb to a physical pb + ***********************************************************************/ +static +void synchronize_primitive_physical_pb_atom_nets(PhysicalPb& phy_pb, + const PhysicalPbId& primitive_pb, + const t_pb_graph_node* pb_graph_node, + const t_pb_routes& pb_route, + const AtomContext& atom_ctx, + const AtomBlockId& atom_blk, + const VprDeviceAnnotation& device_annotation) { + /* Iterate over all the ports: input, output and clock */ + 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) { + /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ + t_model_ports* model_port = pb_graph_node->input_pins[iport][ipin].port->model_port; + if (nullptr == model_port) { + continue; + } + + AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, model_port); + if (!atom_port) { + continue; + } + /* Find the atom nets mapped to the pin + * Note that some inputs may not be used, we set them to be open by default + */ + update_primitive_physical_pb_pin_atom_net(phy_pb, primitive_pb, + &(pb_graph_node->input_pins[iport][ipin]), + pb_route, device_annotation); + } + } + + 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) { + /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ + t_model_ports* model_port = pb_graph_node->output_pins[iport][ipin].port->model_port; + if (nullptr == model_port) { + continue; + } + + AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, model_port); + if (!atom_port) { + continue; + } + /* Find the atom nets mapped to the pin + * Note that some inputs may not be used, we set them to be open by default + */ + update_primitive_physical_pb_pin_atom_net(phy_pb, primitive_pb, + &(pb_graph_node->output_pins[iport][ipin]), + pb_route, device_annotation); + } + } + + for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { + /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ + t_model_ports* model_port = pb_graph_node->clock_pins[iport][ipin].port->model_port; + if (nullptr == model_port) { + continue; + } + + AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, model_port); + if (!atom_port) { + continue; + } + /* Find the atom nets mapped to the pin + * Note that some inputs may not be used, we set them to be open by default + */ + update_primitive_physical_pb_pin_atom_net(phy_pb, primitive_pb, + &(pb_graph_node->clock_pins[iport][ipin]), + pb_route, device_annotation); + } + } +} + /************************************************************************ * Synchronize mapping results from an operating pb to a physical pb ***********************************************************************/ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, - t_pb* op_pb) { + const t_pb* op_pb, + const t_pb_routes& pb_route, + const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation) { + t_pb_graph_node* pb_graph_node = op_pb->pb_graph_node; + t_pb_type* pb_type = pb_graph_node->pb_type; + + if (true == is_primitive_pb_type(pb_type)) { + t_pb_graph_node* physical_pb_graph_node = device_annotation.physical_pb_graph_node(pb_graph_node); + VTR_ASSERT(nullptr != physical_pb_graph_node); + /* Find the physical pb */ + const PhysicalPbId& physical_pb = phy_pb.find_pb(physical_pb_graph_node); + VTR_ASSERT(true == phy_pb.valid_pb_id(physical_pb)); + + /* Set the mode bits */ + phy_pb.set_mode_bits(physical_pb, device_annotation.pb_type_mode_bits(physical_pb_graph_node->pb_type)); + + /* Find mapped atom block and add to this physical pb */ + AtomBlockId atom_blk = atom_ctx.nlist.find_block(op_pb->name); + VTR_ASSERT(atom_blk); + + phy_pb.add_atom_block(physical_pb, atom_blk); + + /* TODO: Iterate over ports and annotate the atom pins */ + synchronize_primitive_physical_pb_atom_nets(phy_pb, physical_pb, + pb_graph_node, + pb_route, + atom_ctx, atom_blk, + device_annotation); + return; + } + + /* Walk through the pb recursively but only visit the mapped modes and child pbs */ + t_mode* mapped_mode = &(pb_graph_node->pb_type->modes[op_pb->mode]); + for (int ipb = 0; ipb < mapped_mode->num_pb_type_children; ++ipb) { + /* Each child may exist multiple times in the hierarchy*/ + for (int jpb = 0; jpb < mapped_mode->pb_type_children[ipb].num_pb; ++jpb) { + if ((nullptr != op_pb->child_pbs[ipb]) && (nullptr != op_pb->child_pbs[ipb][jpb].name)) { + rec_update_physical_pb_from_operating_pb(phy_pb, + &(op_pb->child_pbs[ipb][jpb]), + pb_route, + atom_ctx, + device_annotation); + } + } + } } } /* end namespace openfpga */ diff --git a/openfpga/src/utils/physical_pb_utils.h b/openfpga/src/utils/physical_pb_utils.h index bdd37dc81..0e8bb71df 100644 --- a/openfpga/src/utils/physical_pb_utils.h +++ b/openfpga/src/utils/physical_pb_utils.h @@ -10,6 +10,7 @@ #include #include "physical_types.h" #include "vpr_device_annotation.h" +#include "vpr_context.h" #include "physical_pb.h" /******************************************************************** @@ -20,11 +21,14 @@ namespace openfpga { void alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, - t_pb_graph_node* pb_graph_head, + const t_pb_graph_node* pb_graph_head, const VprDeviceAnnotation& device_annotation); void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, - t_pb* op_pb); + const t_pb* op_pb, + const t_pb_routes& pb_route, + const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation); } /* end namespace openfpga */