Skip to content

Commit 62797c4

Browse files
committed
Clock Modeling: Added two Stage router
- Stage 1: route clock nets to a virtual sink. Virtual sink is connected to all clock network sources - Stage 2: Route all physical sinks of the clock net Note: after stage 1 we remove the virtual sink from the route-tree and traceback
1 parent 8004e3f commit 62797c4

17 files changed

+293
-48
lines changed

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts)
340340
RouterOpts->congested_routing_iteration_threshold_frac = Options.congested_routing_iteration_threshold_frac;
341341
RouterOpts->route_bb_update = Options.route_bb_update;
342342
RouterOpts->clock_modeling = Options.clock_modeling;
343+
RouterOpts->two_stage_routing = Options.two_stage_routing;
343344
RouterOpts->high_fanout_threshold = Options.router_high_fanout_threshold;
344345
RouterOpts->router_debug_net = Options.router_debug_net;
345346
RouterOpts->router_debug_sink_rr = Options.router_debug_sink_rr;

vpr/src/base/read_options.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -899,9 +899,7 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
899899
"Specifies how constant nets (i.e. those driven to a constant\n"
900900
"value) are handled:\n"
901901
" * global: Treat constant nets as globals (not routed)\n"
902-
" * route : Treat constant nets as normal nets (routed)\n"
903-
" * dedicated_network : Build a dedicated clock network based on the\n"
904-
" clock network specified in the architecture file\n")
902+
" * route : Treat constant nets as normal nets (routed)\n")
905903
.default_value("global")
906904
.show_in(argparse::ShowIn::HELP_ONLY);
907905

@@ -911,10 +909,21 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
911909
" * ideal: Treat clock pins as ideal\n"
912910
" (i.e. no routing delays on clocks)\n"
913911
" * route: Treat the clock pins as normal nets\n"
914-
" (i.e. routed using inter-block routing)\n")
912+
" (i.e. routed using inter-block routing)\n"
913+
" * dedicated_network : Build a dedicated clock network based on the\n"
914+
" clock network specified in the architecture file\n")
915915
.default_value("ideal")
916916
.show_in(argparse::ShowIn::HELP_ONLY);
917917

