Skip to content

Commit fbe788f

Browse files
authored
Merge branch 'master' into ap_high_fanout_net_thresholding
2 parents 682fe16 + 8255ada commit fbe788f

File tree

6 files changed

+170
-25
lines changed

6 files changed

+170
-25
lines changed

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi
721721

722722
analysis_opts.timing_update_type = Options.timing_update_type;
723723
analysis_opts.write_timing_summary = Options.write_timing_summary;
724+
analysis_opts.skip_sync_clustering_and_routing_results = Options.skip_sync_clustering_and_routing_results;
724725
analysis_opts.generate_net_timing_report = Options.generate_net_timing_report;
725726
}
726727

vpr/src/base/read_options.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3102,6 +3102,13 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
31023102
.help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.")
31033103
.show_in(argparse::ShowIn::HELP_ONLY);
31043104

3105+
analysis_grp.add_argument<bool, ParseOnOff>(args.skip_sync_clustering_and_routing_results, "--skip_sync_clustering_and_routing_results")
3106+
.help(
3107+
"Select to skip the synchronization on clustering results based on routing optimization results."
3108+
"Note that when this sync-up is disabled, clustering results may be wrong (leading to incorrect bitstreams)!")
3109+
.default_value("off")
3110+
.show_in(argparse::ShowIn::HELP_ONLY);
3111+
31053112
analysis_grp.add_argument<bool, ParseOnOff>(args.generate_net_timing_report, "--generate_net_timing_report")
31063113
.help(
31073114
"Generates a net timing report in CSV format, reporting the delay and slack\n"

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ struct t_options {
274274
argparse::ArgValue<e_post_synth_netlist_unconn_handling> post_synth_netlist_unconn_output_handling;
275275
argparse::ArgValue<bool> post_synth_netlist_module_parameters;
276276
argparse::ArgValue<std::string> write_timing_summary;
277+
argparse::ArgValue<bool> skip_sync_clustering_and_routing_results;
277278
argparse::ArgValue<bool> generate_net_timing_report;
278279
};
279280

vpr/src/base/vpr_api.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,30 +1426,35 @@ bool vpr_analysis_flow(const Netlist<>& net_list,
14261426
VTR_LOG("*****************************************************************************************\n");
14271427
}
14281428

1429-
/* If routing is successful, apply post-routing annotations
1429+
/* If routing is successful and users do not force to skip the sync-up,
1430+
* - apply post-routing annotations
14301431
* - apply logic block pin fix-up
14311432
*
14321433
* Note:
14331434
* - Turn on verbose output when users require verbose output
14341435
* for packer (default verbosity is set to 2 for compact logs)
14351436
*/
14361437
if (route_status.success()) {
1437-
if (is_flat) {
1438-
sync_netlists_to_routing_flat();
1438+
if (!analysis_opts.skip_sync_clustering_and_routing_results) {
1439+
if (is_flat) {
1440+
sync_netlists_to_routing_flat();
1441+
} else {
1442+
sync_netlists_to_routing(net_list,
1443+
g_vpr_ctx.device(),
1444+
g_vpr_ctx.mutable_atom(),
1445+
g_vpr_ctx.mutable_clustering(),
1446+
g_vpr_ctx.placement(),
1447+
vpr_setup.PackerOpts.pack_verbosity > 2);
1448+
}
14391449
} else {
1440-
sync_netlists_to_routing(net_list,
1441-
g_vpr_ctx.device(),
1442-
g_vpr_ctx.mutable_atom(),
1443-
g_vpr_ctx.mutable_clustering(),
1444-
g_vpr_ctx.placement(),
1445-
vpr_setup.PackerOpts.pack_verbosity > 2);
1450+
VTR_LOG_WARN("Synchronization between packing and routing results was not applied due to skip_sync_clustering_and_routing_results being set to true\n");
14461451
}
14471452

14481453
std::string post_routing_packing_output_file_name = vpr_setup.PackerOpts.output_file + ".post_routing";
14491454
write_packing_results_to_xml(Arch.architecture_id,
14501455
post_routing_packing_output_file_name.c_str());
14511456
} else {
1452-
VTR_LOG_WARN("Synchronization between packing and routing results is not applied due to illegal circuit implementation\n");
1457+
VTR_LOG_WARN("Synchronization between packing and routing results was not applied due to illegal circuit implementation\n");
14531458
}
14541459
VTR_LOG("\n");
14551460

vpr/src/base/vpr_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,7 @@ struct t_analysis_opts {
13571357
bool generate_net_timing_report;
13581358

13591359
e_timing_update_type timing_update_type;
1360+
bool skip_sync_clustering_and_routing_results;
13601361
};
13611362

13621363
/// Stores NoC specific options, when supplied as an input by the user

vpr/src/place/initial_placement.cpp

Lines changed: 145 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <limits>
3030
#include <optional>
3131
#include <queue>
32+
#include <vector>
3233

3334
#ifdef VERBOSE
3435
void print_clb_placement(const char* fname);
@@ -1628,27 +1629,20 @@ static void print_ap_initial_placer_status(unsigned iteration,
16281629
}
16291630

16301631
/**
1631-
* @brief Places all blocks in the clustered netlist as close to the global
1632-
* placement produced by the AP flow.
1633-
*
1634-
* This function will place clusters in passes. In the first pass, it will try
1635-
* to place clusters exactly where their global placement is (according to the
1636-
* atoms contained in the cluster). In the second pass, all unplaced clusters
1637-
* will try to be placed within 1 tile of where they wanted to be placed.
1638-
* Subsequent passes will then try to place clusters at exponentially farther
1639-
* distances.
1632+
* @brief Collects unplaced clusters and sorts such that clusters which should
1633+
* be placed first appear early in the list.
16401634
*
16411635
* The clusters are sorted based on how many clusters are in the macro that
16421636
* contains this cluster and the standard deviation of the placement of atoms
16431637
* within the cluster. Large macros with low standard deviation will be placed
16441638
* first.
16451639
*/
1646-
static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
1647-
BlkLocRegistry& blk_loc_registry,
1648-
const PlaceMacros& place_macros,
1649-
const FlatPlacementInfo& flat_placement_info) {
1650-
const ClusteredNetlist& cluster_netlist = g_vpr_ctx.clustering().clb_nlist;
1651-
const DeviceGrid& device_grid = g_vpr_ctx.device().grid;
1640+
static inline std::vector<ClusterBlockId> get_sorted_clusters_to_place(
1641+
BlkLocRegistry& blk_loc_registry,
1642+
const PlaceMacros& place_macros,
1643+
const ClusteredNetlist& cluster_netlist,
1644+
const FlatPlacementInfo& flat_placement_info) {
1645+
16521646
const auto& cluster_constraints = g_vpr_ctx.floorplanning().cluster_constraints;
16531647

16541648
// Create a list of clusters to place.
@@ -1728,6 +1722,29 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
17281722
return cluster_score[lhs] > cluster_score[rhs];
17291723
});
17301724

1725+
return clusters_to_place;
1726+
}
1727+
1728+
/**
1729+
* @brief Tries to place all of the given clusters as closed to their flat
1730+
* placement as possible (minimum displacement from flat placement).
1731+
*
1732+
* This function will place clusters in passes. In the first pass, it will try
1733+
* to place clusters exactly where their global placement is (according to the
1734+
* atoms contained in the cluster). In the second pass, all unplaced clusters
1735+
* will try to be placed within 1 tile of where they wanted to be placed.
1736+
* Subsequent passes will then try to place clusters at exponentially farther
1737+
* distances.
1738+
*/
1739+
static inline void place_blocks_min_displacement(std::vector<ClusterBlockId>& clusters_to_place,
1740+
enum e_pad_loc_type pad_loc_type,
1741+
BlkLocRegistry& blk_loc_registry,
1742+
const PlaceMacros& place_macros,
1743+
const ClusteredNetlist& cluster_netlist,
1744+
const FlatPlacementInfo& flat_placement_info) {
1745+
1746+
const DeviceGrid& device_grid = g_vpr_ctx.device().grid;
1747+
17311748
// Compute the max L1 distance on the device. If we cannot find a location
17321749
// to place a cluster within this distance, then no legal location exists.
17331750
float max_distance_on_device = device_grid.width() + device_grid.height();
@@ -1844,13 +1861,126 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
18441861
iter++;
18451862
}
18461863

