Skip to content

Commit 3f55019

Browse files
committed
address review
1 parent 7b48306 commit 3f55019

8 files changed

+105
-55
lines changed

libs/libarchfpga/src/physical_types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,8 +1671,8 @@ constexpr std::array<const char*, size_t(SwitchType::NUM_SWITCH_TYPES)> SWITCH_T
16711671
*/
16721672
constexpr const char* VPR_DELAYLESS_SWITCH_NAME = "__vpr_delayless_switch__";
16731673

1674-
/* Internal switch: used by the flat router */
1675-
constexpr const char* VPR_INTERNAL_SWITCH_NAME = "Internal Switch";
1674+
/* An intracluster switch automatically added to the RRG by the flat router. */
1675+
constexpr const char* VPR_INTERNAL_SWITCH_NAME = "__vpr_intra_cluster_switch__";
16761676

16771677
enum class BufferSize {
16781678
AUTO,

vpr/src/pack/post_routing_pb_pin_fixup.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,20 +1019,6 @@ static void update_cluster_routing_traces_with_post_routing_results(AtomContext&
10191019
pb->pb_route = new_pb_routes;
10201020
}
10211021

1022-
/********************************************************************
1023-
* Top-level function to synchronize a packed netlist to routing results
1024-
* The problem comes from a mismatch between the packing and routing results
1025-
* When there are equivalent input/output for any grids, router will try
1026-
* to swap the net mapping among these pins so as to achieve best
1027-
* routing optimization.
1028-
* However, it will cause the packing results out-of-date as the net mapping
1029-
* of each grid remain untouched once packing is done.
1030-
* This function aims to fix the mess after routing so that the net mapping
1031-
* can be synchronized
1032-
*
1033-
* Note:
1034-
* - This function SHOULD be run ONLY when routing is finished!!!
1035-
*******************************************************************/
10361022
void sync_netlists_to_routing(const Netlist<>& net_list,
10371023
const DeviceContext& device_ctx,
10381024
AtomContext& atom_ctx,

vpr/src/pack/post_routing_pb_pin_fixup.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@
99
/********************************************************************
1010
* Function declaration
1111
*******************************************************************/
12+
13+
/********************************************************************
14+
* Top-level function to synchronize a packed netlist to routing results
15+
* The problem comes from a mismatch between the packing and routing results
16+
* When there are equivalent input/output for any grids, the router will try
17+
* to swap the net mapping among these pins so as to achieve best
18+
* routing optimization.
19+
* However, it will cause the packing results out-of-date as the net mapping
20+
* of each grid remain untouched once packing is done.
21+
* This function aims to fix the mess after routing so that the net mapping
22+
* can be synchronized
23+
*
24+
* Note:
25+
* - This function SHOULD be run ONLY when routing is finished.
26+
* - This function only handles the two-stage routing results.
27+
* See \see sync_netlists_to_routing_flat() for the flat routing case.
28+
*******************************************************************/
1229
void sync_netlists_to_routing(const Netlist<>& net_list,
1330
const DeviceContext& device_ctx,
1431
AtomContext& atom_ctx,

vpr/src/pack/sync_netlists_to_routing_flat.cpp

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
/********************************************************************
2-
* This file includes functions to fix up the pb pin mapping results
3-
* after routing optimization
4-
*******************************************************************/
5-
/* Headers from vtrutil library */
1+
/**
2+
* @file sync_netlists_to_routing_flat.cpp
3+
*
4+
* @brief Implementation for \see sync_netlists_to_routing_flat().
5+
*/
6+
67
#include "clustered_netlist_fwd.h"
78
#include "clustered_netlist_utils.h"
89
#include "logic_types.h"
@@ -20,12 +21,50 @@
2021

2122
#include "sync_netlists_to_routing_flat.h"
2223

24+
/* Static function decls (file-scope) */
25+
26+
/** Get intra-cluster connections from a given RouteTree. Output <source, sink> pairs to \p out_connections . */
2327
static void get_intra_cluster_connections(const RouteTree& tree, std::vector<std::pair<RRNodeId, RRNodeId>>& out_connections);
28+
29+
/** Rudimentary intra-cluster router between two pb_graph pins.
30+
* This is needed because the flat router compresses the RRG reducing singular paths into nodes.
31+
* We need to unpack it to get valid packing results, which is the purpose of this simple BFS router.
32+
* Outputs the path to the pb_routes field of \p out_pb . */
2433
static void route_intra_cluster_conn(const t_pb_graph_pin* source_pin, const t_pb_graph_pin* sink_pin, AtomNetId net_id, t_pb* out_pb);
34+
35+
/** Rebuild the pb.pb_routes struct for each cluster block from flat routing results.
36+
* The pb_routes struct holds all intra-cluster routing. */
2537
static void sync_pb_routes_to_routing(void);
38+
39+
/** Rebuild ClusteredNetlist from flat routing results, since some nets can move in/out of a block after routing. */
2640
static void sync_clustered_netlist_to_routing(void);
41+
42+
/** Rebuild atom_lookup.atom_pin_pb_graph_pin and pb.atom_pin_bit_index from flat routing results.
43+
* These contain mappings between the AtomNetlist and the physical pins, which are invalidated after flat routing due to changed pin rotations.
44+
* (i.e. the primitive has equivalent input pins and flat routing used a different pin) */
2745
static void fixup_atom_pb_graph_pin_mapping(void);
2846

47+
48+
/* Function definitions */
49+
50+
/** Is the clock net found in the routing results?
51+
* (If not, clock_modeling is probably ideal and we should preserve clock routing while rebuilding.) */
52+
inline bool is_clock_net_routed(void){
53+
auto& atom_ctx = g_vpr_ctx.atom();
54+
auto& route_ctx = g_vpr_ctx.routing();
55+
56+
for(auto net_id: atom_ctx.nlist.nets()){
57+
auto& tree = route_ctx.route_trees[net_id];
58+
if(!tree)
59+
continue;
60+
if(route_ctx.is_clock_net[net_id]) /* Clock net has routing */
61+
return true;
62+
}
63+
64+
return false;
65+
}
66+
67+
/** Get the ClusterBlockId for a given RRNodeId. */
2968
inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode){
3069
auto& device_ctx = g_vpr_ctx.device();
3170
auto& place_ctx = g_vpr_ctx.placement();
@@ -51,7 +90,6 @@ inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode){
5190
return clb;
5291
}
5392

54-
/* Output all intra-cluster connections for a RouteTreeNode */
5593
static void get_intra_cluster_connections(const RouteTree& tree, std::vector<std::pair<RRNodeId, RRNodeId>>& out_connections){
5694
auto& rr_graph = g_vpr_ctx.device().rr_graph;
5795

@@ -73,10 +111,6 @@ static void get_intra_cluster_connections(const RouteTree& tree, std::vector<std
73111
}
74112
}
75113

76-
/** Rudimentary intra-cluster router between two pb_graph pins.
77-
* Easier to use than the packer's router, but it assumes that there is only one path between the provided pins.
78-
* (which should be the case due to the flat router's RR graph compression)
79-
* Outputs the path to the given pb. */
80114
static void route_intra_cluster_conn(const t_pb_graph_pin* source_pin, const t_pb_graph_pin* sink_pin, AtomNetId net_id, t_pb* out_pb){
81115
std::unordered_set<const t_pb_graph_pin*> visited;
82116
std::deque<const t_pb_graph_pin*> queue;
@@ -117,7 +151,7 @@ static void route_intra_cluster_conn(const t_pb_graph_pin* source_pin, const t_p
117151
}
118152
path.push_back(source_pin);
119153

120-
/* Output the path into out_pb_routes (start from source) */
154+
/* Output the path into out_pb, starting from source. This is where the pb_route is updated */
121155
int prev_pin_id = -1;
122156
for(auto it = path.rbegin(); it != path.rend(); ++it){
123157
cur_pin = *it;
@@ -155,14 +189,17 @@ static void sync_pb_routes_to_routing(void){
155189
auto& route_ctx = g_vpr_ctx.routing();
156190
auto& rr_graph = device_ctx.rr_graph;
157191

192+
/* Was the clock net routed? */
193+
bool clock_net_is_routed = is_clock_net_routed();
194+
158195
/* Clear out existing pb_routes: they were made by the intra cluster router and are invalid now */
159196
for (ClusterBlockId clb_blk_id : cluster_ctx.clb_nlist.blocks()) {
160-
/* Only erase entries which are not associated with a clock net: the router doesn't touch the clock nets
161-
* XXX: Assumes --clock_modeling ideal */
197+
/* If we don't have routing for the clock net, don't erase entries associated with a clock net.
198+
* Otherwise we won't have data to rebuild them */
162199
std::vector<int> pins_to_erase;
163200
auto& pb_routes = cluster_ctx.clb_nlist.block_pb(clb_blk_id)->pb_route;
164201
for(auto& [pin, pb_route]: pb_routes){
165-
if(!route_ctx.is_clock_net[pb_route.atom_net_id])
202+
if(clock_net_is_routed || !route_ctx.is_clock_net[pb_route.atom_net_id])
166203
pins_to_erase.push_back(pin);
167204
}
168205

@@ -221,8 +258,9 @@ static void sync_pb_routes_to_routing(void){
221258
}
222259
}
223260

224-
/** Rebuild the ClusterNetId <-> AtomNetId lookup after compressing the ClusterNetlist
225-
* Needs the "most recent" ClusterNetIds in atom_ctx.lookup: won't work after invalidating the ClusterNetIds twice */
261+
/** Rebuild the ClusterNetId <-> AtomNetId lookup after compressing the ClusterNetlist.
262+
* Needs the old ClusterNetIds in atom_ctx.lookup. Won't work after calling compress() twice,
263+
* since we won't have access to the old IDs in the IdRemapper anywhere. */
226264
inline void rebuild_atom_nets_lookup(ClusteredNetlist::IdRemapper& remapped){
227265
auto& atom_ctx = g_vpr_ctx.mutable_atom();
228266
auto& atom_lookup = atom_ctx.lookup;
@@ -248,10 +286,14 @@ static void sync_clustered_netlist_to_routing(void){
248286
auto& atom_ctx = g_vpr_ctx.mutable_atom();
249287
auto& atom_lookup = atom_ctx.lookup;
250288

251-
/* 1. Remove all nets, pins and ports from the clustered netlist (except clocks) */
289+
bool clock_net_is_routed = is_clock_net_routed();
290+
291+
/* 1. Remove all nets, pins and ports from the clustered netlist.
292+
* If the clock net is not routed, don't remove entries for the clock net
293+
* otherwise we won't have data to rebuild them. */
252294
for(auto net_id: clb_netlist.nets()){
253295
auto atom_net_id = atom_lookup.atom_net(net_id);
254-
if(route_ctx.is_clock_net[atom_net_id])
296+
if(!clock_net_is_routed && route_ctx.is_clock_net[atom_net_id])
255297
continue;
256298

257299
clb_netlist.remove_net(net_id);
@@ -260,14 +302,14 @@ static void sync_clustered_netlist_to_routing(void){
260302
for(auto pin_id: clb_netlist.pins()){
261303
ClusterNetId clb_net_id = clb_netlist.pin_net(pin_id);
262304
auto atom_net_id = atom_lookup.atom_net(clb_net_id);
263-
if(atom_net_id && route_ctx.is_clock_net[atom_net_id])
305+
if(!clock_net_is_routed && atom_net_id && route_ctx.is_clock_net[atom_net_id])
264306
continue;
265307
clb_netlist.remove_pin(pin_id);
266308
}
267309
for(auto port_id: clb_netlist.ports()){
268310
ClusterNetId clb_net_id = clb_netlist.port_net(port_id, 0);
269311
auto atom_net_id = atom_lookup.atom_net(clb_net_id);
270-
if(atom_net_id && route_ctx.is_clock_net[atom_net_id])
312+
if(!clock_net_is_routed && atom_net_id && route_ctx.is_clock_net[atom_net_id])
271313
continue;
272314
clb_netlist.remove_port(port_id);
273315
}
@@ -346,7 +388,6 @@ static void sync_clustered_netlist_to_routing(void){
346388
}
347389
}
348390

349-
/** Fix up pin rotation maps and the atom pin -> pb graph pin lookup for every block */
350391
static void fixup_atom_pb_graph_pin_mapping(void){
351392
auto& cluster_ctx = g_vpr_ctx.clustering();
352393
auto& atom_ctx = g_vpr_ctx.mutable_atom();
Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
#include "netlist.h"
22

3-
/**
4-
* Regenerate intra-cluster routing in the packer ctx from flat routing results.
5-
* This function SHOULD be run ONLY when routing is finished!!!
6-
*/
3+
/********************************************************************
4+
* Top-level function to synchronize packing results to routing results.
5+
* Flat routing invalidates the ClusteredNetlist since nets may be routed
6+
* inside or outside a block and changes virtually all intrablock routing.
7+
* This function:
8+
* - rebuilds ClusteredNetlist
9+
* - rebuilds all pb_routes
10+
* - rebuilds pb graph <-> atom pin mapping in AtomLookup
11+
* taking routing results as the source of truth.
12+
*
13+
* Note:
14+
* - This function SHOULD be run ONLY when routing is finished.
15+
* - This function only handles the flat routing results.
16+
* See \see sync_netlists_to_routing() for the two-stage case.
17+
*******************************************************************/
718
void sync_netlists_to_routing_flat(void);

vpr/src/route/annotate_routing.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/********************************************************************
22
* This file includes functions that are used to annotate routing results
3-
* from VPR to OpenFPGA
3+
* from VPR to OpenFPGA. (i.e. create a mapping from RRNodeIds to ClusterNetIds)
44
*******************************************************************/
5-
/* Headers from vtrutil library */
5+
66
#include "vpr_error.h"
77
#include "vtr_assert.h"
88
#include "vtr_time.h"
@@ -13,13 +13,6 @@
1313

1414
#include "annotate_routing.h"
1515

16-
/********************************************************************
17-
* Create a mapping between each rr_node and its mapped nets
18-
* based on VPR routing results
19-
* - Store the net ids mapped to each routing resource nodes
20-
* - Mapped nodes should have valid net ids (except SOURCE and SINK nodes)
21-
* - Unmapped rr_node will use invalid ids
22-
*******************************************************************/
2316
vtr::vector<RRNodeId, ClusterNetId> annotate_rr_node_nets(const ClusteringContext& cluster_ctx,
2417
const DeviceContext& device_ctx,
2518
const bool& verbose) {

vpr/src/route/annotate_routing.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#ifndef ANNOTATE_ROUTING_H
22
#define ANNOTATE_ROUTING_H
33

4-
/********************************************************************
5-
* Include header files that are required by function declaration
6-
*******************************************************************/
74
#include "vpr_context.h"
85

96
/********************************************************************
10-
* Function declaration
7+
* Create a mapping between each rr_node and its mapped nets
8+
* based on VPR routing results.
9+
* - Store the net ids mapped to each routing resource nodes
10+
* - Mapped nodes should have valid net ids (except SOURCE and SINK nodes)
11+
* - Unmapped rr_node will use invalid ids
1112
*******************************************************************/
12-
1313
vtr::vector<RRNodeId, ClusterNetId> annotate_rr_node_nets(const ClusteringContext& cluster_ctx,
1414
const DeviceContext& device_ctx,
1515
const bool& verbose);

vpr/src/route/route_utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ void generate_route_timing_reports(const t_router_opts& router_opts,
7070
/** Get the maximum number of pins used in the netlist (used to allocate things) */
7171
int get_max_pins_per_net(const Netlist<>& net_list);
7272

73+
/** Get the RouteTree associated with the ClusterNetId.
74+
* Flat routing maps AtomNetIds to RouteTrees instead, so we need to first look up the associated AtomNetId. */
7375
inline const vtr::optional<RouteTree>& get_route_tree_from_cluster_net_id(ClusterNetId net_id){
7476
auto& route_ctx = g_vpr_ctx.routing();
7577
if(!route_ctx.is_flat){

0 commit comments

Comments
 (0)