diff --git a/doc/src/vpr/file_formats.rst b/doc/src/vpr/file_formats.rst index ac8c5b4503b..3fcad556dce 100644 --- a/doc/src/vpr/file_formats.rst +++ b/doc/src/vpr/file_formats.rst @@ -585,6 +585,14 @@ The io pad is set to inpad mode and is driven by the inpad: ... +.. note:: ``.net`` files may be outputted at two stages: + - After packing is completed, the packing results will be outputted. The ``.net`` file can be loaded as an input for placer, router and analyzer. Note that the file may **not** represent the final packing results as the analyzer will apply synchronization between packing and routing results. + - After analysis is completed, updated packing results will be outputted. This is due to that VPR router may swap pin mapping in packing results for optimizations. In such cases, packing results are synchronized with routing results. The outputted ``.net`` file will have a postfix of ``.post_routing`` as compared to the original packing results. It could happen that VPR router does not apply any pin swapping and the two ``.net`` files are the same. In both cases, the post-analysis ``.net`` file should be considered to be **the final packing results** for downstream tools, e.g., bitstream generator. Users may load the post-routing ``.net`` file in VPR's analysis flow to sign-off the final results. + +.. warning:: Currently, the packing result synchronization is only applicable to input pins which may be remapped to different nets during routing optimization. If your architecture defines `link_instance_pin_xml_syntax_` equivalence for output pins, the packing results still mismatch the routing results! + +.. _link_instance_pin_xml_syntax: https://docs.verilogtorouting.org/en/latest/arch/reference/#tag-%3Coutputname= + .. _vpr_place_file: Placement File Format (.place) diff --git a/vpr/src/base/netlist_writer.cpp b/vpr/src/base/netlist_writer.cpp index 4b8a9454e9b..5fd7503bfa2 100644 --- a/vpr/src/base/netlist_writer.cpp +++ b/vpr/src/base/netlist_writer.cpp @@ -1818,7 +1818,17 @@ class NetlistWriterVisitor : public NetlistVisitor { if (impl_input_net_id) { //If there is a valid net connected in the implementation AtomNetId logical_net_id = atom_ctx.nlist.port_net(port_id, orig_index); - VTR_ASSERT(impl_input_net_id == logical_net_id); + + // Fatal error should be flagged when the net marked in implementation + // does not match the net marked in input netlist + if (impl_input_net_id != logical_net_id) { + VPR_FATAL_ERROR(VPR_ERROR_IMPL_NETLIST_WRITER, + "Unmatch:\n\tlogical net is '%s' at pin '%lu'\n\timplmented net is '%s' at pin '%s'\n", + atom_ctx.nlist.net_name(logical_net_id).c_str(), + size_t(orig_index), + atom_ctx.nlist.net_name(impl_input_net_id).c_str(), + gpin->to_string().c_str()); + } //Mark the permutation. // The net originally located at orig_index in the atom netlist diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index ebdb28f6a2c..4f183bb114b 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -67,6 +67,7 @@ #include "constant_nets.h" #include "atom_netlist_utils.h" #include "cluster.h" +#include "output_clustering.h" #include "pack_report.h" #include "overuse_report.h" @@ -81,6 +82,8 @@ #include "arch_util.h" +#include "post_routing_pb_pin_fixup.h" + #include "log.h" #include "iostream" @@ -587,6 +590,10 @@ void vpr_load_packing(t_vpr_setup& vpr_setup, const t_arch& arch) { auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); + /* Ensure we have a clean start with void net remapping information */ + cluster_ctx.post_routing_clb_pin_nets.clear(); + cluster_ctx.pre_routing_net_pin_mapping.clear(); + cluster_ctx.clb_nlist = read_netlist(vpr_setup.FileNameOpts.NetFile.c_str(), &arch, vpr_setup.FileNameOpts.verify_file_digests, @@ -743,8 +750,6 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch) { } } - VTR_LOG("\n"); - //Echo files if (vpr_setup.Timing.timing_analysis_enabled) { if (isEchoFileEnabled(E_ECHO_FINAL_ROUTING_TIMING_GRAPH)) { @@ -1183,6 +1188,30 @@ bool vpr_analysis_flow(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteSt VTR_LOG("*****************************************************************************************\n"); } + /* If routing is successful, apply post-routing annotations + * - apply logic block pin fix-up + * + * Note: + * - Turn on verbose output when users require verbose output + * for packer (default verbosity is set to 2 for compact logs) + */ + if (route_status.success()) { + sync_netlists_to_routing(g_vpr_ctx.device(), + g_vpr_ctx.mutable_atom(), + g_vpr_ctx.mutable_clustering(), + g_vpr_ctx.placement(), + g_vpr_ctx.routing(), + vpr_setup.PackerOpts.pack_verbosity > 2); + + std::string post_routing_packing_output_file_name = vpr_setup.PackerOpts.output_file + ".post_routing"; + write_packing_results_to_xml(vpr_setup.PackerOpts.global_clocks, + Arch.architecture_id, + post_routing_packing_output_file_name.c_str()); + } else { + VTR_LOG_WARN("Sychronization between packing and routing results is not applied due to illegal circuit implementation\n"); + } + VTR_LOG("\n"); + vpr_analysis(vpr_setup, Arch, route_status); return true; diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 752c96cc331..7319604ff14 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -268,6 +268,16 @@ struct ClusteringContext : public Context { ///@brief New netlist class derived from Netlist ClusteredNetlist clb_nlist; + + /* Database for nets of each clb block pin after routing stage + * - post_routing_clb_pin_nets: + * mapping of pb_type pins to clustered net ids + * - pre_routing_net_pin_mapping: + * a copy of mapping for current pb_route index to previous pb_route index + * Record the previous pin mapping for finding the correct pin index during timing analysis + */ + std::map> post_routing_clb_pin_nets; + std::map> pre_routing_net_pin_mapping; }; /** diff --git a/vpr/src/base/vpr_types.cpp b/vpr/src/base/vpr_types.cpp index f28d9794efb..5ba8f4910f5 100644 --- a/vpr/src/base/vpr_types.cpp +++ b/vpr/src/base/vpr_types.cpp @@ -70,7 +70,7 @@ t_mode* t_pb::get_mode() const { } /** - * @brief Returns the t_pb associated with the specified gnode which is contained + * @brief Returns the read-only t_pb associated with the specified gnode which is contained * within the current pb */ const t_pb* t_pb::find_pb(const t_pb_graph_node* gnode) const { @@ -96,6 +96,33 @@ const t_pb* t_pb::find_pb(const t_pb_graph_node* gnode) const { return nullptr; //Not found } +/** + * @brief Returns the mutable t_pb associated with the specified gnode which is contained + * within the current pb + */ +t_pb* t_pb::find_mutable_pb(const t_pb_graph_node* gnode) { + //Base case + if (pb_graph_node == gnode) { + return this; + } + + //Search recursively + for (int ichild_type = 0; ichild_type < get_num_child_types(); ++ichild_type) { + if (child_pbs[ichild_type] == nullptr) continue; + + for (int ipb = 0; ipb < get_num_children_of_type(ichild_type); ++ipb) { + t_pb* child_pb = &child_pbs[ichild_type][ipb]; + + t_pb* found_pb = child_pb->find_mutable_pb(gnode); + if (found_pb != nullptr) { + VTR_ASSERT(found_pb->pb_graph_node == gnode); + return found_pb; //Found + } + } + } + return nullptr; //Not found +} + const t_pb* t_pb::find_pb_for_model(const std::string& blif_model) const { //Base case const t_model* model = pb_graph_node->pb_type->model; diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 00a215ee681..dbb37142bda 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -325,11 +325,17 @@ class t_pb { t_mode* get_mode() const; /** - * @brief Returns the t_pb associated with the specified gnode which is contained + * @brief Returns the read-only t_pb associated with the specified gnode which is contained * within the current pb */ const t_pb* find_pb(const t_pb_graph_node* gnode) const; + /** + * @brief Returns the mutable t_pb associated with the specified gnode which is contained + * within the current pb + */ + t_pb* find_mutable_pb(const t_pb_graph_node* gnode); + const t_pb* find_pb_for_model(const std::string& blif_model) const; ///@brief Returns the root pb containing this pb diff --git a/vpr/src/pack/output_clustering.cpp b/vpr/src/pack/output_clustering.cpp index dcc609772e5..51758041f9b 100644 --- a/vpr/src/pack/output_clustering.cpp +++ b/vpr/src/pack/output_clustering.cpp @@ -26,6 +26,7 @@ #include "output_clustering.h" #include "read_xml_arch_file.h" #include "vpr_utils.h" +#include "pack.h" #define LINELENGTH 1024 #define TAB_LENGTH 4 @@ -615,3 +616,26 @@ void output_clustering(const vtr::vector*> intra_lb_routing_placeholder; + std::unordered_set is_clock = alloc_and_load_is_clock(global_clocks); + + output_clustering(intra_lb_routing_placeholder, + global_clocks, + is_clock, + architecture_id, + out_fname, + false); +} diff --git a/vpr/src/pack/output_clustering.h b/vpr/src/pack/output_clustering.h index 214aa50155a..509690e4934 100644 --- a/vpr/src/pack/output_clustering.h +++ b/vpr/src/pack/output_clustering.h @@ -7,4 +7,6 @@ void output_clustering(const vtr::vector*>& intra_lb_routing, bool global_clocks, const std::unordered_set& is_clock, const std::string& architecture_id, const char* out_fname, bool skip_clustering); +void write_packing_results_to_xml(const bool& global_clocks, const std::string& architecture_id, const char* out_fname); + #endif diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 649b4ad2f0f..c048667fb65 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -26,7 +26,6 @@ /* #define DUMP_PB_GRAPH 1 */ /* #define DUMP_BLIF_INPUT 1 */ -static std::unordered_set alloc_and_load_is_clock(bool global_clocks); static bool try_size_device_grid(const t_arch& arch, const std::map& num_type_instances, float target_device_utilization, std::string device_layout_name); static t_ext_pin_util_targets parse_target_external_pin_util(std::vector specs); diff --git a/vpr/src/pack/pack.h b/vpr/src/pack/pack.h index f8ff31aaa8a..df99104512b 100644 --- a/vpr/src/pack/pack.h +++ b/vpr/src/pack/pack.h @@ -1,7 +1,9 @@ #ifndef PACK_H #define PACK_H #include +#include #include "vpr_types.h" +#include "atom_netlist_fwd.h" bool try_pack(t_packer_opts* packer_opts, const t_analysis_opts* analysis_opts, @@ -13,4 +15,6 @@ bool try_pack(t_packer_opts* packer_opts, float get_arch_switch_info(short switch_index, int switch_fanin, float& Tdel_switch, float& R_switch, float& Cout_switch); +std::unordered_set alloc_and_load_is_clock(bool global_clocks); + #endif diff --git a/vpr/src/pack/post_routing_pb_pin_fixup.cpp b/vpr/src/pack/post_routing_pb_pin_fixup.cpp new file mode 100644 index 00000000000..9d83880c9ea --- /dev/null +++ b/vpr/src/pack/post_routing_pb_pin_fixup.cpp @@ -0,0 +1,1081 @@ +/******************************************************************** + * This file includes functions to fix up the pb pin mapping results + * after routing optimization + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_time.h" +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "vpr_error.h" +#include "vpr_utils.h" +#include "rr_graph2.h" + +#include "annotate_routing.h" + +#include "post_routing_pb_pin_fixup.h" + +/* Include global variables of VPR */ +#include "globals.h" + +/******************************************************************** + * Give a given pin index, find the side where this pin is located + * on the physical tile + * Note: + * - Need to check if the pin_width_offset and pin_height_offset + * are properly set in VPR!!! + *******************************************************************/ +static std::vector find_physical_tile_pin_side(t_physical_tile_type_ptr physical_tile, + const int& physical_pin) { + std::vector pin_sides; + for (const e_side& side_cand : {TOP, RIGHT, BOTTOM, LEFT}) { + int pin_width_offset = physical_tile->pin_width_offset[physical_pin]; + int pin_height_offset = physical_tile->pin_height_offset[physical_pin]; + if (physical_tile->pinloc[pin_width_offset][pin_height_offset][side_cand][physical_pin]) { + pin_sides.push_back(side_cand); + } + } + + return pin_sides; +} + +/******************************************************************** + * Fix up the pb pin mapping results for a given clustered block + * 1. For each input/output pin of a clustered pb, + * - find a corresponding node in RRGraph object + * - find the net id for the node in routing context + * - find the net id for the node in clustering context + * - if the net id does not match, we update the clustering context + *******************************************************************/ +static void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ctx, + ClusteringContext& clustering_ctx, + const vtr::vector& rr_node_nets, + const vtr::Point& grid_coord, + const ClusterBlockId& blk_id, + const int& sub_tile_z, + size_t& num_mismatches, + const bool& verbose) { + /* Handle each pin */ + auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id); + auto physical_tile = device_ctx.grid[grid_coord.x()][grid_coord.y()].type; + + /* Narrow down side search for grids + * The wanted side depends on the location of the grid. + * In particular for perimeter grid, + * ------------------------------------------------------- + * Grid location | IPIN side + * ------------------------------------------------------- + * TOP | BOTTOM + * ------------------------------------------------------- + * RIGHT | LEFT + * ------------------------------------------------------- + * BOTTOM | TOP + * ------------------------------------------------------- + * LEFT | RIGHT + * ------------------------------------------------------- + * TOP-LEFT | BOTTOM & RIGHT + * ------------------------------------------------------- + * TOP-RIGHT | BOTTOM & LEFT + * ------------------------------------------------------- + * BOTTOM-LEFT | TOP & RIGHT + * ------------------------------------------------------- + * BOTTOM-RIGHT | TOP & LEFT + * ------------------------------------------------------- + */ + std::vector wanted_sides; + if (device_ctx.grid.height() - 1 == grid_coord.y()) { /* TOP side */ + wanted_sides.push_back(BOTTOM); + } + if (device_ctx.grid.width() - 1 == grid_coord.x()) { /* RIGHT side */ + wanted_sides.push_back(LEFT); + } + if (0 == grid_coord.y()) { /* BOTTOM side */ + wanted_sides.push_back(TOP); + } + if (0 == grid_coord.x()) { /* LEFT side */ + wanted_sides.push_back(RIGHT); + } + + /* If wanted sides is empty still, this block does not have specific wanted sides, + * Deposit all the sides + */ + if (wanted_sides.empty()) { + for (e_side side : {TOP, BOTTOM, LEFT, RIGHT}) { + wanted_sides.push_back(side); + } + } + + for (int pb_type_pin = 0; pb_type_pin < logical_block->pb_type->num_pins; ++pb_type_pin) { + /* Skip non-equivalent ports, no need to do fix-up */ + const t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(blk_id, pb_type_pin); + if (PortEquivalence::FULL != pb_graph_pin->port->equivalent) { + continue; + } + + /* Get the ptc num for the pin in rr_graph, we need to consider the sub tile offset here + * sub tile offset is the location in a sub tile whose capacity is larger than zero + */ + int physical_pin = get_post_placement_physical_pin(physical_tile, logical_block, sub_tile_z, pb_type_pin); + VTR_ASSERT(physical_pin < physical_tile->num_pins); + + auto pin_class = physical_tile->pin_class[physical_pin]; + auto class_inf = physical_tile->class_inf[pin_class]; + + t_rr_type rr_node_type; + if (class_inf.type == DRIVER) { + rr_node_type = OPIN; + } else { + VTR_ASSERT(class_inf.type == RECEIVER); + rr_node_type = IPIN; + } + + std::vector pinloc_sides = find_physical_tile_pin_side(physical_tile, physical_pin); + /* As some grid has height/width offset, we may not have the pin on any side */ + if (0 == pinloc_sides.size()) { + continue; + } + + /* Merge common part of the pin_sides and the wanted sides, + * which are sides we should iterate over + */ + std::vector pin_sides; + for (const e_side& pinloc_side : pinloc_sides) { + if (wanted_sides.end() != std::find(wanted_sides.begin(), wanted_sides.end(), pinloc_side)) { + pin_sides.push_back(pinloc_side); + } + } + /* We should have at least one side now after merging */ + VTR_ASSERT(!pin_sides.empty()); + + ClusterNetId routing_net_id = ClusterNetId::INVALID(); + std::vector visited_rr_nodes; + short valid_routing_net_cnt = 0; + for (const e_side& pin_side : pin_sides) { + /* Find the net mapped to this pin in routing results */ + const int& rr_node = get_rr_node_index(device_ctx.rr_node_indices, + grid_coord.x(), grid_coord.y(), + rr_node_type, physical_pin, pin_side); + + /* Bypass invalid nodes, after that we must have a valid rr_node id */ + if (OPEN == rr_node) { + continue; + } + VTR_ASSERT((size_t)rr_node < device_ctx.rr_nodes.size()); + + /* If the node has been visited on the other side, we just skip it */ + if (visited_rr_nodes.end() != std::find(visited_rr_nodes.begin(), visited_rr_nodes.end(), RRNodeId(rr_node))) { + continue; + } + + /* Get the cluster net id which has been mapped to this net + * In general, there is only one valid rr_node among all the sides. + * However, we have an exception in the Stratix-IV arch modeling, + * where a pb_pin may exist in two different sides but + * router will only map to 1 rr_node + * Therefore, it is better to compare the routing nets + * for all the sides and pick + * - The unique valid net id (others should be all invalid) + * assume that this pin is used by router + * - A invalid net id (others should be all invalid as well) + * assume that this pin is not used by router + */ + if (rr_node_nets[RRNodeId(rr_node)]) { + if (routing_net_id) { + if (routing_net_id != rr_node_nets[RRNodeId(rr_node)]) { + VTR_LOG_ERROR("Pin '%s' is mapped to two nets: '%s' and '%s'\n", + pb_graph_pin->to_string().c_str(), + clustering_ctx.clb_nlist.net_name(routing_net_id).c_str(), + clustering_ctx.clb_nlist.net_name(rr_node_nets[RRNodeId(rr_node)]).c_str()); + } + VTR_ASSERT(routing_net_id == rr_node_nets[RRNodeId(rr_node)]); + } + routing_net_id = rr_node_nets[RRNodeId(rr_node)]; + valid_routing_net_cnt++; + visited_rr_nodes.push_back(RRNodeId(rr_node)); + } + } + + VTR_ASSERT((0 == valid_routing_net_cnt) || (1 == valid_routing_net_cnt)); + + /* Find the net mapped to this pin in clustering results*/ + ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(blk_id, pb_type_pin); + + /* Ignore used in local cluster only, reserved one CLB pin */ + if ((clustering_ctx.clb_nlist.valid_net_id(cluster_net_id)) + && (0 == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size())) { + continue; + } + + /* If the net from the routing results matches the net from the packing results, + * nothing to be changed. Move on to the next net. + */ + if (routing_net_id == cluster_net_id) { + continue; + } + + /* Update the clustering context with net modification */ + clustering_ctx.post_routing_clb_pin_nets[blk_id][pb_graph_pin->pin_count_in_cluster] = routing_net_id; + + std::string routing_net_name("unmapped"); + if (clustering_ctx.clb_nlist.valid_net_id(routing_net_id)) { + routing_net_name = clustering_ctx.clb_nlist.net_name(routing_net_id); + } + + std::string cluster_net_name("unmapped"); + if (clustering_ctx.clb_nlist.valid_net_id(cluster_net_id)) { + cluster_net_name = clustering_ctx.clb_nlist.net_name(cluster_net_id); + } + + VTR_LOGV(verbose, + "Fixed up net '%s' mapping mismatch at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' (was net '%s')\n", + routing_net_name.c_str(), + clustering_ctx.clb_nlist.block_pb(blk_id)->name, + grid_coord.x(), grid_coord.y(), + clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number, + cluster_net_name.c_str()); + + /* Update counter */ + num_mismatches++; + } +} + +/******************************************************************** + * Find an unused pb_route from the other pins in this port + * The pb_route should be remapped to an invalid net, becoming unused + * at post routing stage. + * + * This function will return the first one we can find. + *******************************************************************/ +static int find_target_pb_route_from_equivalent_pins(const AtomContext& atom_ctx, + const ClusteringContext& clustering_ctx, + const ClusterBlockId& blk_id, + t_pb* pb, + const t_pb_graph_pin* source_pb_graph_pin, + const AtomNetId& target_net, + const bool& verbose) { + VTR_ASSERT(source_pb_graph_pin->parent_node->is_root()); + + std::vector pb_route_indices; + + for (int pb_type_pin = 0; pb_type_pin < pb->pb_graph_node->pb_type->num_pins; ++pb_type_pin) { + const t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(blk_id, pb_type_pin); + + if (PortEquivalence::FULL != pb_graph_pin->port->equivalent) { + continue; + } + + /* Limitation: bypass output pins now + * TODO: This is due to the 'instance' equivalence port + * where outputs may be swapped. This definitely requires re-run of packing + * It can not be solved by swapping routing traces now + */ + if (OUT_PORT == pb_graph_pin->port->type) { + continue; + } + + /* Sanity check to ensure the pb_graph_pin is the top-level */ + VTR_ASSERT(pb_graph_pin->parent_node == pb->pb_graph_node); + VTR_ASSERT(pb_graph_pin->parent_node->is_root()); + + int pin = pb_graph_pin->pin_count_in_cluster; + + /* Bypass unused pins */ + if ((0 == pb->pb_route.count(pin)) || (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) { + continue; + } + + auto remapped_result = clustering_ctx.post_routing_clb_pin_nets.at(blk_id).find(pin); + + /* Skip this pin if it is consistent in pre- and post- routing results */ + if (remapped_result == clustering_ctx.post_routing_clb_pin_nets.at(blk_id).end()) { + continue; + } + + /* Only care the pin has the same parent port as source_pb_pin */ + if (source_pb_graph_pin->port != pb->pb_route.at(pin).pb_graph_pin->port) { + continue; + } + + /* We can use the routing trace if it is mapped to the same net as the remapped result + */ + if (target_net == pb->pb_route.at(pin).atom_net_id) { + for (const int& sink_pb_route : pb->pb_route.at(pin).sink_pb_pin_ids) { + VTR_ASSERT(pb->pb_route.at(sink_pb_route).atom_net_id == target_net); + } + + pb_route_indices.push_back(pin); + } + } + + VTR_LOGV(verbose, + "Found %lu candidates to remap net '%s' at clustered block '%s' pin '%s'\n", + pb_route_indices.size(), + atom_ctx.nlist.net_name(target_net).c_str(), + clustering_ctx.clb_nlist.block_pb(blk_id)->name, + source_pb_graph_pin->to_string().c_str()); + + /* Should find at least 1 candidate */ + VTR_ASSERT(!pb_route_indices.empty()); + + return pb_route_indices[0]; +} + +/******************************************************************** + * Find an unused (unrouted) pb_graph_pin that is in the same port as the given pin + * NO optimization is done here!!! First find first fit + *******************************************************************/ +static const t_pb_graph_pin* find_unused_pb_graph_pin_in_the_same_port(const t_pb_graph_pin* pb_graph_pin, + const t_pb_routes& pb_routes, + const AtomNetId& mapped_net) { + /* If the current pb has the right pb_route, we can return it directly */ + if ((0 < pb_routes.count(pb_graph_pin->pin_count_in_cluster)) + && (mapped_net == pb_routes.at(pb_graph_pin->pin_count_in_cluster).atom_net_id)) { + return pb_graph_pin; + } + + /* Otherwise, we have to find an unused pin from the same port */ + for (int ipin = 0; ipin < pb_graph_pin->port->num_pins; ++ipin) { + const t_pb_graph_pin* candidate_pb_graph_pin = find_pb_graph_pin(pb_graph_pin->parent_node, std::string(pb_graph_pin->port->name), ipin); + int cand_pb_route_id = candidate_pb_graph_pin->pin_count_in_cluster; + + /* If unused, we find it */ + if (0 == pb_routes.count(cand_pb_route_id)) { + return candidate_pb_graph_pin; + } + /* If used but in the same net, we can reuse that */ + if (mapped_net == pb_routes.at(cand_pb_route_id).atom_net_id) { + return candidate_pb_graph_pin; + } + } + + /* Not found: Print debugging information */ + for (int ipin = 0; ipin < pb_graph_pin->port->num_pins; ++ipin) { + const t_pb_graph_pin* candidate_pb_graph_pin = find_pb_graph_pin(pb_graph_pin->parent_node, std::string(pb_graph_pin->port->name), ipin); + int cand_pb_route_id = candidate_pb_graph_pin->pin_count_in_cluster; + + VTR_LOG("\tCandidate pin: '%s'", + candidate_pb_graph_pin->to_string().c_str()); + + if (0 == pb_routes.count(cand_pb_route_id)) { + VTR_LOG("\tUnused\n"); + } else { + VTR_LOG("\tmapped to net '%s'\n", + g_vpr_ctx.atom().nlist.net_name(pb_routes.at(cand_pb_route_id).atom_net_id).c_str()); + } + } + + return nullptr; +} + +/******************************************************************** + * Identify if this pb_graph pin only drives 1 edge and the edge size is 1 + *******************************************************************/ +static bool is_single_fanout_pb_pin(const t_pb_graph_pin* pb_pin) { + return (1 == pb_pin->num_output_edges) && (1 == pb_pin->output_edges[0]->num_output_pins); +} + +/******************************************************************** + * Find the sink pb_graph_pin from a driver pb_graph_pin + * which is the only one used in the fan-outs of the driver pb_graph_pin! + *******************************************************************/ +static t_pb_graph_pin* find_used_sink_pb_pin(t_pb_graph_pin* driver_pb_pin, + const int& mode) { + t_pb_graph_pin* sink_pb_pin = nullptr; + int num_cand_pins = 0; + + for (int iedge = 0; iedge < driver_pb_pin->num_output_edges; ++iedge) { + if (mode != driver_pb_pin->output_edges[iedge]->interconnect->parent_mode_index) { + continue; + } + for (int ipin = 0; ipin < driver_pb_pin->output_edges[iedge]->num_output_pins; ++ipin) { + sink_pb_pin = driver_pb_pin->output_edges[iedge]->output_pins[ipin]; + num_cand_pins++; + } + } + + /* If we see multiple pins, we should return null pointer, as we only expect 1 pin to be found! */ + if (1 < num_cand_pins) { + return nullptr; + } + + return sink_pb_pin; +} + +/******************************************************************** + * Try to find the atom pin that is mapped to the sink pb_graph_pin + * which can be traced back through the pb routing tree + * + * Note: + * - This function assumes only 1 sink node to be found + * - All the pb_graph_pins in the routing tree should have only 1 fan-out + * in the selected mode! + * + * Top-level pb_type + * +---------------------------- + * | +------------------------ + * | | Primitive pb_type + * | | +------------------ + * | | | + * driver +---+---->| sink pb_pin <------> atom_pin + * pb_route | + * + *******************************************************************/ +static AtomPinId find_mapped_atom_pin(const AtomContext& atom_ctx, + const IntraLbPbPinLookup& intra_lb_pb_pin_lookup, + t_logical_block_type_ptr logical_type, + t_pb* pb, + const int& pb_route_id) { + /* Walk through the routing tree until we reach the end */ + int sink_pb_route_id = pb_route_id; + while (0 < pb->pb_route.count(sink_pb_route_id)) { + /* We will only care about single fan-out routing trees, + * their atom pin their could be remapped + * If multiple fan-out exist in the paths, + * return an invalid id showing not found! + */ + if (1 != pb->pb_route.at(sink_pb_route_id).sink_pb_pin_ids.size()) { + return AtomPinId::INVALID(); + } + sink_pb_route_id = pb->pb_route.at(sink_pb_route_id).sink_pb_pin_ids[0]; + if (pb->pb_route.at(sink_pb_route_id).sink_pb_pin_ids.empty()) { + break; + } + } + + const t_pb_graph_pin* sink_pb_pin = intra_lb_pb_pin_lookup.pb_gpin(logical_type->index, sink_pb_route_id); + const t_pb* leaf_pb = pb->find_pb(sink_pb_pin->parent_node); + const AtomPortId& atom_port = atom_ctx.nlist.find_atom_port(atom_ctx.lookup.pb_atom(leaf_pb), sink_pb_pin->port->model_port); + BitIndex atom_pin_bit_index = leaf_pb->atom_pin_bit_index(sink_pb_pin); + AtomPinId mapped_atom_pin = atom_ctx.nlist.port_pin(atom_port, atom_pin_bit_index); + + return mapped_atom_pin; +} + +/******************************************************************** + * Cache the mapping from atom pin to pb_graph pin for remapped nets + * in current routing traces + * + * Note: + * - The pb_route_id is the routing trace id for top-level pins ONLY! + * - This is only applicable to the following case: + * + * Top-level pb_type + * +---------------------------- + * | +------------------------ + * | | Primitive pb_type + * | | +------------------ + * | | | + * driver +---+---->| sink + * | + * + * + * Anything violates the assumption will be NOT be cached!!! + *******************************************************************/ +static std::map> cache_atom_pin_to_pb_pin_mapping(const AtomContext& atom_ctx, + const IntraLbPbPinLookup& intra_lb_pb_pin_lookup, + const ClusteringContext& clustering_ctx, + const ClusterBlockId& blk_id, + t_pb* pb, + t_logical_block_type_ptr logical_block) { + std::map> atom_pin_to_pb_pin_mapping; + for (int pb_type_pin = 0; pb_type_pin < logical_block->pb_type->num_pins; ++pb_type_pin) { + /* Skip non-equivalent ports, no need to do fix-up */ + const t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(blk_id, pb_type_pin); + if (PortEquivalence::FULL != pb_graph_pin->port->equivalent) { + continue; + } + + if (OUT_PORT == pb_graph_pin->port->type) { + continue; + } + + /* Sanity check to ensure the pb_graph_pin is the top-level */ + VTR_ASSERT(pb_graph_pin->parent_node == pb->pb_graph_node); + VTR_ASSERT(pb_graph_pin->parent_node->is_root()); + + auto remapped_result = clustering_ctx.post_routing_clb_pin_nets.at(blk_id).find(pb_graph_pin->pin_count_in_cluster); + + /* Skip this pin: it is consistent in pre- and post- routing results */ + if (remapped_result == clustering_ctx.post_routing_clb_pin_nets.at(blk_id).end()) { + continue; + } + + int pb_route_id = pb_graph_pin->pin_count_in_cluster; + auto pb_route_result = pb->pb_route.find(pb_route_id); + if (pb->pb_route.end() == pb_route_result) { + continue; + } + + /* Only cache for single fan-out routing trees */ + if (1 != pb_route_result->second.sink_pb_pin_ids.size()) { + continue; + } + + const AtomPinId& orig_mapped_atom_pin = find_mapped_atom_pin(atom_ctx, intra_lb_pb_pin_lookup, logical_block, pb, pb_route_id); + + /* Sometimes the routing traces is not what we target, skip caching */ + if (orig_mapped_atom_pin) { + atom_pin_to_pb_pin_mapping[pb_route_id] = std::make_pair(orig_mapped_atom_pin, atom_ctx.lookup.atom_pin_pb_graph_pin(orig_mapped_atom_pin)); + } + } + + return atom_pin_to_pb_pin_mapping; +} + +/******************************************************************** + * Spot the original pb_graph_pin that is mapped + * to a given net from the other equivalent pins in this port + *******************************************************************/ +static const t_pb_graph_pin* find_mapped_equivalent_pb_pin_by_net(t_pb* pb, + const t_pb_graph_pin* remapped_pb_pin, + const AtomNetId& atom_net_id) { + t_pb_graph_node* pb_graph_node = remapped_pb_pin->parent_node; + t_port* eq_port = remapped_pb_pin->port; + VTR_ASSERT(IN_PORT == eq_port->type); + + int cnt = 0; + const t_pb_graph_pin* found_pb_pin = nullptr; + + for (int ipin = 0; ipin < eq_port->num_pins; ++ipin) { + const t_pb_graph_pin* cand_pb_pin = &(pb_graph_node->input_pins[eq_port->port_index_by_type][ipin]); + VTR_ASSERT(eq_port == cand_pb_pin->port); + auto pb_route_result = pb->pb_route.find(cand_pb_pin->pin_count_in_cluster); + if (pb->pb_route.end() == pb_route_result) { + continue; + } + if (atom_net_id == pb_route_result->second.atom_net_id) { + found_pb_pin = cand_pb_pin; + cnt++; + } + } + + VTR_ASSERT(1 == cnt); + + return found_pb_pin; +} + +/******************************************************************** + * Recursively remove all the downstream pb_routes with a given starting point + * until reach the primitive nodes + *******************************************************************/ +static void rec_remove_downstream_pb_routes(t_pb_routes& curr_pb_routes, + const int& src_pb_route_id) { + for (const auto& sink_pb_route : curr_pb_routes.at(src_pb_route_id).sink_pb_pin_ids) { + /* Go recursively if this is not the end */ + rec_remove_downstream_pb_routes(curr_pb_routes, sink_pb_route); + /* Remove this sink */ + curr_pb_routes.erase(sink_pb_route); + } +} + +/******************************************************************** + * Update routing traces for regular nets of a logical block + * This function should NOT + * - create a routing traces but use the new routing traces + * from the inputs + * - modify any routing traces for global nets, + * which should be handled in another function!!! + *******************************************************************/ +static void update_cluster_regular_routing_traces_with_post_routing_results(AtomContext& atom_ctx, + const std::map>& previous_atom_pin_to_pb_pin_mapping, + ClusteringContext& clustering_ctx, + const ClusterBlockId& blk_id, + t_pb* pb, + t_logical_block_type_ptr logical_block, + t_pb_routes& new_pb_routes, + size_t& num_fixup, + const bool& verbose) { + /* Go through each pb_graph pin at the top level + * and build the new routing traces + */ + for (int pb_type_pin = 0; pb_type_pin < logical_block->pb_type->num_pins; ++pb_type_pin) { + /* Skip non-equivalent ports, no need to do fix-up */ + const t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(blk_id, pb_type_pin); + if (PortEquivalence::FULL != pb_graph_pin->port->equivalent) { + continue; + } + + /* Limitation: bypass output pins now + * TODO: This is due to the 'instance' equivalence port + * where outputs may be swapped. This definitely requires re-run of packing + * It can not be solved by swapping routing traces now + */ + if (OUT_PORT == pb_graph_pin->port->type) { + continue; + } + + /* Sanity check to ensure the pb_graph_pin is the top-level */ + VTR_ASSERT(pb_graph_pin->parent_node == pb->pb_graph_node); + VTR_ASSERT(pb_graph_pin->parent_node->is_root()); + + auto remapped_result = clustering_ctx.post_routing_clb_pin_nets.at(blk_id).find(pb_graph_pin->pin_count_in_cluster); + + /* Skip this pin: it is consistent in pre- and post- routing results */ + if (remapped_result == clustering_ctx.post_routing_clb_pin_nets.at(blk_id).end()) { + continue; + } + + /* Update only when there is a remapping! */ + VTR_ASSERT_SAFE(remapped_result != clustering_ctx.post_routing_clb_pin_nets[blk_id].end()); + + /* Cache the remapped net id */ + AtomNetId remapped_net = atom_ctx.lookup.atom_net(remapped_result->second); + + /* Skip those pins become unmapped after remapping */ + if (!remapped_net) { + /* Remove the invalid pb_route */ + ClusterNetId global_net_id = clustering_ctx.clb_nlist.block_net(blk_id, pb_type_pin); + if ((clustering_ctx.clb_nlist.valid_net_id(global_net_id)) + && (!clustering_ctx.clb_nlist.net_is_ignored(global_net_id))) { + /* Special: for single-fanout pin, remove all the downstream pb_routes */ + if (is_single_fanout_pb_pin(const_cast(pb_graph_pin))) { + rec_remove_downstream_pb_routes(new_pb_routes, pb_graph_pin->pin_count_in_cluster); + } else { + VTR_ASSERT_SAFE(!is_single_fanout_pb_pin(const_cast(pb_graph_pin))); + /* Now remove the source routing tree */ + new_pb_routes.erase(pb_graph_pin->pin_count_in_cluster); + } + } + continue; + } + + VTR_LOGV(verbose, + "Remapping routing trace for net '%s'\n", + atom_ctx.nlist.net_name(remapped_net).c_str()); + + /* Spot the routing trace + * Two conditions could happen: + * - There is already a routing trace for this pin: + * we just rename the net id + * - There is no routed path for this pin: + * we have to find a routing trace which is used by another pin + * in the same port (every pin in this port should be logic equivalent) + * Rename the net id and pb_graph_node pins + */ + int pb_route_id = find_target_pb_route_from_equivalent_pins(atom_ctx, + clustering_ctx, + blk_id, + pb, + pb_graph_pin, + remapped_net, + verbose); + + /* Record the previous pin mapping for finding the correct pin index during timing analysis */ + clustering_ctx.pre_routing_net_pin_mapping[blk_id][pb_graph_pin->pin_count_in_cluster] = pb_route_id; + + /* Remove the old pb_route and insert the new one */ + new_pb_routes.insert(std::make_pair(pb_graph_pin->pin_count_in_cluster, t_pb_route())); + t_pb_route& new_pb_route = new_pb_routes[pb_graph_pin->pin_count_in_cluster]; + + /* Deposit pb_route data from the reference */ + VTR_ASSERT(remapped_net == pb->pb_route.at(pb_route_id).atom_net_id); + new_pb_route.atom_net_id = pb->pb_route.at(pb_route_id).atom_net_id; + new_pb_route.pb_graph_pin = pb->pb_route.at(pb_route_id).pb_graph_pin; + new_pb_route.driver_pb_pin_id = pb->pb_route.at(pb_route_id).driver_pb_pin_id; + + /* Modify the source pb_graph_pin if we reuse routing trace from another pin */ + if (new_pb_route.pb_graph_pin != pb_graph_pin) { + new_pb_route.pb_graph_pin = pb_graph_pin; + new_pb_route.driver_pb_pin_id = OPEN; + } + + /* Check if the sink pb_pins are accessible from the driver pb_pin + * - If not accessible, remove the associated sink pin_pins + * - We will add the only accessible pin if and only if + * the driver pb_pin has only 1 fan-out according to the pb_graph + * + * Note: + * - This is applicable to the case where the driver pb_pin + * has only 1 fan-out!!! + * - This fix-up is mainly for the following pb_type organization + * + * Top-level pb_type + * +---------------------------- + * | +------------------------ + * | | Primitive pb_type + * | | +------------------ + * | | | + * driver +---+---->| sink + * | + * + * + * Anything violates the assumption will be errored out! + */ + new_pb_route.sink_pb_pin_ids.clear(); + std::map sink_pb_pin_accessibility; + t_pb_graph_pin* sink_pb_pin_to_add = nullptr; + + for (int iedge = 0; iedge < pb_graph_pin->num_output_edges; ++iedge) { + for (int ipin = 0; ipin < pb_graph_pin->output_edges[iedge]->num_output_pins; ++ipin) { + sink_pb_pin_accessibility[pb_graph_pin->output_edges[iedge]->output_pins[ipin]->pin_count_in_cluster] = true; + } + } + + if (is_single_fanout_pb_pin(const_cast(pb_graph_pin))) { + sink_pb_pin_to_add = pb_graph_pin->output_edges[0]->output_pins[0]; + } + + for (const int& sink_pb_route : pb->pb_route.at(pb_route_id).sink_pb_pin_ids) { + if (0 < sink_pb_pin_accessibility.count(sink_pb_route)) { + new_pb_route.sink_pb_pin_ids.push_back(sink_pb_route); + } + } + + /* Add the directly connected pin ONLY when there is no pin to add */ + if ((sink_pb_pin_to_add) + && (new_pb_route.sink_pb_pin_ids.empty())) { + new_pb_route.sink_pb_pin_ids.push_back(sink_pb_pin_to_add->pin_count_in_cluster); + } + + /* Since we modify the pb_route id at the top-level, + * update the children so that we maintain the correct links + * when back-tracing + */ + for (const int& sink_pb_route : new_pb_route.sink_pb_pin_ids) { + if (0 == new_pb_routes.count(sink_pb_route)) { + /* A new sink pb_pin requires a new pb_route to be added + * This could lead to a chain effect to add new pb_routes + * We keep adding the pb_pin until we reach a primitive pb_type + * All the sink pb_pin of the pb_route to be added + * must meet the following requirements + * so that the addition can be considered as legal: + * - It has only 1 fan-out + * + */ + VTR_ASSERT(sink_pb_route == sink_pb_pin_to_add->pin_count_in_cluster); + t_pb_graph_pin* new_sink_pb_pin_to_add = sink_pb_pin_to_add; + VTR_ASSERT(is_single_fanout_pb_pin(const_cast(new_sink_pb_pin_to_add))); + int new_driver_pb_pin = pb_graph_pin->pin_count_in_cluster; + while (1) { + int new_sink_pb_route_id = new_sink_pb_pin_to_add->pin_count_in_cluster; + new_pb_routes.insert(std::make_pair(new_sink_pb_route_id, t_pb_route())); + new_pb_routes[new_sink_pb_route_id].atom_net_id = remapped_net; + new_pb_routes[new_sink_pb_route_id].pb_graph_pin = new_sink_pb_pin_to_add; + new_pb_routes[new_sink_pb_route_id].driver_pb_pin_id = new_driver_pb_pin; + + /* Stop adding more routing tree when reach the primitive */ + if (new_sink_pb_pin_to_add->parent_node->is_primitive()) { + break; + } + + /* Go to the next level */ + const t_pb* sink_pb = pb->find_pb(new_sink_pb_pin_to_add->parent_node); + VTR_ASSERT(sink_pb); + t_pb_graph_pin* next_sink_pb_pin_to_add = find_used_sink_pb_pin(new_sink_pb_pin_to_add, sink_pb->mode); + VTR_ASSERT(next_sink_pb_pin_to_add); + + /* Assign sinks */ + new_pb_routes[new_sink_pb_route_id].sink_pb_pin_ids.push_back(next_sink_pb_pin_to_add->pin_count_in_cluster); + + /* Print verbose outputs */ + VTR_LOGV(verbose, + "Add a new trace '%d' linked to pin '%s' for net '%s'.\n", + new_sink_pb_route_id, + new_sink_pb_pin_to_add->to_string().c_str(), + atom_ctx.nlist.net_name(remapped_net).c_str()); + + /* Update the pins to add for next round */ + new_driver_pb_pin = new_sink_pb_pin_to_add->pin_count_in_cluster; + new_sink_pb_pin_to_add = next_sink_pb_pin_to_add; + } + /* The chain effect will lead to a remapping to atom net pins + * Fix the atom net lookup + */ + VTR_ASSERT(1 == pb->pb_route.at(pb_route_id).sink_pb_pin_ids.size()); + const AtomPinId& orig_mapped_atom_pin = previous_atom_pin_to_pb_pin_mapping.at(pb_route_id).first; + + /* Print verbose outputs */ + VTR_LOGV(verbose, + "Redirect atom pin '%lu' mapping from '%s' to '%s' for net '%s'.\n", + size_t(orig_mapped_atom_pin), + atom_ctx.lookup.atom_pin_pb_graph_pin(orig_mapped_atom_pin)->to_string().c_str(), + new_sink_pb_pin_to_add->to_string().c_str(), + atom_ctx.nlist.net_name(remapped_net).c_str()); + + /* Update the pin binding in atom netlist fast look-up */ + atom_ctx.lookup.set_atom_pin_pb_graph_pin(orig_mapped_atom_pin, new_sink_pb_pin_to_add); + VTR_ASSERT(new_sink_pb_pin_to_add == atom_ctx.lookup.atom_pin_pb_graph_pin(orig_mapped_atom_pin)); + + /* Update the pin rotation map */ + t_pb* atom_pb = pb->find_mutable_pb(new_sink_pb_pin_to_add->parent_node); + atom_pb->set_atom_pin_bit_index(new_sink_pb_pin_to_add, atom_ctx.nlist.pin_port_bit(orig_mapped_atom_pin)); + } else { + new_pb_routes[sink_pb_route].driver_pb_pin_id = pb_graph_pin->pin_count_in_cluster; + + /* It is possible that the sink pb_route was used by another net + * If so, we need to correct the net ids for all the downstream pb_routes + */ + if (remapped_net != new_pb_routes[sink_pb_route].atom_net_id) { + new_pb_routes[sink_pb_route].atom_net_id = remapped_net; + + const t_pb_graph_pin* sink_pb_pin = new_pb_routes[sink_pb_route].pb_graph_pin; + if (is_single_fanout_pb_pin(sink_pb_pin)) { + /* Try to find the leaf pb_graph pin in the routing trace */ + t_pb_graph_pin* next_pb_pin = const_cast(sink_pb_pin); + while (!next_pb_pin->parent_node->is_primitive()) { + /* Go to the next level */ + const t_pb* next_pb = pb->find_pb(next_pb_pin->parent_node); + VTR_ASSERT(next_pb); + next_pb_pin = find_used_sink_pb_pin(next_pb_pin, next_pb->mode); + VTR_ASSERT(next_pb_pin); + new_pb_routes[next_pb_pin->pin_count_in_cluster].atom_net_id = remapped_net; + } + + /* Since this routing trace was mapped to another net, + * we have to spot the original pb_graph_pin that is mapped + * to this net (from the other equivalent pins in this port) + * Then we can find out the atom pin that is linked to the remapped net + */ + const t_pb_graph_pin* orig_mapped_top_level_pb_pin = find_mapped_equivalent_pb_pin_by_net(pb, pb_graph_pin, remapped_net); + VTR_ASSERT(orig_mapped_top_level_pb_pin); + const AtomPinId& orig_mapped_atom_pin = previous_atom_pin_to_pb_pin_mapping.at(orig_mapped_top_level_pb_pin->pin_count_in_cluster).first; + + /* Print verbose outputs */ + VTR_LOGV(verbose, + "Redirect atom pin '%lu' mapping from '%s' to '%s' for net '%s'.\n", + size_t(orig_mapped_atom_pin), + atom_ctx.lookup.atom_pin_pb_graph_pin(orig_mapped_atom_pin)->to_string().c_str(), + next_pb_pin->to_string().c_str(), + atom_ctx.nlist.net_name(remapped_net).c_str()); + + /* Update the pin binding in atom netlist fast look-up */ + atom_ctx.lookup.set_atom_pin_pb_graph_pin(orig_mapped_atom_pin, next_pb_pin); + VTR_ASSERT(next_pb_pin == atom_ctx.lookup.atom_pin_pb_graph_pin(orig_mapped_atom_pin)); + + /* Update the pin rotation map */ + t_pb* atom_pb = pb->find_mutable_pb(next_pb_pin->parent_node); + atom_pb->set_atom_pin_bit_index(next_pb_pin, atom_ctx.nlist.pin_port_bit(orig_mapped_atom_pin)); + } + } + } + } + + VTR_LOGV(verbose, + "Remap clustered block '%s' routing trace[%d] to net '%s'\n", + clustering_ctx.clb_nlist.block_pb(blk_id)->name, + pb_graph_pin->pin_count_in_cluster, + atom_ctx.nlist.net_name(remapped_net).c_str()); + + /* Update fixup counter */ + num_fixup++; + } +} + +/******************************************************************** + * Update routing traces for global nets of a logical block + * This function should NOT + * - create a routing traces but use the new routing traces + * from the inputs + * - modify any routing traces for non-global nets, + * which should be handled in another function!!! + *******************************************************************/ +static void update_cluster_global_routing_traces_with_post_routing_results(const AtomContext& atom_ctx, + ClusteringContext& clustering_ctx, + const ClusterBlockId& blk_id, + t_pb* pb, + t_logical_block_type_ptr logical_block, + t_pb_routes& new_pb_routes, + size_t& num_fixup, + const bool& verbose) { + /* Reassign global nets to unused pins in the same port where they were mapped + * NO optimization is done here!!! First find first fit + */ + for (int pb_type_pin = 0; pb_type_pin < logical_block->pb_type->num_pins; ++pb_type_pin) { + const t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(blk_id, pb_type_pin); + + /* Limitation: bypass output pins now + * TODO: This is due to the 'instance' equivalence port + * where outputs may be swapped. This definitely requires re-run of packing + * It can not be solved by swapping routing traces now + */ + if (OUT_PORT == pb_graph_pin->port->type) { + continue; + } + + /* Sanity check to ensure the pb_graph_pin is the top-level */ + VTR_ASSERT(pb_graph_pin->parent_node == pb->pb_graph_node); + VTR_ASSERT(pb_graph_pin->parent_node->is_root()); + + /* Focus on global net only */ + ClusterNetId global_net_id = clustering_ctx.clb_nlist.block_net(blk_id, pb_type_pin); + if (!clustering_ctx.clb_nlist.valid_net_id(global_net_id)) { + continue; + } + if ((clustering_ctx.clb_nlist.valid_net_id(global_net_id)) + && (!clustering_ctx.clb_nlist.net_is_ignored(global_net_id))) { + continue; + } + + AtomNetId global_atom_net_id = atom_ctx.lookup.atom_net(global_net_id); + + auto remapped_result = clustering_ctx.post_routing_clb_pin_nets.at(blk_id).find(pb_graph_pin->pin_count_in_cluster); + + /* Skip this pin: it is consistent in pre- and post- routing results */ + if (remapped_result == clustering_ctx.post_routing_clb_pin_nets.at(blk_id).end()) { + continue; + } + + /* Update only when there is a remapping! */ + VTR_ASSERT_SAFE(remapped_result != clustering_ctx.post_routing_clb_pin_nets[blk_id].end()); + + VTR_LOGV(verbose, + "Remapping clustered block '%s' global net '%s' to unused pin as %s\r", + clustering_ctx.clb_nlist.block_pb(blk_id)->name, + atom_ctx.nlist.net_name(global_atom_net_id).c_str(), + pb_graph_pin->to_string().c_str()); + + const t_pb_graph_pin* unused_pb_graph_pin = find_unused_pb_graph_pin_in_the_same_port(pb_graph_pin, new_pb_routes, global_atom_net_id); + /* Must find one */ + VTR_ASSERT(nullptr != unused_pb_graph_pin); + /* Create a new pb_route and update sink pb_route */ + /* Remove the old pb_route and insert the new one */ + new_pb_routes.insert(std::make_pair(unused_pb_graph_pin->pin_count_in_cluster, t_pb_route())); + t_pb_route& new_pb_route = new_pb_routes[unused_pb_graph_pin->pin_count_in_cluster]; + + int pb_route_id = pb_graph_pin->pin_count_in_cluster; + /* Deposit pb_route data from the reference */ + VTR_ASSERT(global_atom_net_id == pb->pb_route.at(pb_route_id).atom_net_id); + new_pb_route.atom_net_id = pb->pb_route.at(pb_route_id).atom_net_id; + new_pb_route.pb_graph_pin = unused_pb_graph_pin; + new_pb_route.driver_pb_pin_id = pb->pb_route.at(pb_route_id).driver_pb_pin_id; + new_pb_route.sink_pb_pin_ids = pb->pb_route.at(pb_route_id).sink_pb_pin_ids; + + for (const int& sink_pb_route : new_pb_route.sink_pb_pin_ids) { + VTR_ASSERT(new_pb_routes.at(sink_pb_route).atom_net_id == global_atom_net_id); + new_pb_routes[sink_pb_route].driver_pb_pin_id = unused_pb_graph_pin->pin_count_in_cluster; + } + + /* Update the remapping nets for this global net */ + clustering_ctx.post_routing_clb_pin_nets[blk_id][unused_pb_graph_pin->pin_count_in_cluster] = global_net_id; + clustering_ctx.pre_routing_net_pin_mapping[blk_id][unused_pb_graph_pin->pin_count_in_cluster] = pb_route_id; + + VTR_LOGV(verbose, + "Remap clustered block '%s' global net '%s' to pin '%s'\n", + clustering_ctx.clb_nlist.block_pb(blk_id)->name, + atom_ctx.nlist.net_name(global_atom_net_id).c_str(), + unused_pb_graph_pin->to_string().c_str()); + + /* Update fixup counter */ + num_fixup++; + } +} + +/******************************************************************** + * Fix up routing traces for a given clustered block + * This function will directly update the nets of routing traces + * stored in the clustered block by considering the post-routing results + * + * Note: + * - This function should be called AFTER the function + * update_cluster_pin_with_post_routing_results() + *******************************************************************/ +static void update_cluster_routing_traces_with_post_routing_results(AtomContext& atom_ctx, + const IntraLbPbPinLookup& intra_lb_pb_pin_lookup, + ClusteringContext& clustering_ctx, + const ClusterBlockId& blk_id, + size_t& num_fixup, + const bool& verbose) { + /* Skip block where no remapping is applied */ + if (clustering_ctx.post_routing_clb_pin_nets.find(blk_id) == clustering_ctx.post_routing_clb_pin_nets.end()) { + return; + } + + t_pb* pb = clustering_ctx.clb_nlist.block_pb(blk_id); + auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id); + + /* Create a new set of pb routing traces */ + t_pb_routes new_pb_routes = pb->pb_route; + + /* Cache the current mapping between atom pin to pb_graph pin in this block */ + std::map> previous_atom_pin_to_pb_pin_mapping = cache_atom_pin_to_pb_pin_mapping(const_cast(atom_ctx), intra_lb_pb_pin_lookup, const_cast(clustering_ctx), blk_id, pb, logical_block); + + update_cluster_regular_routing_traces_with_post_routing_results(atom_ctx, + previous_atom_pin_to_pb_pin_mapping, + clustering_ctx, + blk_id, + pb, + logical_block, + new_pb_routes, + num_fixup, + verbose); + + update_cluster_global_routing_traces_with_post_routing_results(const_cast(atom_ctx), + clustering_ctx, + blk_id, + pb, + logical_block, + new_pb_routes, + num_fixup, + verbose); + + /* Replace old pb_routes with the new one */ + pb->pb_route = new_pb_routes; +} + +/******************************************************************** + * Top-level function to synchronize a packed netlist to routing results + * The problem comes from a mismatch between the packing and routing results + * When there are equivalent input/output for any grids, router will try + * to swap the net mapping among these pins so as to achieve best + * routing optimization. + * However, it will cause the packing results out-of-date as the net mapping + * of each grid remain untouched once packing is done. + * This function aims to fix the mess after routing so that the net mapping + * can be synchronized + * + * Note: + * - This function SHOULD be run ONLY when routing is finished!!! + *******************************************************************/ +void sync_netlists_to_routing(const DeviceContext& device_ctx, + AtomContext& atom_ctx, + ClusteringContext& clustering_ctx, + const PlacementContext& placement_ctx, + const RoutingContext& routing_ctx, + const bool& verbose) { + vtr::ScopedStartFinishTimer timer("Synchronize the packed netlist to routing optimization"); + + /* Reset the database for post-routing clb net mapping */ + clustering_ctx.post_routing_clb_pin_nets.clear(); + clustering_ctx.pre_routing_net_pin_mapping.clear(); + + /* Create net-to-rr_node mapping */ + vtr::vector rr_node_nets = annotate_rr_node_nets(device_ctx, + clustering_ctx, + routing_ctx, + verbose); + + IntraLbPbPinLookup intra_lb_pb_pin_lookup(device_ctx.logical_block_types); + + /* Count the number of mismatches and fix-up */ + size_t num_mismatches = 0; + size_t num_fixup = 0; + + /* Update the core logic (center blocks of the FPGA) */ + for (const ClusterBlockId& cluster_blk_id : clustering_ctx.clb_nlist.blocks()) { + /* We know the entrance to grid info and mapping results, do the fix-up for this block */ + vtr::Point grid_coord(placement_ctx.block_locs[cluster_blk_id].loc.x, + placement_ctx.block_locs[cluster_blk_id].loc.y); + + update_cluster_pin_with_post_routing_results(device_ctx, + clustering_ctx, + rr_node_nets, + grid_coord, cluster_blk_id, + placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, + num_mismatches, + verbose); + update_cluster_routing_traces_with_post_routing_results(atom_ctx, + intra_lb_pb_pin_lookup, + clustering_ctx, + cluster_blk_id, + num_fixup, + verbose); + } + + /* Print a short summary */ + VTR_LOG("Found %lu mismatches between routing and packing results.\n", + num_mismatches); + VTR_LOG("Fixed %lu routing traces due to mismatch between routing and packing results.\n", + num_fixup); +} diff --git a/vpr/src/pack/post_routing_pb_pin_fixup.h b/vpr/src/pack/post_routing_pb_pin_fixup.h new file mode 100644 index 00000000000..bd613b94e9e --- /dev/null +++ b/vpr/src/pack/post_routing_pb_pin_fixup.h @@ -0,0 +1,19 @@ +#ifndef POST_ROUTING_PB_PIN_FIXUP_H +#define POST_ROUTING_PB_PIN_FIXUP_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "vpr_context.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +void sync_netlists_to_routing(const DeviceContext& device_ctx, + AtomContext& atom_ctx, + ClusteringContext& clustering_ctx, + const PlacementContext& placement_ctx, + const RoutingContext& routing_ctx, + const bool& verbose); + +#endif diff --git a/vpr/src/route/annotate_routing.cpp b/vpr/src/route/annotate_routing.cpp new file mode 100644 index 00000000000..cf391ca761e --- /dev/null +++ b/vpr/src/route/annotate_routing.cpp @@ -0,0 +1,73 @@ +/******************************************************************** + * This file includes functions that are used to annotate routing results + * from VPR to OpenFPGA + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_time.h" +#include "vtr_log.h" + +#include "vpr_error.h" +#include "rr_graph.h" +#include "annotate_routing.h" + +/******************************************************************** + * Create a mapping between each rr_node and its mapped nets + * based on VPR routing results + * - Store the net ids mapped to each routing resource nodes + * - Mapped nodes should have valid net ids (except SOURCE and SINK nodes) + * - Unmapped rr_node will use invalid ids + *******************************************************************/ +vtr::vector annotate_rr_node_nets(const DeviceContext& device_ctx, + const ClusteringContext& clustering_ctx, + const RoutingContext& routing_ctx, + const bool& verbose) { + size_t counter = 0; + vtr::ScopedStartFinishTimer timer("Annotating rr_node with routed nets"); + + vtr::vector rr_node_nets; + rr_node_nets.resize(device_ctx.rr_nodes.size(), ClusterNetId::INVALID()); + + for (auto net_id : clustering_ctx.clb_nlist.nets()) { + if (clustering_ctx.clb_nlist.net_is_ignored(net_id)) { + continue; + } + + /* Ignore used in local cluster only, reserved one CLB pin */ + if (clustering_ctx.clb_nlist.net_sinks(net_id).empty()) { + continue; + } + t_trace* tptr = routing_ctx.trace[net_id].head; + while (tptr != nullptr) { + const RRNodeId& rr_node = RRNodeId(tptr->index); + /* Ignore source and sink nodes, they are the common node multiple starting and ending points */ + if ((SOURCE != device_ctx.rr_nodes.node_type(rr_node)) + && (SINK != device_ctx.rr_nodes.node_type(rr_node))) { + /* Sanity check: ensure we do not revoke any net mapping + * In some routing architectures, node capacity is more than 1 + * which allows a node to be mapped by multiple nets + * Therefore, the sanity check should focus on the nodes + * whose capacity is 1 + */ + if ((rr_node_nets[rr_node]) + && (1 == device_ctx.rr_nodes.node_capacity(rr_node)) + && (net_id != rr_node_nets[rr_node])) { + VPR_FATAL_ERROR(VPR_ERROR_ANALYSIS, + "Detect two nets '%s' and '%s' that are mapped to the same rr_node '%ld'!\n%s\n", + clustering_ctx.clb_nlist.net_name(net_id).c_str(), + clustering_ctx.clb_nlist.net_name(rr_node_nets[rr_node]).c_str(), + size_t(rr_node), + describe_rr_node((int)size_t(rr_node)).c_str()); + } else { + rr_node_nets[rr_node] = net_id; + } + counter++; + } + tptr = tptr->next; + } + } + + VTR_LOGV(verbose, "Done with %d nodes mapping\n", counter); + + return rr_node_nets; +} diff --git a/vpr/src/route/annotate_routing.h b/vpr/src/route/annotate_routing.h new file mode 100644 index 00000000000..6f5345ae62b --- /dev/null +++ b/vpr/src/route/annotate_routing.h @@ -0,0 +1,18 @@ +#ifndef ANNOTATE_ROUTING_H +#define ANNOTATE_ROUTING_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "vpr_context.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +vtr::vector annotate_rr_node_nets(const DeviceContext& device_ctx, + const ClusteringContext& clustering_ctx, + const RoutingContext& routing_ctx, + const bool& verbose); + +#endif diff --git a/vpr/src/timing/clb_delay_calc.inl b/vpr/src/timing/clb_delay_calc.inl index cabf04b620b..67524a82f7b 100644 --- a/vpr/src/timing/clb_delay_calc.inl +++ b/vpr/src/timing/clb_delay_calc.inl @@ -104,7 +104,12 @@ inline const t_pb_graph_edge* ClbDelayCalc::find_pb_graph_edge(const t_pb_graph_ } } - VTR_ASSERT_MSG(pb_edge, "Should find pb_graph_edge connecting PB pins"); + + if (!pb_edge) { + std::string conkt_debug_message = "Should find pb_graph_edge connecting PB pins from " + driver->to_string() + " to " + sink->to_string() + "!\n"; + VTR_ASSERT_MSG(pb_edge, + conkt_debug_message.c_str()); + } return pb_edge; } diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 58d9a31059b..a2f0909d2b9 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -587,6 +587,7 @@ std::tuple find_pb_route_clb_input_net_pin(ClusterBlockI //Walk back from the sink to the CLB input pin int curr_pb_pin_id = sink_pb_pin_id; int next_pb_pin_id = pb_routes[curr_pb_pin_id].driver_pb_pin_id; + while (next_pb_pin_id >= 0) { //Advance back towards the input curr_pb_pin_id = next_pb_pin_id; @@ -606,7 +607,18 @@ std::tuple find_pb_route_clb_input_net_pin(ClusterBlockI //curr_pb_pin should be a top-level CLB input ClusterNetId clb_net_idx = cluster_ctx.clb_nlist.block_net(clb, curr_pb_pin_id); int clb_net_pin_idx = cluster_ctx.clb_nlist.block_pin_net_index(clb, curr_pb_pin_id); - VTR_ASSERT(clb_net_idx != ClusterNetId::INVALID()); + + /* The net could be remapped, we should verify the remapped location */ + auto remapped_clb = cluster_ctx.post_routing_clb_pin_nets.find(clb); + if (remapped_clb != cluster_ctx.post_routing_clb_pin_nets.end()) { + auto remapped_result = remapped_clb->second.find(curr_pb_pin_id); + if ((remapped_result != remapped_clb->second.end()) + && (remapped_result->second != clb_net_idx)) { + clb_net_idx = remapped_result->second; + VTR_ASSERT(clb_net_idx); + clb_net_pin_idx = cluster_ctx.clb_nlist.block_pin_net_index(clb, cluster_ctx.pre_routing_net_pin_mapping.at(clb).at(curr_pb_pin_id)); + } + } VTR_ASSERT(clb_net_pin_idx >= 0); return std::tuple(clb_net_idx, curr_pb_pin_id, clb_net_pin_idx); @@ -2267,27 +2279,90 @@ int get_sub_tile_physical_pin(int sub_tile_index, return result->second.pin; } +int get_logical_block_physical_sub_tile_index(t_physical_tile_type_ptr physical_tile, + t_logical_block_type_ptr logical_block) { + int sub_tile_index = OPEN; + for (const auto& sub_tile : physical_tile->sub_tiles) { + auto eq_sites = sub_tile.equivalent_sites; + auto it = std::find(eq_sites.begin(), eq_sites.end(), logical_block); + if (it != eq_sites.end()) { + sub_tile_index = sub_tile.index; + } + } + + if (sub_tile_index == OPEN) { + VPR_ERROR(VPR_ERROR_OTHER, + "Found no instances of logical block type '%s' within physical tile type '%s'. ", + logical_block->name, physical_tile->name); + } + + return sub_tile_index; +} + int get_physical_pin(t_physical_tile_type_ptr physical_tile, t_logical_block_type_ptr logical_block, int pin) { + int sub_tile_index = get_logical_block_physical_sub_tile_index(physical_tile, logical_block); + + if (sub_tile_index == OPEN) { + VPR_ERROR(VPR_ERROR_OTHER, + "Couldn't find the corresponding physical tile type pin of the logical block type pin %d.", + pin); + } + + int sub_tile_physical_pin = get_sub_tile_physical_pin(sub_tile_index, physical_tile, logical_block, pin); + return physical_tile->sub_tiles[sub_tile_index].sub_tile_to_tile_pin_indices[sub_tile_physical_pin]; +} + +int get_logical_block_physical_sub_tile_index(t_physical_tile_type_ptr physical_tile, + t_logical_block_type_ptr logical_block, + int sub_tile_capacity) { int sub_tile_index = OPEN; for (const auto& sub_tile : physical_tile->sub_tiles) { auto eq_sites = sub_tile.equivalent_sites; auto it = std::find(eq_sites.begin(), eq_sites.end(), logical_block); - if (it != eq_sites.end()) { + if (it != eq_sites.end() + && (sub_tile.capacity.is_in_range(sub_tile_capacity))) { sub_tile_index = sub_tile.index; + break; } } if (sub_tile_index == OPEN) { VPR_ERROR(VPR_ERROR_OTHER, - "Found no instances of logical block type '%s' within physical tile type '%s'. " + "Found no instances of logical block type '%s' within physical tile type '%s'. ", + logical_block->name, physical_tile->name); + } + + return sub_tile_index; +} + +int get_post_placement_physical_pin(t_physical_tile_type_ptr physical_tile, + t_logical_block_type_ptr logical_block, + int sub_tile_capacity, + int pin) { + int sub_tile_index = get_logical_block_physical_sub_tile_index(physical_tile, logical_block, sub_tile_capacity); + + if (sub_tile_index == OPEN) { + VPR_ERROR(VPR_ERROR_OTHER, "Couldn't find the corresponding physical tile type pin of the logical block type pin %d.", - logical_block->name, physical_tile->name, pin); + pin); } int sub_tile_physical_pin = get_sub_tile_physical_pin(sub_tile_index, physical_tile, logical_block, pin); - return physical_tile->sub_tiles[sub_tile_index].sub_tile_to_tile_pin_indices[sub_tile_physical_pin]; + + /* Find the relative capacity of the logical_block in this sub tile */ + int relative_capacity = sub_tile_capacity - physical_tile->sub_tiles[sub_tile_index].capacity.low; + + /* Find the number of pins per block in the equivalent site list + * of the sub tile. Otherwise, the current logical block may have smaller/larger number of pins + * than other logical blocks that can be placed in the sub-tile. This will lead to an error + * when computing the pin index! + */ + int block_num_pins = physical_tile->sub_tiles[sub_tile_index].num_phy_pins / physical_tile->sub_tiles[sub_tile_index].capacity.total(); + + return relative_capacity * block_num_pins + + physical_tile->sub_tiles[sub_tile_index].sub_tile_to_tile_pin_indices[sub_tile_physical_pin]; } int net_pin_to_tile_pin_index(const ClusterNetId net_id, int net_pin_index) { diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index 3f6e051aedc..425786e1120 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -194,14 +194,55 @@ t_logical_block_type_ptr pick_best_logical_type(t_physical_tile_type_ptr physica //the best expected physical tile the block should use (if no valid placement). t_physical_tile_type_ptr get_physical_tile_type(const ClusterBlockId blk); +//Returns the sub tile index (within 'physical_tile') corresponding to the +//'logical block' +// +//This function will return the index for the first sub_tile that can accommodate +//the logical block +//It is typically called before/during placement, +//when picking a sub-tile to fit a logical block +// +int get_logical_block_physical_sub_tile_index(t_physical_tile_type_ptr physical_tile, + t_logical_block_type_ptr logical_block); + //Returns the physical pin index (within 'physical_tile') corresponding to the //logical index ('pin' of the first instance of 'logical_block' within the physcial tile. // +//This function is called before/during placement, when a sub tile index was not yet assigned. +// //Throws an exception if the corresponding physical pin can't be found. int get_physical_pin(t_physical_tile_type_ptr physical_tile, t_logical_block_type_ptr logical_block, int pin); +//Returns the sub tile index (within 'physical_tile') corresponding to the +//'logical block' by considering if a given offset is in the range of sub tile capacity +int get_logical_block_physical_sub_tile_index(t_physical_tile_type_ptr physical_tile, + t_logical_block_type_ptr logical_block, + int sub_tile_capacity); + +//Returns the physical pin index (within 'physical_tile') corresponding to the +//logical index ('pin' of the first instance of 'logical_block' within the physcial tile. +//This function considers if a given offset is in the range of sub tile capacity +// +// (First pin index at current sub-tile) (The wanted pin index) +// +// | |<----- pin ------->| +// v v +// +// |<----- capacity.low ----->|<----- capacity.low + 1 ----->| ... |<----- sub_tile_capacity ---->| +// +// +//This function is created for device-level information inquiry. +//Therefore, it should ONLY require device-level information as inputs!!! +//It should NOT need any mapping results as inputs!!! +// +//Throws an exception if the corresponding physical pin can't be found. +int get_post_placement_physical_pin(t_physical_tile_type_ptr physical_tile, + t_logical_block_type_ptr logical_block, + int sub_tile_capacity, + int pin); + //Returns the physical pin index (within 'physical_tile') corresponding to the //logical index ('pin') of the 'logical_block' at sub-tile location 'sub_tile_index'. // diff --git a/vtr_flow/arch/complex_switch/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml b/vtr_flow/arch/complex_switch/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml new file mode 100644 index 00000000000..77a30355d4d --- /dev/null +++ b/vtr_flow/arch/complex_switch/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml @@ -0,0 +1,1022 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad io.clock + io.outpad io.inpad io.clock + io.outpad io.inpad io.clock + io.outpad io.inpad io.clock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 + 1 1 + + + + + 1 1 1 1 1 + 1 0 0 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.145e-10 + 1.145e-10 + 1.145e-10 + 1.145e-10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/config/config.txt new file mode 100644 index 00000000000..369f8fc7cd9 --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/config/config.txt @@ -0,0 +1,47 @@ +# +############################################ +# Configuration file for running experiments +############################################## + +# Path to directory of circuits to use +circuits_dir=benchmarks/microbenchmarks + +# Path to directory of architectures to use +archs_dir=arch/complex_switch + +# Add circuits to list to sweep +circuit_list_add=const_true.blif +circuit_list_add=const_false.blif +circuit_list_add=always_true.blif +circuit_list_add=always_false.blif +circuit_list_add=and.blif +circuit_list_add=multiconnected_lut.blif +circuit_list_add=multiconnected_lut2.blif +circuit_list_add=and_latch.blif +circuit_list_add=false_path_mux.blif +circuit_list_add=mult_2x2.blif +circuit_list_add=mult_3x3.blif +circuit_list_add=mult_3x4.blif +circuit_list_add=mult_4x4.blif +circuit_list_add=mult_5x5.blif +circuit_list_add=mult_5x6.blif +circuit_list_add=rca_1bit.blif +circuit_list_add=rca_2bit.blif +circuit_list_add=rca_3bit.blif +circuit_list_add=rca_4bit.blif +circuit_list_add=rca_5bit.blif + +# Add architectures to list to sweep +arch_list_add=k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml + +# Parse info and how to parse +parse_file=vpr_standard.txt + +# How to parse QoR info +qor_parse_file=qor_standard.txt + +# Pass requirements +pass_requirements_file=pass_requirements.txt + +#Script parameters +script_params=-track_memory_usage -check_equivalent -starting_stage abc --gen_post_synthesis_netlist on --sweep_dangling_primary_ios off --sweep_constant_primary_outputs off diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/config/golden_results.txt new file mode 100644 index 00000000000..50ce33d1dff --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/config/golden_results.txt @@ -0,0 +1,21 @@ +arch circuit script_params vtr_flow_elapsed_time error odin_synth_time max_odin_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_time placed_wirelength_est place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml const_true.blif common 0.47 -1 -1 0 0.01 -1 -1 27592 -1 -1 1 0 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/const_true.blif/common 14020 -1 1 1 2 0 1 2 3 3 9 -1 auto 0.01 0 0.01 0.00 nan 0 0 nan 7.986e-06 2.718e-06 6.8232e-05 4.2494e-05 2 0 1 3900 3900 966.985 107.443 0.01 0.000341412 0.000208891 0 1 0 0 0 0 nan nan 0 0 0 0 966.985 107.443 0.00 0.000118607 8.6919e-05 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml const_false.blif common 0.46 -1 -1 0 0.01 -1 -1 27588 -1 -1 1 0 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/const_false.blif/common 14020 -1 1 1 2 0 1 2 3 3 9 -1 auto 0.01 0 0.01 0.00 nan 0 0 nan 1.4672e-05 6.675e-06 9.7506e-05 6.2786e-05 2 0 1 3900 3900 966.985 107.443 0.02 0.000441329 0.000281322 0 1 0 0 0 0 nan nan 0 0 0 0 966.985 107.443 0.00 0.000118172 8.6239e-05 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml always_true.blif common 0.45 -1 -1 0 0.01 -1 -1 27592 -1 -1 1 0 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/always_true.blif/common 14056 6 1 1 8 0 1 8 3 3 9 -1 auto 0.01 0 0.01 0.00 nan 0 0 nan 8.554e-06 3.002e-06 6.6704e-05 4.1451e-05 2 0 1 3900 3900 966.985 107.443 0.01 0.000349309 0.000213988 0 1 0 0 0 0 nan nan 0 0 0 0 966.985 107.443 0.00 0.000123131 9.081e-05 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml always_false.blif common 0.43 -1 -1 0 0.01 -1 -1 27588 -1 -1 1 0 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/always_false.blif/common 14056 6 1 1 8 0 1 8 3 3 9 -1 auto 0.01 0 0.01 0.00 nan 0 0 nan 8.073e-06 2.788e-06 6.671e-05 4.166e-05 2 0 1 3900 3900 966.985 107.443 0.02 0.000475947 0.000289911 0 1 0 0 0 0 nan nan 0 0 0 0 966.985 107.443 0.00 0.000129567 9.7136e-05 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml and.blif common 0.43 -1 -1 1 0.01 -1 -1 27728 -1 -1 1 2 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/and.blif/common 14064 2 1 3 4 0 3 4 3 3 9 -1 auto 0.01 6 0.01 0.00 0.459217 -0.459217 -0.459217 nan 6.781e-06 2.695e-06 0.000323679 0.000152854 12 12 1 3900 3900 2582.62 286.957 0.01 0.000771547 0.000456962 6 1 3 3 88 70 0.58948 nan -0.58948 -0.58948 0 0 3970.02 441.113 0.00 0.000160368 0.0001336 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml multiconnected_lut.blif common 0.46 -1 -1 2 0.02 -1 -1 31140 -1 -1 1 5 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/multiconnected_lut.blif/common 14100 5 1 7 8 0 7 7 3 3 9 -1 auto 0.01 14 0.01 0.00 0.72619 -0.72619 -0.72619 nan 7.215e-06 3.231e-06 0.000366809 0.000206949 14 27 28 3900 3900 2841.42 315.713 0.02 0.00135454 0.00088988 13 1 7 7 189 150 0.987324 nan -0.987324 -0.987324 0 0 4264.82 473.869 0.00 0.000385691 0.000349665 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml multiconnected_lut2.blif common 0.50 -1 -1 2 0.02 -1 -1 31508 -1 -1 1 5 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/multiconnected_lut2.blif/common 14104 5 1 7 8 0 7 7 3 3 9 -1 auto 0.01 14 0.01 0.00 0.72812 -0.72812 -0.72812 nan 8.308e-06 3.808e-06 0.000408465 0.000236106 16 21 6 3900 3900 3970.02 441.113 0.02 0.00207226 0.00130728 24 16 36 36 1095 867 1.52321 nan -1.52321 -1.52321 0 0 4445.42 493.935 0.00 0.0005474 0.000436828 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml and_latch.blif common 0.40 -1 -1 1 0.01 -1 -1 27872 -1 -1 1 3 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/and_latch.blif/common 14100 3 1 5 6 1 4 5 3 3 9 -1 auto 0.01 6 0.01 0.00 0.282563 -0.551847 -0.282563 0.282563 1.1262e-05 6.347e-06 0.00012241 9.5491e-05 12 6 1 3900 3900 2582.62 286.957 0.01 0.000587065 0.000446433 6 1 3 3 67 50 0.411504 0.411504 -0.751406 -0.411504 0 0 3970.02 441.113 0.00 0.000245415 0.00020969 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml false_path_mux.blif common 0.53 -1 -1 1 0.03 -1 -1 30928 -1 -1 1 3 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/false_path_mux.blif/common 14092 4 1 4 6 0 4 6 3 3 9 -1 auto 0.01 8 0.01 0.00 0.459217 -0.459217 -0.459217 nan 7.24e-06 2.975e-06 0.00023265 0.000127078 14 12 13 3900 3900 2841.42 315.713 0.02 0.00102631 0.000635209 8 11 23 23 719 573 0.653593 nan -0.653593 -0.653593 0 0 4264.82 473.869 0.00 0.000333881 0.000253494 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml mult_2x2.blif common 0.42 -1 -1 1 0.03 -1 -1 30076 -1 -1 1 4 0 0 exited with return code 2 v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/mult_2x2.blif/common 14132 4 4 8 12 0 8 9 3 3 9 -1 auto 0.01 17 0.01 0.00 0.461147 -1.8388 -0.461147 nan 3.0291e-05 2.0655e-05 0.000826825 0.000544016 22 59 22 3900 3900 4723.42 524.824 0.06 0.00717109 0.00544596 -1 -1 534 1759 103544 72914 -1 -1 -1 -1 -1 -1 -1 -1 0.02 -1 -1 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml mult_3x3.blif common 0.89 -1 -1 3 0.04 -1 -1 29860 -1 -1 3 6 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/mult_3x3.blif/common 14320 6 6 28 34 0 28 15 5 5 25 clb auto 0.01 85 0.04 0.00 1.13809 -5.19029 -1.13809 nan 2.6664e-05 1.8247e-05 0.00299567 0.002278 24 273 24 23400 11700 20975.0 838.999 0.20 0.0150262 0.0122161 224 18 267 1074 55024 25016 1.66366 nan -7.90973 -1.66366 0 0 27052.1 1082.08 0.01 0.00435926 0.00407205 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml mult_3x4.blif common 0.99 -1 -1 4 0.03 -1 -1 29724 -1 -1 5 7 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/mult_3x4.blif/common 14440 7 8 39 47 0 39 20 5 5 25 clb auto 0.01 138 0.06 0.00 1.44727 -7.36634 -1.44727 nan 3.5014e-05 2.5547e-05 0.00454935 0.00356269 28 409 37 23400 19500 25328.9 1013.15 0.27 0.0208982 0.0172801 317 20 406 1713 102745 42899 1.87939 nan -9.73921 -1.87939 0 0 29680.9 1187.23 0.02 0.00489018 0.00458571 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml mult_4x4.blif common 1.24 -1 -1 8 0.06 -1 -1 30044 -1 -1 7 8 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/mult_4x4.blif/common 14524 8 8 51 59 0 51 23 6 6 36 clb auto 0.01 185 0.06 0.00 2.46893 -11.4231 -2.46893 nan 3.6162e-05 2.7442e-05 0.00429701 0.00346122 30 539 32 165600 27300 47960.3 1332.23 0.47 0.0225668 0.018996 492 21 533 2208 163864 59911 3.19932 nan -15.873 -3.19932 0 0 61410.5 1705.85 0.03 0.00649194 0.00608731 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml mult_5x5.blif common 1.46 -1 -1 7 0.07 -1 -1 31580 -1 -1 11 10 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/mult_5x5.blif/common 16940 10 10 95 105 0 95 31 6 6 36 clb auto 0.01 403 0.08 0.00 2.57403 -17.6381 -2.57403 nan 6.4981e-05 4.9312e-05 0.00861358 0.00713845 40 1027 26 165600 42900 61410.5 1705.85 0.48 0.0392812 0.0338388 859 17 751 3226 229458 81411 3.04713 nan -21.8248 -3.04713 0 0 78756.9 2187.69 0.05 0.0221997 0.0215176 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml mult_5x6.blif common 1.65 -1 -1 8 0.11 -1 -1 31760 -1 -1 11 11 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/mult_5x6.blif/common 16952 11 11 94 105 0 94 33 6 6 36 clb auto 0.01 399 0.10 0.00 2.72861 -20.3704 -2.72861 nan 9.1193e-05 7.3428e-05 0.0105789 0.00898096 38 1023 44 165600 42900 55946.4 1554.07 0.53 0.0449395 0.0388459 958 22 958 3980 301339 108435 3.28798 nan -25.4701 -3.28798 0 0 73011.6 2028.10 0.07 0.0176315 0.0167732 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml rca_1bit.blif common 0.46 -1 -1 1 0.03 -1 -1 28676 -1 -1 1 3 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/rca_1bit.blif/common 16156 3 2 5 7 0 5 6 3 3 9 -1 auto 0.01 10 0.01 0.00 0.459217 -0.918433 -0.459217 nan 6.963e-06 3.165e-06 0.000287954 0.000167268 24 20 13 3900 3900 5011.22 556.802 0.02 0.00175227 0.00111457 16 7 17 32 1105 806 0.645159 nan -1.28203 -0.645159 0 0 6337.42 704.157 0.00 0.000419914 0.000361362 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml rca_2bit.blif common 0.53 -1 -1 2 0.03 -1 -1 29476 -1 -1 1 5 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/rca_2bit.blif/common 14140 5 3 9 12 0 9 9 3 3 9 -1 auto 0.01 18 0.01 0.00 0.72812 -1.91353 -0.72812 nan 1.2566e-05 5.813e-06 0.000448203 0.000307516 20 31 5 3900 3900 4445.42 493.935 0.03 0.00310557 0.00229138 39 16 46 89 3194 2438 1.38711 nan -3.1051 -1.38711 0 0 5185.22 576.135 0.00 0.00094047 0.000809308 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml rca_3bit.blif common 0.58 -1 -1 3 0.04 -1 -1 31000 -1 -1 1 7 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/rca_3bit.blif/common 14180 7 4 13 17 0 13 12 3 3 9 -1 auto 0.01 26 0.01 0.00 0.993163 -3.17366 -0.993163 nan 1.3518e-05 7.808e-06 0.000595566 0.000433481 26 70 25 3900 3900 5185.22 576.135 0.04 0.00569476 0.00423258 46 13 83 159 5776 4099 1.29602 nan -4.18829 -1.29602 0 0 6645.42 738.380 0.00 0.00125086 0.00112261 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml rca_4bit.blif common 0.53 -1 -1 4 0.03 -1 -1 29472 -1 -1 1 9 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/rca_4bit.blif/common 16252 9 5 17 22 0 17 15 3 3 9 -1 auto 0.01 34 0.01 0.00 1.26014 -4.69884 -1.26014 nan 1.6451e-05 1.0448e-05 0.000786263 0.000610898 28 63 27 3900 3900 5935.82 659.535 0.05 0.00662978 0.00512759 52 16 71 131 3861 2539 1.81278 nan -6.22784 -1.81278 0 0 6854.42 761.602 0.00 0.00168496 0.00153102 +k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml rca_5bit.blif common 0.63 -1 -1 4 0.04 -1 -1 29484 -1 -1 2 11 0 0 success v8.0.0-2862-g10bee17c9-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 8.4.0 on Linux-3.10.0-1127.18.2.el7.x86_64 x86_64 2020-10-08T09:49:53 lnissrv4.eng.utah.edu /research/ece/lnis/USERS/tang/github/vtr-verilog-to-routing/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_post_routing_sync/run002/k4_N8_topology-0.85sL2-0.15gL4-on-cb-off-sb_22nm_22nm_nonLR.xml/rca_5bit.blif/common 14264 11 6 24 30 0 24 19 4 4 16 clb auto 0.01 63 0.02 0.00 1.27204 -6.15809 -1.27204 nan 1.9895e-05 1.1091e-05 0.00248089 0.00171025 28 173 35 7800 7800 12557.4 784.840 0.08 0.0101553 0.00789177 153 15 186 419 20955 11824 1.608 nan -7.62824 -1.608 0 0 14986.4 936.652 0.01 0.00271595 0.00251854 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt index bbc8cbca788..76c3cd41d86 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt @@ -72,3 +72,4 @@ regression_tests/vtr_reg_strong/strong_blocks_with_no_inputs regression_tests/vtr_reg_strong/strong_fix_clusters regression_tests/vtr_reg_strong/strong_analytic_placer regression_tests/vtr_reg_strong/strong_place_quench_slack +regression_tests/vtr_reg_strong/strong_post_routing_sync