1864+
if (clusters_to_place.size() > 0) {
1865+
VTR_LOG("Unable to place all clusters.\n");
1866+
VTR_LOG("Clusters left unplaced:\n");
1867+
for (ClusterBlockId blk_id : clusters_to_place) {
1868+
VTR_LOG("\t%s\n", cluster_netlist.block_name(blk_id).c_str());
1869+
}
1870+
}
1871+
18471872
// Check if anything has not been placed, if so just crash for now.
18481873
// TODO: Should fall back on the original initial placer. Unless there is a
18491874
// bug in the code above, it could be that it is challenging to place
18501875
// for this circuit.
18511876
VTR_ASSERT(clusters_to_place.size() == 0);
18521877
}
18531878

1879+
/**
1880+
* @brief Places all blocks in the clustered netlist as close to the global
1881+
* placement produced by the AP flow.
1882+
*
1883+
* This function places the blocks in stages. The goal of this stage-based
1884+
* approach is to place clusters which are challenging to place first. Within
1885+
* each stage, the clusters are ordered based on heuristics such that the most
1886+
* impactful clusters get first dibs on placement.
1887+
*/
1888+
static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
1889+
BlkLocRegistry& blk_loc_registry,
1890+
const PlaceMacros& place_macros,
1891+
const FlatPlacementInfo& flat_placement_info) {
1892+
1893+
const ClusteredNetlist& cluster_netlist = g_vpr_ctx.clustering().clb_nlist;
1894+
1895+
// Get a list of clusters to place, sorted based on different heuristics
1896+
// to try to give more important clusters first dibs on the placement.
1897+
std::vector<ClusterBlockId> sorted_cluster_list = get_sorted_clusters_to_place(blk_loc_registry,
1898+
place_macros,
1899+
cluster_netlist,
1900+
flat_placement_info);
1901+
1902+
// 1: Get the constrained clusters and place them first. For now, we place
1903+
// constrained clusters first to prevent other clusters from taking their
1904+
// spot if they are constrained to one and only one site.
1905+
// TODO: This gives clusters with region constraints VIP access to the
1906+
// placement. This may not give the best results. This should be
1907+
// investigated more once region constraints are more supported in the
1908+
// AP flow.
1909+
std::vector<ClusterBlockId> constrained_clusters;
1910+
constrained_clusters.reserve(sorted_cluster_list.size());
1911+
for (ClusterBlockId blk_id : sorted_cluster_list) {
1912+
if (is_cluster_constrained(blk_id))
1913+
constrained_clusters.push_back(blk_id);
1914+
}
1915+
1916+
if (constrained_clusters.size() > 0) {
1917+
VTR_LOG("Placing constrained clusters...\n");
1918+
place_blocks_min_displacement(constrained_clusters,
1919+
pad_loc_type,
1920+
blk_loc_registry,
1921+
place_macros,
1922+
cluster_netlist,
1923+
flat_placement_info);
1924+
VTR_LOG("\n");
1925+
}
1926+
1927+
// 2. Get all of the large macros and place them next. Large macros have a
1928+
// hard time finding a place to go since they take up so much space. They
1929+
// also can have a larger impact on the quality of the placement, so we
1930+
// give them dibs on placement early.
1931+
std::vector<ClusterBlockId> large_macro_clusters;
1932+
large_macro_clusters.reserve(sorted_cluster_list.size());
1933+
for (ClusterBlockId blk_id : sorted_cluster_list) {
1934+
// If this block has been placed, skip it.
1935+
if (is_block_placed(blk_id, blk_loc_registry.block_locs()))
1936+
continue;
1937+
1938+
// Get the size of the macro this block is a part of.
1939+
t_pl_macro pl_macro = get_or_create_macro(blk_id, place_macros);
1940+
size_t macro_size = pl_macro.members.size();
1941+
if (macro_size > 1) {
1942+
// If the size of the macro is larger than 1 (there is more than
1943+
// one cluster in this macro) add to the list.
1944+
large_macro_clusters.push_back(blk_id);
1945+
}
1946+
}
1947+
1948+
if (large_macro_clusters.size() > 0) {
1949+
VTR_LOG("Placing clusters that are part of larger macros...\n");
1950+
place_blocks_min_displacement(large_macro_clusters,
1951+
pad_loc_type,
1952+
blk_loc_registry,
1953+
place_macros,
1954+
cluster_netlist,
1955+
flat_placement_info);
1956+
VTR_LOG("\n");
1957+
}
1958+
1959+
// 3. Place the rest of the clusters. These clusters will be unconstrained
1960+
// and be of small size; so they are more free to fill in the gaps left
1961+
// behind.
1962+
std::vector<ClusterBlockId> clusters_to_place;
1963+
clusters_to_place.reserve(sorted_cluster_list.size());
1964+
for (ClusterBlockId blk_id : sorted_cluster_list) {
1965+
// If this block has been placed, skip it.
1966+
if (is_block_placed(blk_id, blk_loc_registry.block_locs()))
1967+
continue;
1968+
1969+
clusters_to_place.push_back(blk_id);
1970+
}
1971+
1972+
if (clusters_to_place.size() > 0) {
1973+
VTR_LOG("Placing general clusters...\n");
1974+
place_blocks_min_displacement(clusters_to_place,
1975+
pad_loc_type,
1976+
blk_loc_registry,
1977+
place_macros,
1978+
cluster_netlist,
1979+
flat_placement_info);
1980+
VTR_LOG("\n");
1981+
}
1982+
}
1983+
18541984
void initial_placement(const t_placer_opts& placer_opts,
18551985
const char* constraints_file,
18561986
const t_noc_opts& noc_opts,

0 commit comments

Comments
 (0)