Skip to content

Commit 129ecc5

Browse files
committed
remove traceback, replace rt_node with RouteTree
1 parent 4fa4476 commit 129ecc5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+4704
-4466
lines changed

libs/libvtrutil/src/tl_optional.hpp

Lines changed: 2072 additions & 0 deletions
Large diffs are not rendered by default.

libs/libvtrutil/src/vtr_optional.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
/** std::optional-like interface with optional references.
4+
* currently: import TartanLlama's optional into the vtr namespace
5+
* documentation at https://tl.tartanllama.xyz/en/latest/api/optional.html
6+
* there are three main uses of this:
7+
* 1. replace pointers when refactoring legacy code
8+
* optional<T&> (reference) is in many ways a pointer, it even has * and -> operators,
9+
* but it can't be allocated or freed. this property is very helpful in refactoring.
10+
* 2. explicit alternative for containers
11+
* optional<T> (non-reference) allows you to put non-empty-initializable
12+
* objects into a container which owns them. it is an alternative to
13+
* unique_ptr<T> in that sense, but with a cleaner interface.
14+
* 3. function return types
15+
* returning an optional<T> gives the caller a clear hint to check the return value.
16+
*
17+
* Q: why not use std::optional?
18+
* A: std::optional doesn't allow optional<T&> due to a disagreement about
19+
* what it means to assign to an optional reference. tl::optional permits this, with
20+
* "rebind on assignment" behavior. this means opt<T&> acts very similarly to a pointer.
21+
* Q: why do we need opt<T&>? there's already T*.
22+
* A: in an ideal world where all pointers are aliases to existing values and nothing
23+
* else, opt<T&> wouldn't be that necessary. however VPR is full of legacy code where
24+
* the usual C++ conventions about pointers don't apply.
25+
* when refactoring such code, turning all pointers into opt<T&> helps a lot.
26+
* it can't be allocated or freed and doesn't allow pointer arithmetic.
27+
* in that aspect it acts as a "enforced proper C++ ptr".
28+
* that's why I think it's worth keeping around in the codebase. */
29+
30+
#include "tl_optional.hpp"
31+
32+
namespace vtr {
33+
template<class T>
34+
using optional = tl::optional<T>;
35+
36+
using nullopt_t = tl::nullopt_t;
37+
static constexpr nullopt_t nullopt = tl::nullopt;
38+
39+
using bad_optional_access = tl::bad_optional_access;
40+
} // namespace vtr

utils/fasm/src/fasm.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "atom_netlist_utils.h"
2323
#include "netlist_writer.h"
2424
#include "vpr_utils.h"
25-
#include "route_tree_timing.h"
2625

2726
#include "fasm_utils.h"
2827

@@ -619,31 +618,29 @@ void FasmWriterVisitor::check_for_lut(const t_pb* atom) {
619618
}
620619

621620
void FasmWriterVisitor::visit_atom_impl(const t_pb* atom) {
622-
check_for_lut(atom);
623-
check_for_param(atom);
621+
check_for_lut(atom);
622+
check_for_param(atom);
624623
}
625624

