refactored LB router main function

This commit is contained in:
tangxifan 2020-02-19 11:09:24 -07:00
parent 3d5a15d41e
commit 5ccb4adb08
2 changed files with 197 additions and 38 deletions

View File

@ -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<const t_pb_graph_node*, const t_mode*> 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<const t_pb_grap
void LbRouter::commit_remove_rt(const LbRRGraph& lb_rr_graph,
t_trace* rt,
const e_commit_remove& op,
std::unordered_map<const t_pb_graph_node*, const t_mode*>& mode_map,
t_mode_selection_status& mode_status) {
std::unordered_map<const t_pb_graph_node*, const t_mode*>& 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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 */

View File

@ -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<const t_pb_graph_node*, const t_mode*>& mode_map,
t_mode_selection_status& mode_status);
std::unordered_map<const t_pb_graph_node*, const t_mode*>& 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<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq,
const int& irt_net,
const int& explore_id_index);
void expand_rt(const int& inet,
reservable_pq<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq);
int net_fanout);
void expand_node(const LbRRGraph& lb_rr_graph,
const t_expansion_node& exp_node,
reservable_pq<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, 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<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node> pq_;
/* current congestion factor */
float pres_con_fac_;