918+
gen_grp.add_argument<bool, ParseOnOff>(args.two_stage_routing, "--two_stage_routing")
919+
.help(
920+
"Routes clock nets in two stages if using a dedicated clock network.\n"
921+
" * First stage: From the Net source to a dedicated clock network source\n"
922+
" * Second stage: From the clock network source to net sinks\n")
923+
.default_value("off")
924+
.action(argparse::Action::STORE_TRUE)
925+
.show_in(argparse::ShowIn::HELP_ONLY);
926+
918927
gen_grp.add_argument<bool, ParseOnOff>(args.exit_before_pack, "--exit_before_pack")
919928
.help("Causes VPR to exit before packing starts (useful for statistics collection)")
920929
.default_value("off")

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct t_options {
4949
argparse::ArgValue<float> target_device_utilization;
5050
argparse::ArgValue<e_constant_net_method> constant_net_method;
5151
argparse::ArgValue<e_clock_modeling> clock_modeling;
52+
argparse::ArgValue<bool> two_stage_routing;
5253
argparse::ArgValue<bool> exit_before_pack;
5354
argparse::ArgValue<bool> strict_checks;
5455
argparse::ArgValue<std::string> disable_errors;

vpr/src/base/vpr_api.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a
217217
vpr_setup->device_layout = options->device_layout;
218218
vpr_setup->constant_net_method = options->constant_net_method;
219219
vpr_setup->clock_modeling = options->clock_modeling;
220+
vpr_setup->two_stage_routing = options->two_stage_routing;
220221
vpr_setup->exit_before_pack = options->exit_before_pack;
221222

222223
VTR_LOG("\n");

vpr/src/base/vpr_context.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ struct DeviceContext : public Context {
161161
std::vector<std::unique_ptr<ClockNetwork>> clock_networks;
162162
std::vector<std::unique_ptr<ClockConnection>> clock_connections;
163163

164+
// rr_node idx that connects to the input of all clock network wires
165+
// Useful for two stage clock routing
166+
// XXX: currently only one place to source the clock networks so only storing
167+
// a single value
168+
int virtual_clock_network_sink_idx;
169+
164170
/** Attributes for each rr_node.
165171
* key: rr_node index
166172
* value: map of <attribute_name, attribute_value>

vpr/src/base/vpr_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@ struct t_router_opts {
944944
float congested_routing_iteration_threshold_frac;
945945
e_route_bb_update route_bb_update;
946946
enum e_clock_modeling clock_modeling; //How clock pins and nets should be handled
947+
bool two_stage_routing; //How clock nets on dedicated networks should be routed
947948
int high_fanout_threshold;
948949
int router_debug_net;
949950
int router_debug_sink_rr;
@@ -1298,6 +1299,7 @@ struct t_vpr_setup {
12981299
std::string device_layout;
12991300
e_constant_net_method constant_net_method; //How constant nets should be handled
13001301
e_clock_modeling clock_modeling; //How clocks should be handled
1302+
bool two_stage_routing; //How clocks should be routed in the presence of a dedicated clock network
13011303
bool exit_before_pack; //Exits early before starting packing (useful for collecting statistics without running/loading any stages)
13021304
};
13031305

vpr/src/route/check_route.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ static bool check_adjacent(int from_node, int to_node) {
438438
} else if (to_type == CHANY) {
439439
num_adj += chanx_chany_adjacent(from_node, to_node);
440440
} else {
441-
VTR_ASSERT(0);
441+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
442+
"in check_adjacent: %d and %d are not adjacent", from_node, to_node);
442443
}
443444
break;
444445

@@ -469,7 +470,8 @@ static bool check_adjacent(int from_node, int to_node) {
469470
} else if (to_type == CHANX) {
470471
num_adj += chanx_chany_adjacent(to_node, from_node);
471472
} else {
472-
VTR_ASSERT(0);
473+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
474+
"in check_adjacent: %d and %d are not adjacent", from_node, to_node);
473475
}
474476
break;
475477

vpr/src/route/clock_connection_builders.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_
4949
auto& rr_nodes = device_ctx.rr_nodes;
5050
auto& rr_node_indices = device_ctx.rr_node_indices;
5151

52+
int virtual_clock_network_sink_idx =
53+
create_virtual_clock_network_sink_node(switch_location.x, switch_location.y);
54+
device_ctx.virtual_clock_network_sink_idx = virtual_clock_network_sink_idx;
55+
5256
// rr_node indices for x and y channel routing wires and clock wires to connect to
5357
auto x_wire_indices = get_rr_node_chan_wires_at_location(
5458
rr_node_indices, CHANX, switch_location.x, switch_location.y);
@@ -73,9 +77,34 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_
7377
for (size_t i = 0; i < num_wires_y; i++) {
7478
rr_nodes[y_wire_indices[i]].add_edge(clock_index, rr_switch_idx);
7579
}
80+
81+
// Connect to virtual clock sink node
82+
// used by the two stage router
83+
rr_nodes[clock_index].add_edge(virtual_clock_network_sink_idx, rr_switch_idx);
7684
}
7785
}
7886

87+
int RoutingToClockConnection::create_virtual_clock_network_sink_node(
88+
int x,
89+
int y)
90+
{
91+
auto& device_ctx = g_vpr_ctx.mutable_device();
92+
auto& rr_nodes = device_ctx.rr_nodes;
93+
rr_nodes.emplace_back();
94+
auto node_index = rr_nodes.size() - 1;
95+
96+
rr_nodes[node_index].set_coordinates(x, y, x, y);
97+
rr_nodes[node_index].set_capacity(1);
98+
rr_nodes[node_index].set_cost_index(SINK_COST_INDEX);
99+
rr_nodes[node_index].set_type(SINK);
100+
float R = 0.;
101+
float C = 0.;
102+
rr_nodes[node_index].set_rc_index(find_create_rr_rc_data(R, C));
103+
104+
return node_index;
105+
}
106+
107+
79108
/*
80109
* ClockToClockConneciton (setters)
81110
*/

vpr/src/route/clock_connection_builders.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class RoutingToClockConnection : public ClockConnection {
5454
*/
5555
/* Connects the inter-block routing to the clock source at the specified coordinates */
5656
void create_switches(const ClockRRGraphBuilder& clock_graph);
57+
int create_virtual_clock_network_sink_node(int x, int y);
5758
};
5859

5960
class ClockToClockConneciton : public ClockConnection {

vpr/src/route/clock_network_builders.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ int ClockRib::create_chanx_wire(int x_start,
274274
rr_nodes[node_index].set_type(CHANX);
275275
rr_nodes[node_index].set_capacity(1);
276276
rr_nodes[node_index].set_track_num(ptc_num);
277-
auto rc_index = find_create_rr_rc_data(x_chan_wire.layer.r_metal, x_chan_wire.layer.c_metal);
278-
rr_nodes[node_index].set_rc_index(rc_index);
277+
rr_nodes[node_index].set_rc_index(find_create_rr_rc_data(
278+
x_chan_wire.layer.r_metal, x_chan_wire.layer.c_metal));
279279
rr_nodes[node_index].set_direction(direction);
280280

281281
short seg_index = 0;
@@ -523,8 +523,8 @@ int ClockSpine::create_chany_wire(int y_start,
523523
rr_nodes[node_index].set_type(CHANY);
524524
rr_nodes[node_index].set_capacity(1);
525525
rr_nodes[node_index].set_track_num(ptc_num);
526-
auto rc_index = find_create_rr_rc_data(y_chan_wire.layer.r_metal, y_chan_wire.layer.c_metal);
527-
rr_nodes[node_index].set_rc_index(rc_index);
526+
rr_nodes[node_index].set_rc_index(find_create_rr_rc_data(
527+
y_chan_wire.layer.r_metal, y_chan_wire.layer.c_metal));
528528
rr_nodes[node_index].set_direction(direction);
529529

530530
short seg_index = 0;

vpr/src/route/route_common.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,26 @@ void node_to_heap(int inode, float total_cost, int prev_node, int prev_edge, flo
801801
add_to_heap(hptr);
802802
}
803803

804+
void drop_traceback_tail(ClusterNetId net_id) {
805+
auto& route_ctx = g_vpr_ctx.mutable_routing();
806+
807+
auto* tail_ptr = route_ctx.trace[net_id].tail;
808+
auto node = tail_ptr->index;
809+
route_ctx.trace_nodes[net_id].erase(node);
810+
auto* trace_ptr = route_ctx.trace[net_id].head;
811+
while (trace_ptr!= nullptr) {
812+
t_trace* next_ptr = trace_ptr->next;
813+
if (next_ptr == tail_ptr) {
814+
trace_ptr->iswitch = tail_ptr->iswitch;
815+
trace_ptr->next = nullptr;
816+
route_ctx.trace[net_id].tail = trace_ptr;
817+
break;
818+
}
819+
trace_ptr = next_ptr;
820+
}
821+
free_trace_data(tail_ptr);
822+
}
823+
804824
void free_traceback(ClusterNetId net_id) {
805825
/* Puts the entire traceback (old routing) for this net on the free list *
806826
* and sets the route_ctx.trace_head pointers etc. for the net to NULL. */

vpr/src/route/route_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ void node_to_heap(int inode, float cost, int prev_node, int prev_edge, float bac
7979
bool is_empty_heap();
8080

8181
void free_traceback(ClusterNetId net_id);
82+
void drop_traceback_tail(ClusterNetId net_id);
8283
void free_traceback(t_trace* tptr);
8384

8485
void add_to_mod_list(int inode, std::vector<int>& modified_rr_node_inf);

0 commit comments

Comments
 (0)