626-
void FasmWriterVisitor::walk_route_tree(const RRGraphBuilder& rr_graph_builder, const t_rt_node *root) {
627-
for (t_linked_rt_edge* edge = root->u.child_list; edge != nullptr; edge = edge->next) {
628-
auto *meta = vpr::rr_edge_metadata(rr_graph_builder, root->inode, edge->child->inode, edge->iswitch, fasm_features);
625+
void FasmWriterVisitor::walk_route_tree(const RRGraphBuilder& rr_graph_builder, const RouteTreeNode& root) {
626+
for(auto& child: root.child_nodes()){
627+
auto* meta = vpr::rr_edge_metadata(rr_graph_builder, size_t(root.inode), size_t(child.inode), size_t(child.parent_switch), fasm_features);
628+
629629
if(meta != nullptr) {
630630
output_fasm_features(meta->as_string().get(strings_), "", "");
631631
}
632632

633-
walk_route_tree(rr_graph_builder, edge->child);
633+
walk_route_tree(rr_graph_builder, child);
634634
}
635635
}
636636

637637
void FasmWriterVisitor::walk_routing() {
638638
auto& route_ctx = g_vpr_ctx.mutable_routing();
639639
const auto& device_ctx = g_vpr_ctx.device();
640640

641-
for(const auto &trace : route_ctx.trace) {
642-
t_trace *head = trace.head;
643-
if (!head) continue;
644-
t_rt_node* root = traceback_to_route_tree(head, is_flat_);
645-
walk_route_tree(device_ctx.rr_graph_builder, root);
646-
free_route_tree(root);
641+
for(const auto &tree : route_ctx.route_trees) {
642+
if (!tree) continue;
643+
walk_route_tree(device_ctx.rr_graph_builder, tree.value().root());
647644
}
648645
}
649646

utils/fasm/src/fasm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include "netlist_writer.h"
2323
#include "lut.h"
2424
#include "parameters.h"
25-
#include "route_tree_type.h"
25+
#include "route_tree_fwd.h"
2626

2727
namespace fasm {
2828

@@ -73,7 +73,7 @@ class FasmWriterVisitor : public NetlistVisitor {
7373
void check_for_lut(const t_pb* atom);
7474
void output_fasm_mux(std::string fasm_mux, t_interconnect *interconnect, const t_pb_graph_pin *mux_input_pin);
7575
void walk_routing();
76-
void walk_route_tree(const RRGraphBuilder& rr_graph_builder, const t_rt_node *root);
76+
void walk_route_tree(const RRGraphBuilder& rr_graph_builder, const RouteTreeNode& root);
7777
std::string build_clb_prefix(const t_pb *pb, const t_pb_graph_node* pb_graph_node, bool* is_parent_pb_null) const;
7878
const LutOutputDefinition* find_lut(const t_pb_graph_node* pb_graph_node);
7979
void check_for_param(const t_pb *atom);

utils/fasm/src/main.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,7 @@ int main(int argc, const char **argv) {
120120
(float) (entire_flow_end - entire_flow_begin) / CLOCKS_PER_SEC);
121121

122122
/* free data structures */
123-
if(is_flat) {
124-
vpr_free_all((const Netlist<>&) g_vpr_ctx.atom().nlist, Arch, vpr_setup);
125-
} else {
126-
vpr_free_all((const Netlist<>&) g_vpr_ctx.clustering().clb_nlist, Arch, vpr_setup);
127-
}
123+
vpr_free_all(Arch, vpr_setup);
128124

129125

130126
} catch (const tatum::Error& tatum_error) {

utils/fasm/test/test_fasm.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "catch2/catch_test_macros.hpp"
22
#include "catch2/matchers/catch_matchers_all.hpp"
33

4+
#include "route_common.h"
45
#include "vpr_api.h"
56
#include "vtr_util.h"
67
#include "rr_metadata.h"
@@ -23,7 +24,6 @@ namespace {
2324

2425
// ============================================================================
2526

26-
using Catch::Matchers::Equals;
2727
using Catch::Matchers::StartsWith;
2828
using Catch::Matchers::ContainsSubstring;
2929

@@ -296,7 +296,7 @@ TEST_CASE("fasm_integration_test", "[fasm]") {
296296
echo_enabled,
297297
echo_file_name,
298298
is_flat);
299-
vpr_free_all((const Netlist<>&) g_vpr_ctx.clustering().clb_nlist, arch, vpr_setup);
299+
vpr_free_all(arch, vpr_setup);
300300
}
301301

302302
t_vpr_setup vpr_setup;
@@ -586,20 +586,17 @@ TEST_CASE("fasm_integration_test", "[fasm]") {
586586

587587
// Verify routes
588588
const auto & route_ctx = g_vpr_ctx.routing();
589-
for(const auto &trace : route_ctx.trace) {
590-
const t_trace *head = trace.head;
591-
while(head != nullptr) {
592-
const t_trace *next = head->next;
593-
594-
if(next != nullptr && head->iswitch != OPEN) {
595-
const auto next_inode = next->index;
596-
auto iter = routing_edges.find(std::make_tuple(head->index, next_inode, head->iswitch));
589+
for(const auto& root : route_ctx.route_trees) {
590+
if(!root)
591+
continue;
592+
593+
for(auto& rt_node: root.value().all_nodes()) {
594+
for(auto& child_node: rt_node.child_nodes()){
595+
auto iter = routing_edges.find(std::make_tuple(size_t(rt_node.inode), size_t(child_node.inode), size_t(child_node.parent_switch)));
597596
if (iter == routing_edges.end()) {
598-
FAIL_CHECK("source: " << head->index << " sink: " << next_inode << " switch:" << head->iswitch);
597+
FAIL_CHECK("source: " << size_t(rt_node.inode) << " sink: " << size_t(child_node.inode) << " switch:" << size_t(child_node.parent_switch));
599598
}
600599
}
601-
602-
head = next;
603600
}
604601
}
605602

@@ -635,7 +632,7 @@ TEST_CASE("fasm_integration_test", "[fasm]") {
635632
CHECK(found_mux4);
636633

637634

638-
vpr_free_all((const Netlist<>&) g_vpr_ctx.clustering().clb_nlist, arch, vpr_setup);
635+
vpr_free_all(arch, vpr_setup);
639636
}
640637

641638
} // namespace

utils/fasm/test/test_lut.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ TEST_CASE("default_lut", "[fasm]") {
1212
fasm::Lut lut(num_inputs);
1313

1414
const LogicVec &table = lut.table();
15-
CHECK(table.size() == (1 << num_inputs));
15+
CHECK(table.size() == size_t(1 << num_inputs));
1616

1717
for(const vtr::LogicValue & value : table) {
1818
CHECK(value == vtr::LogicValue::FALSE);
@@ -27,7 +27,7 @@ TEST_CASE("const_true", "[fasm]") {
2727
lut.SetConstant(vtr::LogicValue::TRUE);
2828

2929
const LogicVec &table = lut.table();
30-
CHECK(table.size() == (1 << num_inputs));
30+
CHECK(table.size() == size_t(1 << num_inputs));
3131

3232
for(const vtr::LogicValue & value : table) {
3333
CHECK(value == vtr::LogicValue::TRUE);
@@ -42,7 +42,7 @@ TEST_CASE("const_false", "[fasm]") {
4242
lut.SetConstant(vtr::LogicValue::FALSE);
4343

4444
const LogicVec &table = lut.table();
45-
CHECK(table.size() == (1 << num_inputs));
45+
CHECK(table.size() == size_t(1 << num_inputs));
4646

4747
for(const vtr::LogicValue & value : table) {
4848
CHECK(value == vtr::LogicValue::FALSE);
@@ -58,7 +58,7 @@ TEST_CASE("wire", "[fasm]") {
5858
lut.CreateWire(input_pin);
5959

6060
const LogicVec &table = lut.table();
61-
CHECK(table.size() == (1 << num_inputs));
61+
CHECK(table.size() == size_t(1 << num_inputs));
6262
for(size_t i = 0; i < table.size(); ++i) {
6363
if(((1 << input_pin) & i) != 0) {
6464
CHECK(table[i] == vtr::LogicValue::TRUE);

utils/route_diag/src/main.cpp

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,9 @@
3131
#include "RoutingDelayCalculator.h"
3232
#include "place_and_route.h"
3333
#include "router_delay_profiling.h"
34-
#include "route_tree_type.h"
34+
#include "route_tree.h"
3535
#include "route_common.h"
3636
#include "route_timing.h"
37-
#include "route_tree_timing.h"
3837
#include "route_export.h"
3938
#include "rr_graph.h"
4039
#include "rr_graph2.h"
@@ -74,7 +73,7 @@ static void do_one_route(const Netlist<>& net_list,
7473
const auto& rr_graph = device_ctx.rr_graph;
7574
auto& route_ctx = g_vpr_ctx.routing();
7675

77-
t_rt_node* rt_root = init_route_tree_to_source_no_net(source_node);
76+
RouteTree tree((RRNodeId(source_node)));
7877

7978
/* Update base costs according to fanout and criticality rules */
8079
update_rr_base_costs(1);
@@ -118,31 +117,29 @@ static void do_one_route(const Netlist<>& net_list,
118117
-1,
119118
false,
120119
std::unordered_map<RRNodeId, int>());
121-
std::tie(found_path, cheapest) = router.timing_driven_route_connection_from_route_tree(rt_root,
122-
sink_node,
123-
cost_params,
124-
bounding_box,
125-
router_stats,
126-
conn_params);
120+
std::tie(found_path, cheapest) = router.timing_driven_route_connection_from_route_tree(tree.root(),
121+
sink_node,
122+
cost_params,
123+
bounding_box,
124+
router_stats,
125+
conn_params);
127126

128127
if (found_path) {
129128
VTR_ASSERT(cheapest.index == sink_node);
130129

131-
t_rt_node* rt_node_of_sink = update_route_tree(&cheapest, OPEN, nullptr, router_opts.flat_routing);
130+
vtr::optional<RouteTreeNode&> rt_node_of_sink;
131+
std::tie(std::ignore, rt_node_of_sink) = tree.update_from_heap(&cheapest, OPEN, nullptr, router_opts.flat_routing);
132132

133133
//find delay
134-
float net_delay = rt_node_of_sink->Tdel;
134+
float net_delay = rt_node_of_sink.value().Tdel;
135135
VTR_LOG("Routed successfully, delay = %g!\n", net_delay);
136136
VTR_LOG("\n");
137-
print_route_tree_node(rt_root);
138-
VTR_LOG("\n");
139-
print_route_tree(rt_root);
137+
tree.print();
140138
VTR_LOG("\n");
141139

142-
VTR_ASSERT_MSG(route_ctx.rr_node_route_inf[rt_root->inode].occ() <= rr_graph.node_capacity(RRNodeId(rt_root->inode)), "SOURCE should never be congested");
143-
free_route_tree(rt_root);
140+
VTR_ASSERT_MSG(route_ctx.rr_node_route_inf[size_t(tree.root().inode)].occ() <= rr_graph.node_capacity(tree.root().inode), "SOURCE should never be congested");
144141
} else {
145-
VTR_LOG("Routed failed");
142+
VTR_LOG("Routing failed");
146143
}
147144

148145
//Reset for the next router call
@@ -347,10 +344,10 @@ int main(int argc, const char **argv) {
347344
vpr_setup.Segments,
348345
is_flat);
349346
}
350-
free_routing_structs(net_list);
347+
free_routing_structs();
351348

352349
/* free data structures */
353-
vpr_free_all(net_list, Arch, vpr_setup);
350+
vpr_free_all(Arch, vpr_setup);
354351

355352
} catch (const tatum::Error& tatum_error) {
356353
vtr::printf_error(__FILE__, __LINE__, "STA Engine: %s\n", tatum_error.what());

0 commit comments

Comments
 (0)