Skip to content

Commit dce37b9

Browse files
authored
Merge pull request #2627 from nedsels/improve_binary_heap
Update BinaryHeap to FourAryHeap
2 parents 1ce545f + fc49189 commit dce37b9

File tree

36 files changed

+3162
-2820
lines changed

36 files changed

+3162
-2820
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,4 @@ tags
153153
.idea
154154
cmake-build-debug
155155
cmake-build-release
156-
/.metadata/
156+
/.metadata/

doc/src/api/vprinternals/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ VPR INTERNALS
1010
vpr_ui
1111
draw_files
1212
vpr_noc
13+
vpr_router
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
==============
2+
Router Heap
3+
==============
4+
5+
t_heap
6+
----------
7+
.. doxygenstruct:: t_heap
8+
:project: vpr
9+
:members:
10+
11+
HeapInterface
12+
----------
13+
.. doxygenclass:: HeapInterface
14+
:project: vpr
15+
:members:
16+
17+
HeapStorage
18+
----------
19+
.. doxygenclass:: HeapStorage
20+
:project: vpr
21+
:members:
22+
23+
KAryHeap
24+
----------
25+
.. doxygenclass:: KAryHeap
26+
:project: vpr
27+
:members:
28+
29+
FourAryHeap
30+
----------
31+
.. doxygenclass:: FourAryHeap
32+
:project: vpr
33+
:members:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _router:
2+
3+
=======
4+
VPR Router
5+
=======
6+
7+
.. toctree::
8+
:maxdepth: 1
9+
10+
router_heap

utils/route_diag/src/main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ static void do_one_route(const Netlist<>& net_list,
103103
segment_inf,
104104
is_flat);
105105

