route_common functions now adopt RRGraph object
This commit is contained in:
parent
266b4b6fbe
commit
26523f1b63
|
@ -157,10 +157,10 @@ struct DeviceContext : public Context {
|
||||||
std::vector<t_rr_rc_data> rr_rc_data;
|
std::vector<t_rr_rc_data> rr_rc_data;
|
||||||
|
|
||||||
//Sets of non-configurably connected nodes
|
//Sets of non-configurably connected nodes
|
||||||
std::vector<std::vector<int>> rr_non_config_node_sets;
|
std::vector<std::vector<RRNodeId>> rr_non_config_node_sets;
|
||||||
|
|
||||||
//Reverse look-up from RR node to non-configurably connected node set (index into rr_nonconf_node_sets)
|
//Reverse look-up from RR node to non-configurably connected node set (index into rr_nonconf_node_sets)
|
||||||
std::unordered_map<RRNodeId, RRNodeId> rr_node_to_non_config_node_set;
|
std::unordered_map<RRNodeId, int> rr_node_to_non_config_node_set;
|
||||||
|
|
||||||
//The indicies of rr nodes of a given type at a specific x,y grid location
|
//The indicies of rr nodes of a given type at a specific x,y grid location
|
||||||
t_rr_node_indices rr_node_indices; //[0..NUM_RR_TYPES-1][0..grid.width()-1][0..grid.width()-1][0..size-1]
|
t_rr_node_indices rr_node_indices; //[0..NUM_RR_TYPES-1][0..grid.width()-1][0..grid.width()-1][0..size-1]
|
||||||
|
@ -284,12 +284,12 @@ struct PlacementContext : public Context {
|
||||||
struct RoutingContext : public Context {
|
struct RoutingContext : public Context {
|
||||||
/* [0..num_nets-1] of linked list start pointers. Defines the routing. */
|
/* [0..num_nets-1] of linked list start pointers. Defines the routing. */
|
||||||
vtr::vector<ClusterNetId, t_traceback> trace;
|
vtr::vector<ClusterNetId, t_traceback> trace;
|
||||||
vtr::vector<ClusterNetId, std::unordered_set<int>> trace_nodes;
|
vtr::vector<ClusterNetId, std::unordered_set<RRNodeId>> trace_nodes;
|
||||||
|
|
||||||
/* Xifan Tang: this should adopt RRNodeId as well */
|
/* Xifan Tang: this should adopt RRNodeId as well */
|
||||||
vtr::vector<ClusterNetId, std::vector<RRNodeId>> net_rr_terminals; /* [0..num_nets-1][0..num_pins-1] */
|
vtr::vector<ClusterNetId, std::vector<RRNodeId>> net_rr_terminals; /* [0..num_nets-1][0..num_pins-1] */
|
||||||
|
|
||||||
vtr::vector<ClusterBlockId, std::vector<int>> rr_blk_source; /* [0..num_blocks-1][0..num_class-1] */
|
vtr::vector<ClusterBlockId, std::vector<RRNodeId>> rr_blk_source; /* [0..num_blocks-1][0..num_class-1] */
|
||||||
|
|
||||||
vtr::vector<RRNodeId, t_rr_node_route_inf> rr_node_route_inf; /* [0..device_ctx.num_rr_nodes-1] */
|
vtr::vector<RRNodeId, t_rr_node_route_inf> rr_node_route_inf; /* [0..device_ctx.num_rr_nodes-1] */
|
||||||
|
|
||||||
|
|
|
@ -92,18 +92,18 @@ static int num_linked_f_pointer_allocated = 0;
|
||||||
* */
|
* */
|
||||||
|
|
||||||
/******************** Subroutines local to route_common.c *******************/
|
/******************** Subroutines local to route_common.c *******************/
|
||||||
static t_trace_branch traceback_branch(int node, std::unordered_set<int>& main_branch_visited);
|
static t_trace_branch traceback_branch(const RRNodeId& node, std::unordered_set<RRNodeId>& main_branch_visited);
|
||||||
static std::pair<t_trace*, t_trace*> add_trace_non_configurable(t_trace* head, t_trace* tail, int node, std::unordered_set<int>& visited);
|
static std::pair<t_trace*, t_trace*> add_trace_non_configurable(t_trace* head, t_trace* tail, const RRNodeId& node, std::unordered_set<RRNodeId>& visited);
|
||||||
static std::pair<t_trace*, t_trace*> add_trace_non_configurable_recurr(int node, std::unordered_set<int>& visited, int depth = 0);
|
static std::pair<t_trace*, t_trace*> add_trace_non_configurable_recurr(const RRNodeId& node, std::unordered_set<RRNodeId>& visited, int depth = 0);
|
||||||
|
|
||||||
static vtr::vector<ClusterNetId, std::vector<int>> load_net_rr_terminals(const t_rr_node_indices& L_rr_node_indices);
|
static vtr::vector<ClusterNetId, std::vector<RRNodeId>> load_net_rr_terminals(const RRGraph& rr_graph);
|
||||||
static vtr::vector<ClusterBlockId, std::vector<int>> load_rr_clb_sources(const t_rr_node_indices& L_rr_node_indices);
|
static vtr::vector<ClusterBlockId, std::vector<RRNodeId>> load_rr_clb_sources(const RRGraph& rr_graph);
|
||||||
|
|
||||||
static t_clb_opins_used alloc_and_load_clb_opins_used_locally();
|
static t_clb_opins_used alloc_and_load_clb_opins_used_locally();
|
||||||
static void adjust_one_rr_occ_and_apcost(int inode, int add_or_sub, float pres_fac, float acc_fac);
|
static void adjust_one_rr_occ_and_apcost(const RRNodeId& inode, int add_or_sub, float pres_fac, float acc_fac);
|
||||||
|
|
||||||
bool validate_traceback_recurr(t_trace* trace, std::set<int>& seen_rr_nodes);
|
bool validate_traceback_recurr(t_trace* trace, std::set<RRNodeId>& seen_rr_nodes);
|
||||||
static bool validate_trace_nodes(t_trace* head, const std::unordered_set<int>& trace_nodes);
|
static bool validate_trace_nodes(t_trace* head, const std::unordered_set<RRNodeId>& trace_nodes);
|
||||||
static float get_single_rr_cong_cost(const RRNodeId& inode);
|
static float get_single_rr_cong_cost(const RRNodeId& inode);
|
||||||
|
|
||||||
/************************** Subroutine definitions ***************************/
|
/************************** Subroutine definitions ***************************/
|
||||||
|
@ -179,7 +179,8 @@ void restore_routing(vtr::vector<ClusterNetId, t_trace*>& best_routing,
|
||||||
* Use this number as a routing serial number to ensure that programming *
|
* Use this number as a routing serial number to ensure that programming *
|
||||||
* changes do not break the router. */
|
* changes do not break the router. */
|
||||||
void get_serial_num() {
|
void get_serial_num() {
|
||||||
int serial_num, inode;
|
int serial_num;
|
||||||
|
RRNodeId inode;
|
||||||
t_trace* tptr;
|
t_trace* tptr;
|
||||||
|
|
||||||
auto& cluster_ctx = g_vpr_ctx.clustering();
|
auto& cluster_ctx = g_vpr_ctx.clustering();
|
||||||
|
@ -196,11 +197,11 @@ void get_serial_num() {
|
||||||
while (tptr != nullptr) {
|
while (tptr != nullptr) {
|
||||||
inode = tptr->index;
|
inode = tptr->index;
|
||||||
serial_num += (size_t(net_id) + 1)
|
serial_num += (size_t(net_id) + 1)
|
||||||
* (device_ctx.rr_nodes[inode].xlow() * (device_ctx.grid.width()) - device_ctx.rr_nodes[inode].yhigh());
|
* (device_ctx.rr_graph.node_xlow(inode) * (device_ctx.grid.width()) - device_ctx.rr_graph.node_yhigh(inode));
|
||||||
|
|
||||||
serial_num -= device_ctx.rr_nodes[inode].ptc_num() * (size_t(net_id) + 1) * 10;
|
serial_num -= device_ctx.rr_graph.node_ptc_num(inode) * (size_t(net_id) + 1) * 10;
|
||||||
|
|
||||||
serial_num -= device_ctx.rr_nodes[inode].type() * (size_t(net_id) + 1) * 100;
|
serial_num -= device_ctx.rr_graph.node_type(inode) * (size_t(net_id) + 1) * 100;
|
||||||
serial_num %= 2000000000; /* Prevent overflow */
|
serial_num %= 2000000000; /* Prevent overflow */
|
||||||
tptr = tptr->next;
|
tptr = tptr->next;
|
||||||
}
|
}
|
||||||
|
@ -336,8 +337,8 @@ bool feasible_routing() {
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
auto& route_ctx = g_vpr_ctx.routing();
|
auto& route_ctx = g_vpr_ctx.routing();
|
||||||
|
|
||||||
for (size_t inode = 0; inode < device_ctx.rr_graph.nodes().size(); inode++) {
|
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
|
||||||
if (route_ctx.rr_node_route_inf[inode].occ() > device_ctx.rr_nodes[inode].capacity()) {
|
if (route_ctx.rr_node_route_inf[inode].occ() > device_ctx.rr_graph.node_capacity(inode)) {
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,7 +415,7 @@ void pathfinder_update_path_cost(t_trace* route_segment_start,
|
||||||
} /* End while loop -- did an entire traceback. */
|
} /* End while loop -- did an entire traceback. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void pathfinder_update_single_node_cost(int inode, int add_or_sub, float pres_fac) {
|
void pathfinder_update_single_node_cost(const RRNodeId& inode, int add_or_sub, float pres_fac) {
|
||||||
/* Updates pathfinder's congestion cost by either adding or removing the
|
/* Updates pathfinder's congestion cost by either adding or removing the
|
||||||
* usage of a resource node. pres_cost is Pn in the Pathfinder paper.
|
* usage of a resource node. pres_cost is Pn in the Pathfinder paper.
|
||||||
* pres_cost is set according to the overuse that would result from having
|
* pres_cost is set according to the overuse that would result from having
|
||||||
|
@ -428,7 +429,7 @@ void pathfinder_update_single_node_cost(int inode, int add_or_sub, float pres_fa
|
||||||
// can't have negative occupancy
|
// can't have negative occupancy
|
||||||
VTR_ASSERT(occ >= 0);
|
VTR_ASSERT(occ >= 0);
|
||||||
|
|
||||||
int capacity = device_ctx.rr_nodes[inode].capacity();
|
int capacity = device_ctx.rr_graph.node_capacity(inode);
|
||||||
if (occ < capacity) {
|
if (occ < capacity) {
|
||||||
route_ctx.rr_node_route_inf[inode].pres_cost = 1.0;
|
route_ctx.rr_node_route_inf[inode].pres_cost = 1.0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -449,9 +450,9 @@ void pathfinder_update_cost(float pres_fac, float acc_fac) {
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
auto& route_ctx = g_vpr_ctx.mutable_routing();
|
auto& route_ctx = g_vpr_ctx.mutable_routing();
|
||||||
|
|
||||||
for (size_t inode = 0; inode < device_ctx.rr_graph.nodes().size(); inode++) {
|
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
|
||||||
occ = route_ctx.rr_node_route_inf[inode].occ();
|
occ = route_ctx.rr_node_route_inf[inode].occ();
|
||||||
capacity = device_ctx.rr_nodes[inode].capacity();
|
capacity = device_ctx.rr_graph.node_capacity(inode);
|
||||||
|
|
||||||
if (occ > capacity) {
|
if (occ > capacity) {
|
||||||
route_ctx.rr_node_route_inf[inode].acc_cost += (occ - capacity) * acc_fac;
|
route_ctx.rr_node_route_inf[inode].acc_cost += (occ - capacity) * acc_fac;
|
||||||
|
@ -496,9 +497,9 @@ void init_route_structs(int bb_factor) {
|
||||||
init_heap(device_ctx.grid);
|
init_heap(device_ctx.grid);
|
||||||
|
|
||||||
//Various look-ups
|
//Various look-ups
|
||||||
route_ctx.net_rr_terminals = load_net_rr_terminals(device_ctx.rr_node_indices);
|
route_ctx.net_rr_terminals = load_net_rr_terminals(device_ctx.rr_graph);
|
||||||
route_ctx.route_bb = load_route_bb(bb_factor);
|
route_ctx.route_bb = load_route_bb(bb_factor);
|
||||||
route_ctx.rr_blk_source = load_rr_clb_sources(device_ctx.rr_node_indices);
|
route_ctx.rr_blk_source = load_rr_clb_sources(device_ctx.rr_graph);
|
||||||
route_ctx.clb_opins_used_locally = alloc_and_load_clb_opins_used_locally();
|
route_ctx.clb_opins_used_locally = alloc_and_load_clb_opins_used_locally();
|
||||||
route_ctx.net_status.resize(cluster_ctx.clb_nlist.nets().size());
|
route_ctx.net_status.resize(cluster_ctx.clb_nlist.nets().size());
|
||||||
|
|
||||||
|
@ -550,14 +551,15 @@ update_traceback(t_heap* hptr, ClusterNetId net_id) {
|
||||||
|
|
||||||
//Traces back a new routing branch starting from the specified 'node' and working backwards to any existing routing.
|
//Traces back a new routing branch starting from the specified 'node' and working backwards to any existing routing.
|
||||||
//Returns the new branch, and also updates trace_nodes for any new nodes which are included in the branches traceback.
|
//Returns the new branch, and also updates trace_nodes for any new nodes which are included in the branches traceback.
|
||||||
static t_trace_branch traceback_branch(int node, std::unordered_set<int>& trace_nodes) {
|
static t_trace_branch traceback_branch(const RRNodeId& node, std::unordered_set<RRNodeId>& trace_nodes) {
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
auto& route_ctx = g_vpr_ctx.routing();
|
auto& route_ctx = g_vpr_ctx.routing();
|
||||||
|
|
||||||
auto rr_type = device_ctx.rr_nodes[node].type();
|
auto rr_type = device_ctx.rr_graph.node_type(node);
|
||||||
if (rr_type != SINK) {
|
if (rr_type != SINK) {
|
||||||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
|
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
|
||||||
"in traceback_branch: Expected type = SINK (%d).\n");
|
"in traceback_branch: Expected type = SINK (%d).\n",
|
||||||
|
size_t(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
//We construct the main traceback by walking from the given node back to the source,
|
//We construct the main traceback by walking from the given node back to the source,
|
||||||
|
@ -570,16 +572,16 @@ static t_trace_branch traceback_branch(int node, std::unordered_set<int>& trace_
|
||||||
|
|
||||||
trace_nodes.insert(node);
|
trace_nodes.insert(node);
|
||||||
|
|
||||||
std::vector<int> new_nodes_added_to_traceback = {node};
|
std::vector<RRNodeId> new_nodes_added_to_traceback = {node};
|
||||||
|
|
||||||
auto iedge = route_ctx.rr_node_route_inf[node].prev_edge;
|
RREdgeId iedge = route_ctx.rr_node_route_inf[node].prev_edge;
|
||||||
int inode = route_ctx.rr_node_route_inf[node].prev_node;
|
RRNodeId inode = route_ctx.rr_node_route_inf[node].prev_node;
|
||||||
|
|
||||||
while (inode != NO_PREVIOUS) {
|
while (inode != RRNodeId::INVALID()) {
|
||||||
//Add the current node to the head of traceback
|
//Add the current node to the head of traceback
|
||||||
t_trace* prev_ptr = alloc_trace_data();
|
t_trace* prev_ptr = alloc_trace_data();
|
||||||
prev_ptr->index = inode;
|
prev_ptr->index = inode;
|
||||||
prev_ptr->iswitch = device_ctx.rr_nodes[inode].edge_switch(iedge);
|
prev_ptr->iswitch = (short)size_t(device_ctx.rr_graph.edge_switch(iedge));
|
||||||
prev_ptr->next = branch_head;
|
prev_ptr->next = branch_head;
|
||||||
branch_head = prev_ptr;
|
branch_head = prev_ptr;
|
||||||
|
|
||||||
|
@ -597,7 +599,7 @@ static t_trace_branch traceback_branch(int node, std::unordered_set<int>& trace_
|
||||||
//We next re-expand all the main-branch nodes to add any non-configurably connected side branches
|
//We next re-expand all the main-branch nodes to add any non-configurably connected side branches
|
||||||
// We are careful to do this *after* the main branch is constructed to ensure nodes which are both
|
// We are careful to do this *after* the main branch is constructed to ensure nodes which are both
|
||||||
// non-configurably connected *and* part of the main branch are only added to the traceback once.
|
// non-configurably connected *and* part of the main branch are only added to the traceback once.
|
||||||
for (int new_node : new_nodes_added_to_traceback) {
|
for (const RRNodeId& new_node : new_nodes_added_to_traceback) {
|
||||||
//Expand each main branch node
|
//Expand each main branch node
|
||||||
std::tie(branch_head, branch_tail) = add_trace_non_configurable(branch_head, branch_tail, new_node, trace_nodes);
|
std::tie(branch_head, branch_tail) = add_trace_non_configurable(branch_head, branch_tail, new_node, trace_nodes);
|
||||||
}
|
}
|
||||||
|
@ -608,7 +610,7 @@ static t_trace_branch traceback_branch(int node, std::unordered_set<int>& trace_
|
||||||
//Traces any non-configurable subtrees from branch_head, returning the new branch_head and updating trace_nodes
|
//Traces any non-configurable subtrees from branch_head, returning the new branch_head and updating trace_nodes
|
||||||
//
|
//
|
||||||
//This effectively does a depth-first traversal
|
//This effectively does a depth-first traversal
|
||||||
static std::pair<t_trace*, t_trace*> add_trace_non_configurable(t_trace* head, t_trace* tail, int node, std::unordered_set<int>& trace_nodes) {
|
static std::pair<t_trace*, t_trace*> add_trace_non_configurable(t_trace* head, t_trace* tail, const RRNodeId& node, std::unordered_set<RRNodeId>& trace_nodes) {
|
||||||
//Trace any non-configurable subtrees
|
//Trace any non-configurable subtrees
|
||||||
t_trace* subtree_head = nullptr;
|
t_trace* subtree_head = nullptr;
|
||||||
t_trace* subtree_tail = nullptr;
|
t_trace* subtree_tail = nullptr;
|
||||||
|
@ -632,17 +634,17 @@ static std::pair<t_trace*, t_trace*> add_trace_non_configurable(t_trace* head, t
|
||||||
}
|
}
|
||||||
|
|
||||||
//Recursive helper function for add_trace_non_configurable()
|
//Recursive helper function for add_trace_non_configurable()
|
||||||
static std::pair<t_trace*, t_trace*> add_trace_non_configurable_recurr(int node, std::unordered_set<int>& trace_nodes, int depth) {
|
static std::pair<t_trace*, t_trace*> add_trace_non_configurable_recurr(const RRNodeId& node, std::unordered_set<RRNodeId>& trace_nodes, int depth) {
|
||||||
t_trace* head = nullptr;
|
t_trace* head = nullptr;
|
||||||
t_trace* tail = nullptr;
|
t_trace* tail = nullptr;
|
||||||
|
|
||||||
//Record the non-configurable out-going edges
|
//Record the non-configurable out-going edges
|
||||||
std::vector<t_edge_size> unvisited_non_configurable_edges;
|
std::vector<RREdgeId> unvisited_non_configurable_edges;
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
for (auto iedge : device_ctx.rr_nodes[node].non_configurable_edges()) {
|
for (auto iedge : device_ctx.rr_graph.node_non_configurable_out_edges(node)) {
|
||||||
VTR_ASSERT_SAFE(!device_ctx.rr_nodes[node].edge_is_configurable(iedge));
|
VTR_ASSERT_SAFE(!device_ctx.rr_graph.edge_is_configurable(iedge));
|
||||||
|
|
||||||
int to_node = device_ctx.rr_nodes[node].edge_sink_node(iedge);
|
const RRNodeId& to_node = device_ctx.rr_graph.edge_sink_node(iedge);
|
||||||
|
|
||||||
if (!trace_nodes.count(to_node)) {
|
if (!trace_nodes.count(to_node)) {
|
||||||
unvisited_non_configurable_edges.push_back(iedge);
|
unvisited_non_configurable_edges.push_back(iedge);
|
||||||
|
@ -665,8 +667,8 @@ static std::pair<t_trace*, t_trace*> add_trace_non_configurable_recurr(int node,
|
||||||
} else {
|
} else {
|
||||||
//Recursive case: intermediate node with non-configurable edges
|
//Recursive case: intermediate node with non-configurable edges
|
||||||
for (auto iedge : unvisited_non_configurable_edges) {
|
for (auto iedge : unvisited_non_configurable_edges) {
|
||||||
int to_node = device_ctx.rr_nodes[node].edge_sink_node(iedge);
|
const RRNodeId& to_node = device_ctx.rr_graph.edge_sink_node(iedge);
|
||||||
int iswitch = device_ctx.rr_nodes[node].edge_switch(iedge);
|
int iswitch = (int)size_t(device_ctx.rr_graph.edge_switch(iedge));
|
||||||
|
|
||||||
VTR_ASSERT(!trace_nodes.count(to_node));
|
VTR_ASSERT(!trace_nodes.count(to_node));
|
||||||
trace_nodes.insert(node);
|
trace_nodes.insert(node);
|
||||||
|
@ -725,7 +727,7 @@ float get_rr_cong_cost(const RRNodeId& inode) {
|
||||||
|
|
||||||
auto itr = device_ctx.rr_node_to_non_config_node_set.find(inode);
|
auto itr = device_ctx.rr_node_to_non_config_node_set.find(inode);
|
||||||
if (itr != device_ctx.rr_node_to_non_config_node_set.end()) {
|
if (itr != device_ctx.rr_node_to_non_config_node_set.end()) {
|
||||||
for (const RRNodeId& node : device_ctx.rr_non_config_node_sets[itr->second]) {
|
for (RRNodeId node : device_ctx.rr_non_config_node_sets[itr->second]) {
|
||||||
if (node == inode) {
|
if (node == inode) {
|
||||||
continue; //Already included above
|
continue; //Already included above
|
||||||
}
|
}
|
||||||
|
@ -755,22 +757,20 @@ static float get_single_rr_cong_cost(const RRNodeId& inode) {
|
||||||
* the same net to two inputs of an and-gate (and-gate inputs are logically *
|
* the same net to two inputs of an and-gate (and-gate inputs are logically *
|
||||||
* equivalent, so both will connect to the same SINK). */
|
* equivalent, so both will connect to the same SINK). */
|
||||||
void mark_ends(ClusterNetId net_id) {
|
void mark_ends(ClusterNetId net_id) {
|
||||||
unsigned int ipin;
|
|
||||||
int inode;
|
|
||||||
|
|
||||||
auto& cluster_ctx = g_vpr_ctx.clustering();
|
auto& cluster_ctx = g_vpr_ctx.clustering();
|
||||||
auto& route_ctx = g_vpr_ctx.mutable_routing();
|
auto& route_ctx = g_vpr_ctx.mutable_routing();
|
||||||
|
|
||||||
for (ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++) {
|
for (unsigned int ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++) {
|
||||||
inode = route_ctx.net_rr_terminals[net_id][ipin];
|
const RRNodeId& inode = route_ctx.net_rr_terminals[net_id][ipin];
|
||||||
route_ctx.rr_node_route_inf[inode].target_flag++;
|
route_ctx.rr_node_route_inf[inode].target_flag++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark_remaining_ends(const std::vector<int>& remaining_sinks) {
|
void mark_remaining_ends(const std::vector<RRNodeId>& remaining_sinks) {
|
||||||
// like mark_ends, but only performs it for the remaining sinks of a net
|
// like mark_ends, but only performs it for the remaining sinks of a net
|
||||||
auto& route_ctx = g_vpr_ctx.mutable_routing();
|
auto& route_ctx = g_vpr_ctx.mutable_routing();
|
||||||
for (int sink_node : remaining_sinks)
|
for (const RRNodeId& sink_node : remaining_sinks)
|
||||||
++route_ctx.rr_node_route_inf[sink_node].target_flag;
|
++route_ctx.rr_node_route_inf[sink_node].target_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,10 +1016,9 @@ void reset_rr_node_route_structs() {
|
||||||
|
|
||||||
VTR_ASSERT(route_ctx.rr_node_route_inf.size() == size_t(device_ctx.rr_graph.nodes().size()));
|
VTR_ASSERT(route_ctx.rr_node_route_inf.size() == size_t(device_ctx.rr_graph.nodes().size()));
|
||||||
|
|
||||||
for (size_t inode = 0; inode < device_ctx.rr_graph.nodes().size(); inode++) {
|
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
|
||||||
route_ctx.rr_node_route_inf[inode].prev_node = NO_PREVIOUS;
|
route_ctx.rr_node_route_inf[inode].prev_node = RRNodeId::INVALID();
|
||||||
route_ctx.rr_node_route_inf[inode].prev_node_id = RRNodeId::INVALID();
|
route_ctx.rr_node_route_inf[inode].prev_edge = RREdgeId::INVALID();
|
||||||
route_ctx.rr_node_route_inf[inode].prev_edge = NO_PREVIOUS;
|
|
||||||
route_ctx.rr_node_route_inf[inode].pres_cost = 1.0;
|
route_ctx.rr_node_route_inf[inode].pres_cost = 1.0;
|
||||||
route_ctx.rr_node_route_inf[inode].acc_cost = 1.0;
|
route_ctx.rr_node_route_inf[inode].acc_cost = 1.0;
|
||||||
route_ctx.rr_node_route_inf[inode].path_cost = std::numeric_limits<float>::infinity();
|
route_ctx.rr_node_route_inf[inode].path_cost = std::numeric_limits<float>::infinity();
|
||||||
|
@ -1032,8 +1031,8 @@ void reset_rr_node_route_structs() {
|
||||||
/* Allocates and loads the route_ctx.net_rr_terminals data structure. For each net it stores the rr_node *
|
/* Allocates and loads the route_ctx.net_rr_terminals data structure. For each net it stores the rr_node *
|
||||||
* index of the SOURCE of the net and all the SINKs of the net [clb_nlist.nets()][clb_nlist.net_pins()]. *
|
* index of the SOURCE of the net and all the SINKs of the net [clb_nlist.nets()][clb_nlist.net_pins()]. *
|
||||||
* Entry [inet][pnum] stores the rr index corresponding to the SOURCE (opin) or SINK (ipin) of the pin. */
|
* Entry [inet][pnum] stores the rr index corresponding to the SOURCE (opin) or SINK (ipin) of the pin. */
|
||||||
static vtr::vector<ClusterNetId, std::vector<int>> load_net_rr_terminals(const t_rr_node_indices& L_rr_node_indices) {
|
static vtr::vector<ClusterNetId, std::vector<RRNodeId>> load_net_rr_terminals(const RRGraph& rr_graph) {
|
||||||
vtr::vector<ClusterNetId, std::vector<int>> net_rr_terminals;
|
vtr::vector<ClusterNetId, std::vector<RRNodeId>> net_rr_terminals;
|
||||||
|
|
||||||
auto& cluster_ctx = g_vpr_ctx.clustering();
|
auto& cluster_ctx = g_vpr_ctx.clustering();
|
||||||
auto& place_ctx = g_vpr_ctx.placement();
|
auto& place_ctx = g_vpr_ctx.placement();
|
||||||
|
@ -1059,8 +1058,8 @@ static vtr::vector<ClusterNetId, std::vector<int>> load_net_rr_terminals(const t
|
||||||
|
|
||||||
int iclass = type->pin_class[phys_pin];
|
int iclass = type->pin_class[phys_pin];
|
||||||
|
|
||||||
int inode = get_rr_node_index(L_rr_node_indices, i, j, (pin_count == 0 ? SOURCE : SINK), /* First pin is driver */
|
RRNodeId inode = rr_graph.find_node(i, j, (pin_count == 0 ? SOURCE : SINK), /* First pin is driver */
|
||||||
iclass);
|
iclass);
|
||||||
net_rr_terminals[net_id][pin_count] = inode;
|
net_rr_terminals[net_id][pin_count] = inode;
|
||||||
pin_count++;
|
pin_count++;
|
||||||
}
|
}
|
||||||
|
@ -1074,10 +1073,9 @@ static vtr::vector<ClusterNetId, std::vector<int>> load_net_rr_terminals(const t
|
||||||
* they are used only to reserve pins for locally used OPINs in the router. *
|
* they are used only to reserve pins for locally used OPINs in the router. *
|
||||||
* [0..cluster_ctx.clb_nlist.blocks().size()-1][0..num_class-1]. *
|
* [0..cluster_ctx.clb_nlist.blocks().size()-1][0..num_class-1]. *
|
||||||
* The values for blocks that are padsare NOT valid. */
|
* The values for blocks that are padsare NOT valid. */
|
||||||
static vtr::vector<ClusterBlockId, std::vector<int>> load_rr_clb_sources(const t_rr_node_indices& L_rr_node_indices) {
|
static vtr::vector<ClusterBlockId, std::vector<RRNodeId>> load_rr_clb_sources(const RRGraph& rr_graph) {
|
||||||
vtr::vector<ClusterBlockId, std::vector<int>> rr_blk_source;
|
vtr::vector<ClusterBlockId, std::vector<RRNodeId>> rr_blk_source;
|
||||||
|
|
||||||
int i, j, iclass, inode;
|
|
||||||
int class_low, class_high;
|
int class_low, class_high;
|
||||||
t_rr_type rr_type;
|
t_rr_type rr_type;
|
||||||
|
|
||||||
|
@ -1090,20 +1088,20 @@ static vtr::vector<ClusterBlockId, std::vector<int>> load_rr_clb_sources(const t
|
||||||
auto type = physical_tile_type(blk_id);
|
auto type = physical_tile_type(blk_id);
|
||||||
get_class_range_for_block(blk_id, &class_low, &class_high);
|
get_class_range_for_block(blk_id, &class_low, &class_high);
|
||||||
rr_blk_source[blk_id].resize(type->num_class);
|
rr_blk_source[blk_id].resize(type->num_class);
|
||||||
for (iclass = 0; iclass < type->num_class; iclass++) {
|
for (int iclass = 0; iclass < type->num_class; iclass++) {
|
||||||
if (iclass >= class_low && iclass <= class_high) {
|
if (iclass >= class_low && iclass <= class_high) {
|
||||||
i = place_ctx.block_locs[blk_id].loc.x;
|
int i = place_ctx.block_locs[blk_id].loc.x;
|
||||||
j = place_ctx.block_locs[blk_id].loc.y;
|
int j = place_ctx.block_locs[blk_id].loc.y;
|
||||||
|
|
||||||
if (type->class_inf[iclass].type == DRIVER)
|
if (type->class_inf[iclass].type == DRIVER)
|
||||||
rr_type = SOURCE;
|
rr_type = SOURCE;
|
||||||
else
|
else
|
||||||
rr_type = SINK;
|
rr_type = SINK;
|
||||||
|
|
||||||
inode = get_rr_node_index(L_rr_node_indices, i, j, rr_type, iclass);
|
const RRNodeId& inode = rr_graph.find_node(i, j, rr_type, iclass);
|
||||||
rr_blk_source[blk_id][iclass] = inode;
|
rr_blk_source[blk_id][iclass] = inode;
|
||||||
} else {
|
} else {
|
||||||
rr_blk_source[blk_id][iclass] = OPEN;
|
rr_blk_source[blk_id][iclass] = RRNodeId::INVALID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1149,31 +1147,29 @@ t_bb load_net_route_bb(ClusterNetId net_id, int bb_factor) {
|
||||||
int max_dim = std::max<int>(device_ctx.grid.width() - 1, device_ctx.grid.height() - 1);
|
int max_dim = std::max<int>(device_ctx.grid.width() - 1, device_ctx.grid.height() - 1);
|
||||||
bb_factor = std::min(bb_factor, max_dim);
|
bb_factor = std::min(bb_factor, max_dim);
|
||||||
|
|
||||||
int driver_rr = route_ctx.net_rr_terminals[net_id][0];
|
const RRNodeId& driver_rr = route_ctx.net_rr_terminals[net_id][0];
|
||||||
const t_rr_node& source_node = device_ctx.rr_nodes[driver_rr];
|
VTR_ASSERT(device_ctx.rr_graph.node_type(driver_rr) == SOURCE);
|
||||||
VTR_ASSERT(source_node.type() == SOURCE);
|
|
||||||
|
|
||||||
VTR_ASSERT(source_node.xlow() <= source_node.xhigh());
|
VTR_ASSERT(device_ctx.rr_graph.node_xlow(driver_rr) <= device_ctx.rr_graph.node_xhigh(driver_rr));
|
||||||
VTR_ASSERT(source_node.ylow() <= source_node.yhigh());
|
VTR_ASSERT(device_ctx.rr_graph.node_ylow(driver_rr) <= device_ctx.rr_graph.node_yhigh(driver_rr));
|
||||||
|
|
||||||
int xmin = source_node.xlow();
|
int xmin = device_ctx.rr_graph.node_xlow(driver_rr);
|
||||||
int ymin = source_node.ylow();
|
int ymin = device_ctx.rr_graph.node_ylow(driver_rr);
|
||||||
int xmax = source_node.xhigh();
|
int xmax = device_ctx.rr_graph.node_xhigh(driver_rr);
|
||||||
int ymax = source_node.yhigh();
|
int ymax = device_ctx.rr_graph.node_yhigh(driver_rr);
|
||||||
|
|
||||||
auto net_sinks = cluster_ctx.clb_nlist.net_sinks(net_id);
|
auto net_sinks = cluster_ctx.clb_nlist.net_sinks(net_id);
|
||||||
for (size_t ipin = 1; ipin < net_sinks.size() + 1; ++ipin) { //Start at 1 since looping through sinks
|
for (size_t ipin = 1; ipin < net_sinks.size() + 1; ++ipin) { //Start at 1 since looping through sinks
|
||||||
int sink_rr = route_ctx.net_rr_terminals[net_id][ipin];
|
const RRNodeId& sink_rr = route_ctx.net_rr_terminals[net_id][ipin];
|
||||||
const t_rr_node& sink_node = device_ctx.rr_nodes[sink_rr];
|
VTR_ASSERT(device_ctx.rr_graph.node_type(sink_rr) == SINK);
|
||||||
VTR_ASSERT(sink_node.type() == SINK);
|
|
||||||
|
|
||||||
VTR_ASSERT(sink_node.xlow() <= sink_node.xhigh());
|
VTR_ASSERT(device_ctx.rr_graph.node_xlow(sink_rr) <= device_ctx.rr_graph.node_xhigh(sink_rr));
|
||||||
VTR_ASSERT(sink_node.ylow() <= sink_node.yhigh());
|
VTR_ASSERT(device_ctx.rr_graph.node_ylow(sink_rr) <= device_ctx.rr_graph.node_yhigh(sink_rr));
|
||||||
|
|
||||||
xmin = std::min<int>(xmin, sink_node.xlow());
|
xmin = std::min<int>(xmin, device_ctx.rr_graph.node_xlow(sink_rr));
|
||||||
xmax = std::max<int>(xmax, sink_node.xhigh());
|
xmax = std::max<int>(xmax, device_ctx.rr_graph.node_xhigh(sink_rr));
|
||||||
ymin = std::min<int>(ymin, sink_node.ylow());
|
ymin = std::min<int>(ymin, device_ctx.rr_graph.node_ylow(sink_rr));
|
||||||
ymax = std::max<int>(ymax, sink_node.yhigh());
|
ymax = std::max<int>(ymax, device_ctx.rr_graph.node_yhigh(sink_rr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Want the channels on all 4 sides to be usuable, even if bb_factor = 0. */
|
/* Want the channels on all 4 sides to be usuable, even if bb_factor = 0. */
|
||||||
|
@ -1271,11 +1267,11 @@ void push_back_node(const RRNodeId& inode, float total_cost, const RRNodeId& pre
|
||||||
* bottom up with build_heap */
|
* bottom up with build_heap */
|
||||||
|
|
||||||
auto& route_ctx = g_vpr_ctx.routing();
|
auto& route_ctx = g_vpr_ctx.routing();
|
||||||
if (total_cost >= route_ctx.rr_node_route_inf[size_t(inode)].path_cost)
|
if (total_cost >= route_ctx.rr_node_route_inf[inode].path_cost)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
t_heap* hptr = alloc_heap_data();
|
t_heap* hptr = alloc_heap_data();
|
||||||
hptr->index = size_t(inode);
|
hptr->index = inode;
|
||||||
hptr->cost = total_cost;
|
hptr->cost = total_cost;
|
||||||
hptr->u.prev.node = prev_node;
|
hptr->u.prev.node = prev_node;
|
||||||
hptr->u.prev.edge = prev_edge;
|
hptr->u.prev.edge = prev_edge;
|
||||||
|
@ -1317,7 +1313,7 @@ void verify_extract_top() {
|
||||||
std::cout << "starting to compare top elements\n";
|
std::cout << "starting to compare top elements\n";
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (!is_empty_heap()) {
|
while (!is_empty_heap()) {
|
||||||
while (heap_copy[i]->index == OPEN)
|
while (heap_copy[i]->index == RRNodeId::INVALID())
|
||||||
++i; // skip the ones that won't be extracted
|
++i; // skip the ones that won't be extracted
|
||||||
auto top = get_heap_head();
|
auto top = get_heap_head();
|
||||||
if (abs(top->cost - heap_copy[i]->cost) > float_epsilon)
|
if (abs(top->cost - heap_copy[i]->cost) > float_epsilon)
|
||||||
|
@ -1372,7 +1368,7 @@ get_heap_head() {
|
||||||
}
|
}
|
||||||
heap_::sift_up(hole, heap[heap_tail]);
|
heap_::sift_up(hole, heap[heap_tail]);
|
||||||
|
|
||||||
} while (cheapest->index == OPEN); /* Get another one if invalid entry. */
|
} while (cheapest->index == RRNodeId::INVALID()); /* Get another one if invalid entry. */
|
||||||
|
|
||||||
return (cheapest);
|
return (cheapest);
|
||||||
}
|
}
|
||||||
|
@ -1401,9 +1397,9 @@ alloc_heap_data() {
|
||||||
temp_ptr->cost = 0.;
|
temp_ptr->cost = 0.;
|
||||||
temp_ptr->backward_path_cost = 0.;
|
temp_ptr->backward_path_cost = 0.;
|
||||||
temp_ptr->R_upstream = 0.;
|
temp_ptr->R_upstream = 0.;
|
||||||
temp_ptr->index = OPEN;
|
temp_ptr->index = RRNodeId::INVALID();
|
||||||
temp_ptr->u.prev.node = NO_PREVIOUS;
|
temp_ptr->u.prev.node = RRNodeId::INVALID();
|
||||||
temp_ptr->u.prev.edge = NO_PREVIOUS;
|
temp_ptr->u.prev.edge = RREdgeId::INVALID();
|
||||||
return (temp_ptr);
|
return (temp_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1467,18 +1463,18 @@ void print_route(FILE* fp, const vtr::vector<ClusterNetId, t_traceback>& traceba
|
||||||
t_trace* tptr = route_ctx.trace[net_id].head;
|
t_trace* tptr = route_ctx.trace[net_id].head;
|
||||||
|
|
||||||
while (tptr != nullptr) {
|
while (tptr != nullptr) {
|
||||||
int inode = tptr->index;
|
RRNodeId inode = tptr->index;
|
||||||
t_rr_type rr_type = device_ctx.rr_nodes[inode].type();
|
t_rr_type rr_type = device_ctx.rr_graph.node_type(inode);
|
||||||
int ilow = device_ctx.rr_nodes[inode].xlow();
|
int ilow = device_ctx.rr_graph.node_xlow(inode);
|
||||||
int jlow = device_ctx.rr_nodes[inode].ylow();
|
int jlow = device_ctx.rr_graph.node_ylow(inode);
|
||||||
|
|
||||||
fprintf(fp, "Node:\t%d\t%6s (%d,%d) ", inode,
|
fprintf(fp, "Node:\t%ld\t%6s (%d,%d) ", size_t(inode),
|
||||||
device_ctx.rr_nodes[inode].type_string(), ilow, jlow);
|
rr_node_typename[device_ctx.rr_graph.node_type(inode)], ilow, jlow);
|
||||||
|
|
||||||
if ((ilow != device_ctx.rr_nodes[inode].xhigh())
|
if ((ilow != device_ctx.rr_graph.node_xhigh(inode))
|
||||||
|| (jlow != device_ctx.rr_nodes[inode].yhigh()))
|
|| (jlow != device_ctx.rr_graph.node_yhigh(inode)))
|
||||||
fprintf(fp, "to (%d,%d) ", device_ctx.rr_nodes[inode].xhigh(),
|
fprintf(fp, "to (%d,%d) ", device_ctx.rr_graph.node_xhigh(inode),
|
||||||
device_ctx.rr_nodes[inode].yhigh());
|
device_ctx.rr_graph.node_yhigh(inode));
|
||||||
|
|
||||||
switch (rr_type) {
|
switch (rr_type) {
|
||||||
case IPIN:
|
case IPIN:
|
||||||
|
@ -1507,14 +1503,14 @@ void print_route(FILE* fp, const vtr::vector<ClusterNetId, t_traceback>& traceba
|
||||||
default:
|
default:
|
||||||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
|
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
|
||||||
"in print_route: Unexpected traceback element type: %d (%s).\n",
|
"in print_route: Unexpected traceback element type: %d (%s).\n",
|
||||||
rr_type, device_ctx.rr_nodes[inode].type_string());
|
rr_type, rr_node_typename[device_ctx.rr_graph.node_type(inode)]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "%d ", device_ctx.rr_nodes[inode].ptc_num());
|
fprintf(fp, "%d ", device_ctx.rr_graph.node_ptc_num(inode));
|
||||||
|
|
||||||
if (!is_io_type(device_ctx.grid[ilow][jlow].type) && (rr_type == IPIN || rr_type == OPIN)) {
|
if (!is_io_type(device_ctx.grid[ilow][jlow].type) && (rr_type == IPIN || rr_type == OPIN)) {
|
||||||
int pin_num = device_ctx.rr_nodes[inode].ptc_num();
|
int pin_num = device_ctx.rr_graph.node_ptc_num(inode);
|
||||||
int xoffset = device_ctx.grid[ilow][jlow].width_offset;
|
int xoffset = device_ctx.grid[ilow][jlow].width_offset;
|
||||||
int yoffset = device_ctx.grid[ilow][jlow].height_offset;
|
int yoffset = device_ctx.grid[ilow][jlow].height_offset;
|
||||||
ClusterBlockId iblock = place_ctx.grid_blocks[ilow - xoffset][jlow - yoffset].blocks[0];
|
ClusterBlockId iblock = place_ctx.grid_blocks[ilow - xoffset][jlow - yoffset].blocks[0];
|
||||||
|
@ -1600,8 +1596,7 @@ void print_route(const char* placement_file, const char* route_file) {
|
||||||
// To model this we 'reserve' these locally used outputs, ensuring that the router will not use them (as if it did
|
// To model this we 'reserve' these locally used outputs, ensuring that the router will not use them (as if it did
|
||||||
// this would equate to duplicating a BLE into an already in-use BLE instance, which is clearly incorrect).
|
// this would equate to duplicating a BLE into an already in-use BLE instance, which is clearly incorrect).
|
||||||
void reserve_locally_used_opins(float pres_fac, float acc_fac, bool rip_up_local_opins) {
|
void reserve_locally_used_opins(float pres_fac, float acc_fac, bool rip_up_local_opins) {
|
||||||
int num_local_opin, inode, from_node, iconn, num_edges, to_node;
|
int num_local_opin;
|
||||||
int iclass, ipin;
|
|
||||||
float cost;
|
float cost;
|
||||||
t_heap* heap_head_ptr;
|
t_heap* heap_head_ptr;
|
||||||
t_physical_tile_type_ptr type;
|
t_physical_tile_type_ptr type;
|
||||||
|
@ -1613,15 +1608,15 @@ void reserve_locally_used_opins(float pres_fac, float acc_fac, bool rip_up_local
|
||||||
if (rip_up_local_opins) {
|
if (rip_up_local_opins) {
|
||||||
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
|
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
|
||||||
type = physical_tile_type(blk_id);
|
type = physical_tile_type(blk_id);
|
||||||
for (iclass = 0; iclass < type->num_class; iclass++) {
|
for (int iclass = 0; iclass < type->num_class; iclass++) {
|
||||||
num_local_opin = route_ctx.clb_opins_used_locally[blk_id][iclass].size();
|
num_local_opin = route_ctx.clb_opins_used_locally[blk_id][iclass].size();
|
||||||
|
|
||||||
if (num_local_opin == 0) continue;
|
if (num_local_opin == 0) continue;
|
||||||
VTR_ASSERT(type->class_inf[iclass].equivalence == PortEquivalence::INSTANCE);
|
VTR_ASSERT(type->class_inf[iclass].equivalence == PortEquivalence::INSTANCE);
|
||||||
|
|
||||||
/* Always 0 for pads and for RECEIVER (IPIN) classes */
|
/* Always 0 for pads and for RECEIVER (IPIN) classes */
|
||||||
for (ipin = 0; ipin < num_local_opin; ipin++) {
|
for (int ipin = 0; ipin < num_local_opin; ipin++) {
|
||||||
inode = route_ctx.clb_opins_used_locally[blk_id][iclass][ipin];
|
const RRNodeId& inode = route_ctx.clb_opins_used_locally[blk_id][iclass][ipin];
|
||||||
adjust_one_rr_occ_and_apcost(inode, -1, pres_fac, acc_fac);
|
adjust_one_rr_occ_and_apcost(inode, -1, pres_fac, acc_fac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1630,7 +1625,7 @@ void reserve_locally_used_opins(float pres_fac, float acc_fac, bool rip_up_local
|
||||||
|
|
||||||
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
|
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
|
||||||
type = physical_tile_type(blk_id);
|
type = physical_tile_type(blk_id);
|
||||||
for (iclass = 0; iclass < type->num_class; iclass++) {
|
for (int iclass = 0; iclass < type->num_class; iclass++) {
|
||||||
num_local_opin = route_ctx.clb_opins_used_locally[blk_id][iclass].size();
|
num_local_opin = route_ctx.clb_opins_used_locally[blk_id][iclass].size();
|
||||||
|
|
||||||
if (num_local_opin == 0) continue;
|
if (num_local_opin == 0) continue;
|
||||||
|
@ -1642,25 +1637,24 @@ void reserve_locally_used_opins(float pres_fac, float acc_fac, bool rip_up_local
|
||||||
//congestion cost are popped-off/reserved first. (Intuitively, we want
|
//congestion cost are popped-off/reserved first. (Intuitively, we want
|
||||||
//the reserved OPINs to move out of the way of congestion, by preferring
|
//the reserved OPINs to move out of the way of congestion, by preferring
|
||||||
//to reserve OPINs with lower congestion costs).
|
//to reserve OPINs with lower congestion costs).
|
||||||
from_node = route_ctx.rr_blk_source[blk_id][iclass];
|
const RRNodeId& from_node = route_ctx.rr_blk_source[blk_id][iclass];
|
||||||
num_edges = device_ctx.rr_nodes[from_node].num_edges();
|
for (const RREdgeId& iconn : device_ctx.rr_graph.node_out_edges(from_node)) {
|
||||||
for (iconn = 0; iconn < num_edges; iconn++) {
|
const RRNodeId& to_node = device_ctx.rr_graph.edge_sink_node(iconn);
|
||||||
to_node = device_ctx.rr_nodes[from_node].edge_sink_node(iconn);
|
|
||||||
|
|
||||||
VTR_ASSERT(device_ctx.rr_nodes[to_node].type() == OPIN);
|
VTR_ASSERT(device_ctx.rr_graph.node_type(to_node) == OPIN);
|
||||||
|
|
||||||
//Add the OPIN to the heap according to it's congestion cost
|
//Add the OPIN to the heap according to it's congestion cost
|
||||||
cost = get_rr_cong_cost(to_node);
|
cost = get_rr_cong_cost(to_node);
|
||||||
node_to_heap(to_node, cost, OPEN, OPEN, 0., 0.);
|
node_to_heap(to_node, cost, RRNodeId::INVALID(), RREdgeId::INVALID(), 0., 0.);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ipin = 0; ipin < num_local_opin; ipin++) {
|
for (int ipin = 0; ipin < num_local_opin; ipin++) {
|
||||||
//Pop the nodes off the heap. We get them from the heap so we
|
//Pop the nodes off the heap. We get them from the heap so we
|
||||||
//reserve those pins with lowest congestion cost first.
|
//reserve those pins with lowest congestion cost first.
|
||||||
heap_head_ptr = get_heap_head();
|
heap_head_ptr = get_heap_head();
|
||||||
inode = heap_head_ptr->index;
|
const RRNodeId& inode = heap_head_ptr->index;
|
||||||
|
|
||||||
VTR_ASSERT(device_ctx.rr_nodes[inode].type() == OPIN);
|
VTR_ASSERT(device_ctx.rr_graph.node_type(inode) == OPIN);
|
||||||
|
|
||||||
adjust_one_rr_occ_and_apcost(inode, 1, pres_fac, acc_fac);
|
adjust_one_rr_occ_and_apcost(inode, 1, pres_fac, acc_fac);
|
||||||
route_ctx.clb_opins_used_locally[blk_id][iclass][ipin] = inode;
|
route_ctx.clb_opins_used_locally[blk_id][iclass][ipin] = inode;
|
||||||
|
@ -1672,7 +1666,7 @@ void reserve_locally_used_opins(float pres_fac, float acc_fac, bool rip_up_local
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adjust_one_rr_occ_and_apcost(int inode, int add_or_sub, float pres_fac, float acc_fac) {
|
static void adjust_one_rr_occ_and_apcost(const RRNodeId& inode, int add_or_sub, float pres_fac, float acc_fac) {
|
||||||
/* Increments or decrements (depending on add_or_sub) the occupancy of *
|
/* Increments or decrements (depending on add_or_sub) the occupancy of *
|
||||||
* one rr_node, and adjusts the present cost of that node appropriately. */
|
* one rr_node, and adjusts the present cost of that node appropriately. */
|
||||||
|
|
||||||
|
@ -1680,7 +1674,7 @@ static void adjust_one_rr_occ_and_apcost(int inode, int add_or_sub, float pres_f
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
|
|
||||||
int new_occ = route_ctx.rr_node_route_inf[inode].occ() + add_or_sub;
|
int new_occ = route_ctx.rr_node_route_inf[inode].occ() + add_or_sub;
|
||||||
int capacity = device_ctx.rr_nodes[inode].capacity();
|
int capacity = device_ctx.rr_graph.node_capacity(inode);
|
||||||
route_ctx.rr_node_route_inf[inode].set_occ(new_occ);
|
route_ctx.rr_node_route_inf[inode].set_occ(new_occ);
|
||||||
|
|
||||||
if (new_occ < capacity) {
|
if (new_occ < capacity) {
|
||||||
|
@ -1711,11 +1705,11 @@ void print_traceback(ClusterNetId net_id) {
|
||||||
VTR_LOG("traceback %zu: ", size_t(net_id));
|
VTR_LOG("traceback %zu: ", size_t(net_id));
|
||||||
t_trace* head = route_ctx.trace[net_id].head;
|
t_trace* head = route_ctx.trace[net_id].head;
|
||||||
while (head) {
|
while (head) {
|
||||||
int inode{head->index};
|
RRNodeId inode{head->index};
|
||||||
if (device_ctx.rr_nodes[inode].type() == SINK)
|
if (device_ctx.rr_graph.node_type(inode) == SINK)
|
||||||
VTR_LOG("%d(sink)(%d)->", inode, route_ctx.rr_node_route_inf[inode].occ());
|
VTR_LOG("%ld(sink)(%d)->", size_t(inode), route_ctx.rr_node_route_inf[inode].occ());
|
||||||
else
|
else
|
||||||
VTR_LOG("%d(%d)->", inode, route_ctx.rr_node_route_inf[inode].occ());
|
VTR_LOG("%ld(%d)->", size_t(inode), route_ctx.rr_node_route_inf[inode].occ());
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
VTR_LOG("\n");
|
VTR_LOG("\n");
|
||||||
|
@ -1726,8 +1720,8 @@ void print_traceback(const t_trace* trace) {
|
||||||
auto& route_ctx = g_vpr_ctx.routing();
|
auto& route_ctx = g_vpr_ctx.routing();
|
||||||
const t_trace* prev = nullptr;
|
const t_trace* prev = nullptr;
|
||||||
while (trace) {
|
while (trace) {
|
||||||
int inode = trace->index;
|
RRNodeId inode = trace->index;
|
||||||
VTR_LOG("%d (%s)", inode, rr_node_typename[device_ctx.rr_nodes[inode].type()]);
|
VTR_LOG("%ld (%s)", size_t(inode), rr_node_typename[device_ctx.rr_graph.node_type(inode)]);
|
||||||
|
|
||||||
if (trace->iswitch == OPEN) {
|
if (trace->iswitch == OPEN) {
|
||||||
VTR_LOG(" !"); //End of branch
|
VTR_LOG(" !"); //End of branch
|
||||||
|
@ -1737,7 +1731,7 @@ void print_traceback(const t_trace* trace) {
|
||||||
VTR_LOG("*"); //Reached non-configurably
|
VTR_LOG("*"); //Reached non-configurably
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route_ctx.rr_node_route_inf[inode].occ() > device_ctx.rr_nodes[inode].capacity()) {
|
if (route_ctx.rr_node_route_inf[inode].occ() > device_ctx.rr_graph.node_capacity(inode)) {
|
||||||
VTR_LOG(" x"); //Overused
|
VTR_LOG(" x"); //Overused
|
||||||
}
|
}
|
||||||
VTR_LOG("\n");
|
VTR_LOG("\n");
|
||||||
|
@ -1748,12 +1742,12 @@ void print_traceback(const t_trace* trace) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validate_traceback(t_trace* trace) {
|
bool validate_traceback(t_trace* trace) {
|
||||||
std::set<int> seen_rr_nodes;
|
std::set<RRNodeId> seen_rr_nodes;
|
||||||
|
|
||||||
return validate_traceback_recurr(trace, seen_rr_nodes);
|
return validate_traceback_recurr(trace, seen_rr_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validate_traceback_recurr(t_trace* trace, std::set<int>& seen_rr_nodes) {
|
bool validate_traceback_recurr(t_trace* trace, std::set<RRNodeId>& seen_rr_nodes) {
|
||||||
if (!trace) {
|
if (!trace) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1767,7 +1761,7 @@ bool validate_traceback_recurr(t_trace* trace, std::set<int>& seen_rr_nodes) {
|
||||||
|
|
||||||
//Verify that the next element (branch point) has been already seen in the traceback so far
|
//Verify that the next element (branch point) has been already seen in the traceback so far
|
||||||
if (!seen_rr_nodes.count(next->index)) {
|
if (!seen_rr_nodes.count(next->index)) {
|
||||||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback branch point %d not found", next->index);
|
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback branch point %ld not found", size_t(next->index));
|
||||||
} else {
|
} else {
|
||||||
//Recurse along the new branch
|
//Recurse along the new branch
|
||||||
return validate_traceback_recurr(next, seen_rr_nodes);
|
return validate_traceback_recurr(next, seen_rr_nodes);
|
||||||
|
@ -1779,25 +1773,25 @@ bool validate_traceback_recurr(t_trace* trace, std::set<int>& seen_rr_nodes) {
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[trace->index].num_edges(); ++iedge) {
|
for (const RREdgeId& iedge : device_ctx.rr_graph.node_out_edges(trace->index)) {
|
||||||
int to_node = device_ctx.rr_nodes[trace->index].edge_sink_node(iedge);
|
RRNodeId to_node = device_ctx.rr_graph.edge_sink_node(iedge);
|
||||||
|
|
||||||
if (to_node == next->index) {
|
if (to_node == next->index) {
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
//Verify that the switch matches
|
//Verify that the switch matches
|
||||||
int rr_iswitch = device_ctx.rr_nodes[trace->index].edge_switch(iedge);
|
int rr_iswitch = (int)size_t(device_ctx.rr_graph.edge_switch(iedge));
|
||||||
if (trace->iswitch != rr_iswitch) {
|
if (trace->iswitch != rr_iswitch) {
|
||||||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback mismatched switch type: traceback %d rr_graph %d (RR nodes %d -> %d)\n",
|
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback mismatched switch type: traceback %d rr_graph %d (RR nodes %ld -> %ld)\n",
|
||||||
trace->iswitch, rr_iswitch,
|
trace->iswitch, rr_iswitch,
|
||||||
trace->index, to_node);
|
size_t(trace->index), size_t(to_node));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback no RR edge between RR nodes %d -> %d\n", trace->index, next->index);
|
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback no RR edge between RR nodes %ld -> %ld\n", size_t(trace->index), size_t(next->index));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Recurse
|
//Recurse
|
||||||
|
@ -1845,14 +1839,14 @@ void print_invalid_routing_info() {
|
||||||
void print_rr_node_route_inf() {
|
void print_rr_node_route_inf() {
|
||||||
auto& route_ctx = g_vpr_ctx.routing();
|
auto& route_ctx = g_vpr_ctx.routing();
|
||||||
auto& device_ctx = g_vpr_ctx.device();
|
auto& device_ctx = g_vpr_ctx.device();
|
||||||
for (size_t inode = 0; inode < route_ctx.rr_node_route_inf.size(); ++inode) {
|
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
|
||||||
if (!std::isinf(route_ctx.rr_node_route_inf[inode].path_cost)) {
|
if (!std::isinf(route_ctx.rr_node_route_inf[inode].path_cost)) {
|
||||||
int prev_node = route_ctx.rr_node_route_inf[inode].prev_node;
|
RRNodeId prev_node = route_ctx.rr_node_route_inf[inode].prev_node;
|
||||||
int prev_edge = route_ctx.rr_node_route_inf[inode].prev_edge;
|
RREdgeId prev_edge = route_ctx.rr_node_route_inf[inode].prev_edge;
|
||||||
VTR_LOG("rr_node: %d prev_node: %d prev_edge: %d",
|
VTR_LOG("rr_node: %d prev_node: %d prev_edge: %d",
|
||||||
inode, prev_node, prev_edge);
|
size_t(inode), size_t(prev_node), size_t(prev_edge));
|
||||||
|
|
||||||
if (prev_node != OPEN && prev_edge != OPEN && !device_ctx.rr_nodes[prev_node].edge_is_configurable(prev_edge)) {
|
if (prev_node != RRNodeId::INVALID() && prev_edge != RREdgeId::INVALID() && !device_ctx.rr_graph.edge_is_configurable(prev_edge)) {
|
||||||
VTR_LOG("*");
|
VTR_LOG("*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1868,23 +1862,24 @@ void print_rr_node_route_inf_dot() {
|
||||||
|
|
||||||
VTR_LOG("digraph G {\n");
|
VTR_LOG("digraph G {\n");
|
||||||
VTR_LOG("\tnode[shape=record]\n");
|
VTR_LOG("\tnode[shape=record]\n");
|
||||||
for (size_t inode = 0; inode < route_ctx.rr_node_route_inf.size(); ++inode) {
|
|
||||||
|
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
|
||||||
if (!std::isinf(route_ctx.rr_node_route_inf[inode].path_cost)) {
|
if (!std::isinf(route_ctx.rr_node_route_inf[inode].path_cost)) {
|
||||||
VTR_LOG("\tnode%zu[label=\"{%zu (%s)", inode, inode, device_ctx.rr_nodes[inode].type_string());
|
VTR_LOG("\tnode%zu[label=\"{%zu (%s)", size_t(inode), size_t(inode), rr_node_typename[device_ctx.rr_graph.node_type(inode)]);
|
||||||
if (route_ctx.rr_node_route_inf[inode].occ() > device_ctx.rr_nodes[inode].capacity()) {
|
if (route_ctx.rr_node_route_inf[inode].occ() > device_ctx.rr_graph.node_capacity(inode)) {
|
||||||
VTR_LOG(" x");
|
VTR_LOG(" x");
|
||||||
}
|
}
|
||||||
VTR_LOG("}\"]\n");
|
VTR_LOG("}\"]\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t inode = 0; inode < route_ctx.rr_node_route_inf.size(); ++inode) {
|
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
|
||||||
if (!std::isinf(route_ctx.rr_node_route_inf[inode].path_cost)) {
|
if (!std::isinf(route_ctx.rr_node_route_inf[inode].path_cost)) {
|
||||||
int prev_node = route_ctx.rr_node_route_inf[inode].prev_node;
|
RRNodeId prev_node = route_ctx.rr_node_route_inf[inode].prev_node;
|
||||||
int prev_edge = route_ctx.rr_node_route_inf[inode].prev_edge;
|
RREdgeId prev_edge = route_ctx.rr_node_route_inf[inode].prev_edge;
|
||||||
|
|
||||||
if (prev_node != OPEN && prev_edge != OPEN) {
|
if (prev_node != RRNodeId::INVALID() && prev_edge != RREdgeId::INVALID()) {
|
||||||
VTR_LOG("\tnode%d -> node%zu [", prev_node, inode);
|
VTR_LOG("\tnode%ld -> node%ld [", size_t(prev_node), size_t(inode));
|
||||||
if (prev_node != OPEN && prev_edge != OPEN && !device_ctx.rr_nodes[prev_node].edge_is_configurable(prev_edge)) {
|
if (prev_node != RRNodeId::INVALID() && prev_edge != RREdgeId::INVALID() && !device_ctx.rr_graph.edge_is_configurable(prev_edge)) {
|
||||||
VTR_LOG("label=\"*\"");
|
VTR_LOG("label=\"*\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1896,26 +1891,35 @@ void print_rr_node_route_inf_dot() {
|
||||||
VTR_LOG("}\n");
|
VTR_LOG("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool validate_trace_nodes(t_trace* head, const std::unordered_set<int>& trace_nodes) {
|
static bool validate_trace_nodes(t_trace* head, const std::unordered_set<RRNodeId>& trace_nodes) {
|
||||||
//Verifies that all nodes in the traceback 'head' are conatined in 'trace_nodes'
|
//Verifies that all nodes in the traceback 'head' are conatined in 'trace_nodes'
|
||||||
|
|
||||||
if (!head) {
|
if (!head) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> missing_from_trace_nodes;
|
std::vector<RRNodeId> missing_from_trace_nodes;
|
||||||
for (t_trace* tptr = head; tptr != nullptr; tptr = tptr->next) {
|
for (t_trace* tptr = head; tptr != nullptr; tptr = tptr->next) {
|
||||||
if (!trace_nodes.count(tptr->index)) {
|
if (!trace_nodes.count(tptr->index)) {
|
||||||
missing_from_trace_nodes.push_back(tptr->index);
|
missing_from_trace_nodes.push_back(tptr->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!missing_from_trace_nodes.empty()) {
|
if (!missing_from_trace_nodes.empty()) {
|
||||||
|
std::string missing_from_trace_nodes_str;
|
||||||
|
for (const RRNodeId& node : missing_from_trace_nodes) {
|
||||||
|
if (&node != &missing_from_trace_nodes[0]) {
|
||||||
|
missing_from_trace_nodes_str += std::string(", ");
|
||||||
|
}
|
||||||
|
missing_from_trace_nodes_str += std::to_string(size_t(node));
|
||||||
|
}
|
||||||
|
|
||||||
std::string msg = vtr::string_fmt(
|
std::string msg = vtr::string_fmt(
|
||||||
"The following %zu nodes were found in traceback"
|
"The following %zu nodes were found in traceback"
|
||||||
" but were missing from trace_nodes: %s\n",
|
" but were missing from trace_nodes: %s\n",
|
||||||
missing_from_trace_nodes.size(),
|
missing_from_trace_nodes.size(),
|
||||||
vtr::join(missing_from_trace_nodes, ", ").c_str());
|
missing_from_trace_nodes_str.c_str());
|
||||||
|
|
||||||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, msg.c_str());
|
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, msg.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -41,11 +41,18 @@ struct t_heap {
|
||||||
RRNodeId index = RRNodeId::INVALID();
|
RRNodeId index = RRNodeId::INVALID();
|
||||||
|
|
||||||
struct t_prev {
|
struct t_prev {
|
||||||
RRNodeId& node;
|
RRNodeId node;
|
||||||
RREdgeId& edge;
|
RREdgeId edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
/* Xifan Tang - type union was used here,
|
||||||
|
* but it causes an error in vtr_memory.h
|
||||||
|
* when allocating the data structure.
|
||||||
|
* I change to struct here.
|
||||||
|
* TODO: investigate the source of errors
|
||||||
|
* and see if this will cause memory overhead
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
t_heap* next;
|
t_heap* next;
|
||||||
t_prev prev;
|
t_prev prev;
|
||||||
} u;
|
} u;
|
||||||
|
@ -60,7 +67,7 @@ t_bb load_net_route_bb(ClusterNetId net_id, int bb_factor);
|
||||||
void pathfinder_update_path_cost(t_trace* route_segment_start,
|
void pathfinder_update_path_cost(t_trace* route_segment_start,
|
||||||
int add_or_sub,
|
int add_or_sub,
|
||||||
float pres_fac);
|
float pres_fac);
|
||||||
void pathfinder_update_single_node_cost(int inode, int add_or_sub, float pres_fac);
|
void pathfinder_update_single_node_cost(const RRNodeId& inode, int add_or_sub, float pres_fac);
|
||||||
|
|
||||||
void pathfinder_update_cost(float pres_fac, float acc_fac);
|
void pathfinder_update_cost(float pres_fac, float acc_fac);
|
||||||
|
|
||||||
|
@ -71,7 +78,7 @@ void reset_path_costs(const std::vector<RRNodeId>& visited_rr_nodes);
|
||||||
float get_rr_cong_cost(const RRNodeId& inode);
|
float get_rr_cong_cost(const RRNodeId& inode);
|
||||||
|
|
||||||
void mark_ends(ClusterNetId net_id);
|
void mark_ends(ClusterNetId net_id);
|
||||||
void mark_remaining_ends(const std::vector<int>& remaining_sinks);
|
void mark_remaining_ends(const std::vector<RRNodeId>& remaining_sinks);
|
||||||
|
|
||||||
void add_to_heap(t_heap* hptr);
|
void add_to_heap(t_heap* hptr);
|
||||||
t_heap* alloc_heap_data();
|
t_heap* alloc_heap_data();
|
||||||
|
|
Loading…
Reference in New Issue