From 5ccb4adb0856f417d9bc87ea37a27702013bbf3e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Feb 2020 11:09:24 -0700 Subject: [PATCH] refactored LB router main function --- openfpga/src/repack/lb_router.cpp | 197 ++++++++++++++++++++++++++---- openfpga/src/repack/lb_router.h | 38 ++++-- 2 files changed, 197 insertions(+), 38 deletions(-) diff --git a/openfpga/src/repack/lb_router.cpp b/openfpga/src/repack/lb_router.cpp index fece00596..a22d1d25e 100644 --- a/openfpga/src/repack/lb_router.cpp +++ b/openfpga/src/repack/lb_router.cpp @@ -19,11 +19,13 @@ namespace openfpga { /************************************************** * Public Constructors *************************************************/ -LbRouter::LbRouter(const LbRRGraph& lb_rr_graph) { +LbRouter::LbRouter(const LbRRGraph& lb_rr_graph, t_logical_block_type_ptr lb_type) { routing_status_.resize(lb_rr_graph.nodes().size()); explored_node_tb_.resize(lb_rr_graph.nodes().size()); explore_id_index_ = 1; + lb_type_ = lb_type; + /* Default routing parameters */ params_.max_iterations = 50; params_.pres_fac = 1; @@ -100,6 +102,115 @@ bool LbRouter::route_has_conflict(const LbRRGraph& lb_rr_graph, t_trace* rt) con return false; } +/************************************************** + * Public mutators + *************************************************/ +bool LbRouter::try_route(const LbRRGraph& lb_rr_graph, + const AtomNetlist& atom_nlist, + const int& verbosity) { + /* Validate if the rr_graph is the one we used to initialize the router */ + VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); + + bool is_routed = false; + bool is_impossible = false; + + mode_status_.is_mode_conflict = false; + mode_status_.try_expand_all_modes = false; + + t_expansion_node exp_node; + + reset_explored_node_tb(); + + /* Reset current routing */ + reset_net_rt(); + reset_routing_status(); + + std::unordered_map mode_map; + + /* Iteratively remove congestion until a successful route is found. + * Cap the total number of iterations tried so that if a solution does not exist, then the router won't run indefinitely */ + pres_con_fac_ = params_.pres_fac; + for (int iter = 0; iter < params_.max_iterations && !is_routed && !is_impossible; iter++) { + unsigned int inet; + /* Iterate across all nets internal to logic block */ + for (inet = 0; inet < lb_nets_.size() && !is_impossible; inet++) { + int idx = inet; + if (is_skip_route_net(lb_rr_graph, lb_nets_[idx].rt_tree)) { + continue; + } + commit_remove_rt(lb_rr_graph, lb_nets_[idx].rt_tree, RT_REMOVE, mode_map); + free_net_rt(lb_nets_[idx].rt_tree); + lb_nets_[idx].rt_tree = nullptr; + add_source_to_rt(idx); + + /* Route each sink of net */ + for (unsigned int itarget = 1; itarget < lb_nets_[idx].terminals.size() && !is_impossible; itarget++) { + pq_.clear(); + /* Get lowest cost next node, repeat until a path is found or if it is impossible to route */ + + expand_rt(idx, idx); + + is_impossible = try_expand_nodes(atom_nlist, lb_rr_graph, lb_nets_[idx], exp_node, itarget, mode_status_.expand_all_modes, verbosity); + + if (is_impossible && !mode_status_.expand_all_modes) { + mode_status_.try_expand_all_modes = true; + mode_status_.expand_all_modes = true; + break; + } + + if (exp_node.node_index == lb_nets_[idx].terminals[itarget]) { + /* Net terminal is routed, add this to the route tree, clear data structures, and keep going */ + is_impossible = add_to_rt(lb_nets_[idx].rt_tree, exp_node.node_index, idx); + } + + if (is_impossible) { + VTR_LOG("Routing was impossible!\n"); + } else if (mode_status_.expand_all_modes) { + is_impossible = route_has_conflict(lb_rr_graph, lb_nets_[idx].rt_tree); + if (is_impossible) { + VTR_LOG("Routing was impossible due to modes!\n"); + } + } + + explore_id_index_++; + if (explore_id_index_ > 2000000000) { + /* overflow protection */ + for (const LbRRNodeId& id : lb_rr_graph.nodes()) { + explored_node_tb_[id].explored_id = OPEN; + explored_node_tb_[id].enqueue_id = OPEN; + explore_id_index_ = 1; + } + } + } + + if (!is_impossible) { + commit_remove_rt(lb_rr_graph, lb_nets_[idx].rt_tree, RT_COMMIT, mode_map); + if (mode_status_.is_mode_conflict) { + is_impossible = true; + } + } + } + + if (!is_impossible) { + is_routed_ = is_route_success(lb_rr_graph); + } else { + --inet; + VTR_LOGV(verbosity < 3, "Net '%s' is impossible to route within proposed %s cluster\n", + atom_nlist.net_name(lb_nets_[inet].atom_net_id).c_str(), lb_type_->name); + is_routed_ = false; + } + pres_con_fac_ *= params_.pres_fac_mult; + } + + /* TODO: + * Let user to decide to how proceed upon the routing results: + * - route success: save the results through public accessors to lb_nets_ + * print the route results to files + * - route fail: report all the congestion nodes + */ + return is_routed_; +} + /************************************************** * Private mutators *************************************************/ @@ -204,8 +315,7 @@ bool LbRouter::check_edge_for_route_conflicts(std::unordered_map& mode_map, - t_mode_selection_status& mode_status) { + std::unordered_map& mode_map) { int incr; if (nullptr == rt) { @@ -235,16 +345,16 @@ void LbRouter::commit_remove_rt(const LbRRGraph& lb_rr_graph, // Check to see if there is no mode conflict between previous nets. // A conflict is present if there are differing modes between a pb_graph_node // and its children. - if (op == RT_COMMIT && mode_status.try_expand_all_modes) { + if (op == RT_COMMIT && mode_status_.try_expand_all_modes) { const LbRRNodeId& node = rt->next_nodes[i].current_node; t_pb_graph_pin* pin = lb_rr_graph.node_pb_graph_pin(node); if (check_edge_for_route_conflicts(mode_map, driver_pin, pin)) { - mode_status.is_mode_conflict = true; + mode_status_.is_mode_conflict = true; } } - commit_remove_rt(lb_rr_graph, &rt->next_nodes[i], op, mode_map, mode_status); + commit_remove_rt(lb_rr_graph, &rt->next_nodes[i], op, mode_map); } } @@ -318,7 +428,6 @@ void LbRouter::add_source_to_rt(const int& inet) { void LbRouter::expand_rt_rec(t_trace* rt, const LbRRNodeId& prev_index, - reservable_pq, compare_expansion_node>& pq, const int& irt_net, const int& explore_id_index) { t_expansion_node enode; @@ -327,7 +436,7 @@ void LbRouter::expand_rt_rec(t_trace* rt, enode.cost = 0; enode.node_index = rt->current_node; enode.prev_index = prev_index; - pq.push(enode); + pq_.push(enode); explored_node_tb_[enode.node_index].inet = irt_net; explored_node_tb_[enode.node_index].explored_id = OPEN; explored_node_tb_[enode.node_index].enqueue_id = explore_id_index; @@ -335,24 +444,22 @@ void LbRouter::expand_rt_rec(t_trace* rt, explored_node_tb_[enode.node_index].prev_index = prev_index; for (unsigned int i = 0; i < rt->next_nodes.size(); i++) { - expand_rt_rec(&rt->next_nodes[i], rt->current_node, pq, irt_net, explore_id_index); + expand_rt_rec(&rt->next_nodes[i], rt->current_node, irt_net, explore_id_index); } } void LbRouter::expand_rt(const int& inet, - reservable_pq, compare_expansion_node>& pq, const int& irt_net) { - VTR_ASSERT(pq.empty()); + VTR_ASSERT(pq_.empty()); - expand_rt_rec(lb_nets_[inet].rt_tree, LbRRNodeId::INVALID(), pq, irt_net, explore_id_index_); + expand_rt_rec(lb_nets_[inet].rt_tree, LbRRNodeId::INVALID(), irt_net, explore_id_index_); } void LbRouter::expand_edges(const LbRRGraph& lb_rr_graph, t_mode* mode, const LbRRNodeId& cur_inode, float cur_cost, - int net_fanout, - reservable_pq, compare_expansion_node>& pq) { + int net_fanout) { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -394,19 +501,18 @@ void LbRouter::expand_edges(const LbRRGraph& lb_rr_graph, /* Add to queue if cost is lower than lowest cost path to this enode */ if (explored_node_tb_[enode.node_index].enqueue_id == explore_id_index_) { if (enode.cost < explored_node_tb_[enode.node_index].enqueue_cost) { - pq.push(enode); + pq_.push(enode); } } else { explored_node_tb_[enode.node_index].enqueue_id = explore_id_index_; explored_node_tb_[enode.node_index].enqueue_cost = enode.cost; - pq.push(enode); + pq_.push(enode); } } } void LbRouter::expand_node(const LbRRGraph& lb_rr_graph, const t_expansion_node& exp_node, - reservable_pq, compare_expansion_node>& pq, const int& net_fanout) { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -420,12 +526,11 @@ void LbRouter::expand_node(const LbRRGraph& lb_rr_graph, mode = &(lb_rr_graph.node_pb_graph_pin(cur_node)->parent_node->pb_type->modes[0]); } - expand_edges(lb_rr_graph, mode, cur_node, cur_cost, net_fanout, pq); + expand_edges(lb_rr_graph, mode, cur_node, cur_cost, net_fanout); } void LbRouter::expand_node_all_modes(const LbRRGraph& lb_rr_graph, const t_expansion_node& exp_node, - reservable_pq, compare_expansion_node>& pq, const int& net_fanout) { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -457,7 +562,7 @@ void LbRouter::expand_node_all_modes(const LbRRGraph& lb_rr_graph, if (is_illegal == true) { continue; } - expand_edges(lb_rr_graph, mode, cur_inode, cur_cost, net_fanout, pq); + expand_edges(lb_rr_graph, mode, cur_inode, cur_cost, net_fanout); } } @@ -465,14 +570,13 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, const LbRRGraph& lb_rr_graph, const t_net& lb_net, t_expansion_node& exp_node, - reservable_pq, compare_expansion_node>& pq, const int& itarget, const bool& try_other_modes, const int& verbosity) { bool is_impossible = false; do { - if (pq.empty()) { + if (pq_.empty()) { /* No connection possible */ is_impossible = true; @@ -493,8 +597,8 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, VTR_LOG("\n"); } } else { - exp_node = pq.top(); - pq.pop(); + exp_node = pq_.top(); + pq_.pop(); LbRRNodeId exp_inode = exp_node.node_index; if (explored_node_tb_[exp_inode].explored_id != explore_id_index_) { @@ -506,9 +610,9 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, explored_node_tb_[exp_inode].prev_index = exp_node.prev_index; if (exp_inode != lb_net.terminals[itarget]) { if (!try_other_modes) { - expand_node(lb_rr_graph, exp_node, pq, lb_net.terminals.size() - 1); + expand_node(lb_rr_graph, exp_node, lb_net.terminals.size() - 1); } else { - expand_node_all_modes(lb_rr_graph, exp_node, pq, lb_net.terminals.size() - 1); + expand_node_all_modes(lb_rr_graph, exp_node, lb_net.terminals.size() - 1); } } } @@ -539,4 +643,45 @@ void LbRouter::reset_explored_node_tb() { } } +void LbRouter::reset_net_rt() { + for (unsigned int inet = 0; inet < lb_nets_.size(); inet++) { + free_net_rt(lb_nets_[inet].rt_tree); + lb_nets_[inet].rt_tree = nullptr; + } +} + +void LbRouter::reset_routing_status() { + for (t_routing_status& status : routing_status_) { + status.historical_usage = 0; + status.occ = 0; + } +} + +void LbRouter::clear_nets() { + reset_net_rt(); + for (unsigned int i = 0; i < lb_nets_.size(); i++) { + lb_nets_[i].terminals.clear(); + } + lb_nets_.clear(); +} + +void LbRouter::free_net_rt(t_trace* lb_trace) { + if (lb_trace != nullptr) { + for (unsigned int i = 0; i < lb_trace->next_nodes.size(); i++) { + free_lb_trace(&lb_trace->next_nodes[i]); + } + lb_trace->next_nodes.clear(); + delete lb_trace; + } +} + +void LbRouter::free_lb_trace(t_trace* lb_trace) { + if (lb_trace != nullptr) { + for (unsigned int i = 0; i < lb_trace->next_nodes.size(); i++) { + free_lb_trace(&lb_trace->next_nodes[i]); + } + lb_trace->next_nodes.clear(); + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_router.h b/openfpga/src/repack/lb_router.h index 8a4feac9c..40d8d5d93 100644 --- a/openfpga/src/repack/lb_router.h +++ b/openfpga/src/repack/lb_router.h @@ -183,7 +183,7 @@ class LbRouter { }; public : /* Public constructors */ - LbRouter(const LbRRGraph& lb_rr_graph); + LbRouter(const LbRRGraph& lb_rr_graph, t_logical_block_type_ptr lb_type); public : /* Public accessors */ /** @@ -206,6 +206,15 @@ class LbRouter { bool route_has_conflict(const LbRRGraph& lb_rr_graph, t_trace* rt) const; + public : /* Public mutators */ + /** + * Perform routing algorithm on a given logical tile routing resource graph + * Note: the lb_rr_graph must be the same as you initilized the router!!! + */ + bool try_route(const LbRRGraph& lb_rr_graph, + const AtomNetlist& atom_nlist, + const int& verbosity); + private : /* Private mutators */ /*It is possible that a net may connect multiple times to a logically equivalent set of primitive pins. *The cluster router will only route one connection for a particular net to the common sink of the @@ -223,43 +232,35 @@ class LbRouter { void commit_remove_rt(const LbRRGraph& lb_rr_graph, t_trace* rt, const e_commit_remove& op, - std::unordered_map& mode_map, - t_mode_selection_status& mode_status); + std::unordered_map& mode_map); bool is_skip_route_net(const LbRRGraph& lb_rr_graph, t_trace* rt); bool add_to_rt(t_trace* rt, const LbRRNodeId& node_index, const int& irt_net); void add_source_to_rt(const int& inet); void expand_rt_rec(t_trace* rt, const LbRRNodeId& prev_index, - reservable_pq, compare_expansion_node>& pq, const int& irt_net, const int& explore_id_index); void expand_rt(const int& inet, - reservable_pq, compare_expansion_node>& pq, const int& irt_net); void expand_edges(const LbRRGraph& lb_rr_graph, t_mode* mode, const LbRRNodeId& cur_inode, float cur_cost, - int net_fanout, - reservable_pq, compare_expansion_node>& pq); + int net_fanout); void expand_node(const LbRRGraph& lb_rr_graph, const t_expansion_node& exp_node, - reservable_pq, compare_expansion_node>& pq, const int& net_fanout); void expand_node_all_modes(const LbRRGraph& lb_rr_graph, const t_expansion_node& exp_node, - reservable_pq, compare_expansion_node>& pq, const int& net_fanout); bool try_expand_nodes(const AtomNetlist& atom_nlist, const LbRRGraph& lb_rr_graph, const t_net& lb_net, t_expansion_node& exp_node, - reservable_pq, compare_expansion_node>& pq, const int& itarget, const bool& try_other_modes, const int& verbosity); - private : /* Private validators */ /** * Validate if the rr_graph is the one we used to initialize the router @@ -268,6 +269,12 @@ class LbRouter { private : /* Private initializer and cleaner */ void reset_explored_node_tb(); + void reset_net_rt(); + void reset_routing_status(); + + void clear_nets(); + void free_net_rt(t_trace* lb_trace); + void free_lb_trace(t_trace* lb_trace); private : /* Stores all data needed by intra-logic cluster_ctx.blocks router */ /* Logical Netlist Info */ @@ -292,7 +299,14 @@ class LbRouter { /* Parameters used by router */ t_option params_; - bool is_routed_; /* Stores whether or not the current logical-to-physical mapping has a routed solution */ + /* Stores whether or not the current logical-to-physical mapping has a routed solution */ + bool is_routed_; + + /* Stores the mode selection status when expanding the edges */ + t_mode_selection_status mode_status_; + + /* Stores state info of the priority queue in expanding edges during route */ + reservable_pq, compare_expansion_node> pq_; /* current congestion factor */ float pres_con_fac_;