106-
ConnectionRouter<BinaryHeap> router(
107-
device_ctx.grid,
108-
*router_lookahead,
106+
ConnectionRouter<FourAryHeap> router(
107+
device_ctx.grid,
108+
*router_lookahead,
109109
device_ctx.rr_graph.rr_nodes(),
110110
&device_ctx.rr_graph,
111111
device_ctx.rr_rc_data,

vpr/src/base/ShowSetup.cpp

Lines changed: 185 additions & 258 deletions
Large diffs are not rendered by default.

vpr/src/base/read_options.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,8 @@ struct ParseRouterHeap {
10611061
ConvertedValue<e_heap_type> conv_value;
10621062
if (str == "binary")
10631063
conv_value.set_value(e_heap_type::BINARY_HEAP);
1064+
else if (str == "four_ary")
1065+
conv_value.set_value(e_heap_type::FOUR_ARY_HEAP);
10641066
else if (str == "bucket")
10651067
conv_value.set_value(e_heap_type::BUCKET_HEAP_APPROXIMATION);
10661068
else {
@@ -1075,6 +1077,8 @@ struct ParseRouterHeap {
10751077
ConvertedValue<std::string> conv_value;
10761078
if (val == e_heap_type::BINARY_HEAP)
10771079
conv_value.set_value("binary");
1080+
else if (val == e_heap_type::FOUR_ARY_HEAP)
1081+
conv_value.set_value("four_ary");
10781082
else {
10791083
VTR_ASSERT(val == e_heap_type::BUCKET_HEAP_APPROXIMATION);
10801084
conv_value.set_value("bucket");
@@ -1083,7 +1087,7 @@ struct ParseRouterHeap {
10831087
}
10841088

10851089
std::vector<std::string> default_choices() {
1086-
return {"binary", "bucket"};
1090+
return {"binary", "four_ary", "bucket"};
10871091
}
10881092
};
10891093

@@ -2648,11 +2652,12 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
26482652
.help(
26492653
"Controls what type of heap to use for timing driven router.\n"
26502654
" * binary: A binary heap is used.\n"
2655+
" * four_ary: A four_ary heap is used.\n"
26512656
" * bucket: A bucket heap approximation is used. The bucket heap\n"
26522657
" * is faster because it is only a heap approximation.\n"
26532658
" * Testing has shown the approximation results in\n"
2654-
" * similiar QoR with less CPU work.\n")
2655-
.default_value("binary")
2659+
" * similar QoR with less CPU work.\n")
2660+
.default_value("four_ary")
26562661
.show_in(argparse::ShowIn::HELP_ONLY);
26572662

26582663
route_timing_grp.add_argument(args.router_first_iteration_timing_report_file, "--router_first_iter_timing_report")

vpr/src/base/read_route.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#include "route_common.h"
4747
#include "route_tree.h"
4848
#include "read_route.h"
49-
#include "binary_heap.h"
49+
#include "four_ary_heap.h"
5050

5151
#include "old_traceback.h"
5252

@@ -129,7 +129,7 @@ bool read_route(const char* route_file, const t_router_opts& router_opts, bool v
129129
fp.close();
130130

131131
/*Correctly set up the clb opins*/
132-
BinaryHeap small_heap;
132+
FourAryHeap small_heap;
133133
small_heap.init_heap(device_ctx.grid);
134134
if (!flat_router) {
135135
reserve_locally_used_opins(&small_heap, router_opts.initial_pres_fac,

vpr/src/route/binary_heap.cpp

Lines changed: 23 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,23 @@
11
#include "binary_heap.h"
2-
#include "rr_graph_fwd.h"
32
#include "vtr_log.h"
43

5-
static size_t parent(size_t i) { return i >> 1; }
64
// child indices of a heap
7-
static size_t left(size_t i) { return i << 1; }
8-
static size_t right(size_t i) { return (i << 1) + 1; }
9-
10-
BinaryHeap::BinaryHeap()
11-
: heap_()
12-
, heap_size_(0)
13-
, heap_tail_(0)
14-
, max_index_(std::numeric_limits<size_t>::max())
15-
, prune_limit_(std::numeric_limits<size_t>::max()) {}
16-
17-
BinaryHeap::~BinaryHeap() {
18-
free_all_memory();
19-
}
5+
static inline size_t left(size_t i) { return i << 1; }
6+
static inline size_t right(size_t i) { return (i << 1) + 1; }
207

21-
t_heap* BinaryHeap::alloc() {
22-
return storage_.alloc();
23-
}
24-
void BinaryHeap::free(t_heap* hptr) {
25-
storage_.free(hptr);
26-
}
8+
inline size_t BinaryHeap::parent(size_t i) const { return i >> 1; }
279

28-
void BinaryHeap::init_heap(const DeviceGrid& grid) {
29-
size_t target_heap_size = (grid.width() - 1) * (grid.height() - 1);
30-
if (heap_.empty() || heap_size_ < target_heap_size) {
31-
if (!heap_.empty()) {
32-
// coverity[offset_free : Intentional]
33-
heap_.clear();
34-
}
35-
heap_size_ = (grid.width() - 1) * (grid.height() - 1);
36-
heap_.resize(heap_size_ + 1); /* heap_size_ + 1 because heap stores from [1..heap_size] */
10+
bool BinaryHeap::is_valid() const {
11+
if (heap_.empty()) {
12+
return false;
3713
}
38-
heap_tail_ = 1;
39-
}
40-
41-
void BinaryHeap::add_to_heap(t_heap* hptr) {
42-
expand_heap_if_full();
43-
// start with undefined hole
44-
++heap_tail_;
45-
sift_up(heap_tail_ - 1, hptr);
4614

47-
// If we have pruned, rebuild the heap now.
48-
if (check_prune_limit()) {
49-
build_heap();
15+
for (size_t i = 1; i <= heap_tail_ >> 1; ++i) {
16+
if (left(i) < heap_tail_ && heap_[left(i)].cost < heap_[i].cost) return false;
17+
if (right(i) < heap_tail_ && heap_[right(i)].cost < heap_[i].cost) return false;
5018
}
51-
}
5219

53-
bool BinaryHeap::is_empty_heap() const {
54-
return (bool)(heap_tail_ == 1);
20+
return true;
5521
}
5622

5723
t_heap* BinaryHeap::get_heap_head() {
@@ -68,173 +34,44 @@ t_heap* BinaryHeap::get_heap_head() {
6834
return (nullptr);
6935
}
7036

71-
cheapest = heap_[1];
37+
cheapest = heap_[1].elem_ptr;
7238

7339
hole = 1;
7440
child = 2;
41+
7542
--heap_tail_;
43+
7644
while (child < heap_tail_) {
77-
if (heap_[child + 1]->cost < heap_[child]->cost)
45+
if (heap_[child + 1].cost < heap_[child].cost)
7846
++child; // become right child
47+
7948
heap_[hole] = heap_[child];
8049
hole = child;
8150
child = left(child);
8251
}
83-
sift_up(hole, heap_[heap_tail_]);
8452

53+
sift_up(hole, heap_[heap_tail_]);
8554
} while (!cheapest->index.is_valid()); /* Get another one if invalid entry. */
8655

8756
return (cheapest);
8857
}
8958

90-
void BinaryHeap::empty_heap() {
91-
for (size_t i = 1; i < heap_tail_; i++)
92-
free(heap_[i]);
93-
94-
heap_tail_ = 1;
95-
}
96-
97-
size_t BinaryHeap::size() const { return heap_tail_ - 1; } // heap[0] is not valid element
98-
9959
// make a heap rooted at index hole by **sifting down** in O(lgn) time
10060
void BinaryHeap::sift_down(size_t hole) {
101-
t_heap* head{heap_[hole]};
61+
heap_elem head{heap_[hole]};
10262
size_t child{left(hole)};
63+
10364
while (child < heap_tail_) {
104-
if (child + 1 < heap_tail_ && heap_[child + 1]->cost < heap_[child]->cost)
65+
if (child + 1 < heap_tail_ && heap_[child + 1].cost < heap_[child].cost)
10566
++child;
106-
if (heap_[child]->cost < head->cost) {
67+
68+
if (heap_[child].cost < head.cost) {
10769
heap_[hole] = heap_[child];
10870
hole = child;
10971
child = left(child);
11072
} else
11173
break;
11274
}
113-
heap_[hole] = head;
114-
}
115-
116-
// runs in O(n) time by sifting down; the least work is done on the most elements: 1 swap for bottom layer, 2 swap for 2nd, ... lgn swap for top
117-
// 1*(n/2) + 2*(n/4) + 3*(n/8) + ... + lgn*1 = 2n (sum of i/2^i)
118-
void BinaryHeap::build_heap() {
119-
// second half of heap are leaves
120-
for (size_t i = heap_tail_ >> 1; i != 0; --i)
121-
sift_down(i);
122-
}
123-
124-
void BinaryHeap::set_prune_limit(size_t max_index, size_t prune_limit) {
125-
if (prune_limit != std::numeric_limits<size_t>::max()) {
126-
VTR_ASSERT(max_index < prune_limit);
127-
}
128-
max_index_ = max_index;
129-
prune_limit_ = prune_limit;
130-
}
131-
132-
// O(lgn) sifting up to maintain heap property after insertion (should sift down when building heap)
133-
void BinaryHeap::sift_up(size_t leaf, t_heap* const node) {
134-
while ((leaf > 1) && (node->cost < heap_[parent(leaf)]->cost)) {
135-
// sift hole up
136-
heap_[leaf] = heap_[parent(leaf)];
137-
leaf = parent(leaf);
138-
}
139-
heap_[leaf] = node;
140-
}
141-
142-
//expands heap by "realloc"
143-
void BinaryHeap::expand_heap_if_full() {
144-
if (heap_tail_ > heap_size_) { /* Heap is full */
145-
heap_size_ *= 2;
146-
heap_.resize(heap_size_ + 1);
147-
}
148-
}
14975

150-
// adds an element to the back of heap and expand if necessary, but does not maintain heap property
151-
void BinaryHeap::push_back(t_heap* const hptr) {
152-
expand_heap_if_full();
153-
heap_[heap_tail_] = hptr;
154-
++heap_tail_;
155-
156-
check_prune_limit();
157-
}
158-
159-
bool BinaryHeap::is_valid() const {
160-
if (heap_.empty()) {
161-
return false;
162-
}
163-
164-
for (size_t i = 1; i <= heap_tail_ >> 1; ++i) {
165-
if (left(i) < heap_tail_ && heap_[left(i)]->cost < heap_[i]->cost) return false;
166-
if (right(i) < heap_tail_ && heap_[right(i)]->cost < heap_[i]->cost) return false;
167-
}
168-
return true;
169-
}
170-
171-
void BinaryHeap::free_all_memory() {
172-
if (!heap_.empty()) {
173-
empty_heap();
174-
175-
// coverity[offset_free : Intentional]
176-
heap_.clear();
177-
}
178-
179-
// heap_ = nullptr; /* Defensive coding: crash hard if I use these. */
180-
181-
storage_.free_all_memory();
182-
}
183-
184-
bool BinaryHeap::check_prune_limit() {
185-
if (heap_tail_ > prune_limit_) {
186-
prune_heap();
187-
return true;
188-
}
189-
190-
return false;
191-
}
192-
193-
void BinaryHeap::prune_heap() {
194-
VTR_ASSERT(max_index_ < prune_limit_);
195-
196-
std::vector<t_heap*> best_heap_item(max_index_, nullptr);
197-
198-
// Find the cheapest instance of each index and store it.
199-
for (size_t i = 1; i < heap_tail_; i++) {
200-
if (heap_[i] == nullptr) {
201-
continue;
202-
}
203-
204-
if (!heap_[i]->index.is_valid()) {
205-
free(heap_[i]);
206-
heap_[i] = nullptr;
207-
continue;
208-
}
209-
210-
auto idx = size_t(heap_[i]->index);
211-
212-
VTR_ASSERT(idx < max_index_);
213-
214-
if (best_heap_item[idx] == nullptr || best_heap_item[idx]->cost > heap_[i]->cost) {
215-
best_heap_item[idx] = heap_[i];
216-
}
217-
}
218-
219-
// Free unused nodes.
220-
for (size_t i = 1; i < heap_tail_; i++) {
221-
if (heap_[i] == nullptr) {
222-
continue;
223-
}
224-
225-
auto idx = size_t(heap_[i]->index);
226-
227-
if (best_heap_item[idx] != heap_[i]) {
228-
free(heap_[i]);
229-
heap_[i] = nullptr;
230-
}
231-
}
232-
233-
heap_tail_ = 1;
234-
235-
for (size_t i = 0; i < max_index_; ++i) {
236-
if (best_heap_item[i] != nullptr) {
237-
heap_[heap_tail_++] = best_heap_item[i];
238-
}
239-
}
240-
}
76+
heap_[hole] = head;
77+
}

0 commit comments

Comments
 (0)