Skip to content

Commit e4dff26

Browse files
authored
Merge branch 'master' into flatRecon_result_collection
2 parents 1dc11cf + 7a678a6 commit e4dff26

File tree

22 files changed

+375
-39
lines changed

22 files changed

+375
-39
lines changed

doc/src/vpr/command_line_usage.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,18 @@ If any of init_t, exit_t or alpha_t is specified, the user schedule, with a fixe
840840

841841
**Default:** ``1.0``
842842

843+
.. option:: --anneal_auto_init_t_estimator {cost_variance, equilibrium}
844+
845+
Controls which estimation method is used when selecting the starting temperature
846+
for the automatic annealing schedule.
847+
848+
The options for estimators are:
849+
850+
* ``cost_variance``: Estimates the initial temperature using the variance of cost after a set of trial swaps. The initial temperature is set to a value proportional to the variance.
851+
* ``equilibrium``: Estimates the initial temperature by trying to predict the equilibrium temperature for the initial placement (i.e. the temperature that would result in no change in cost).
852+
853+
**Default** ``cost_variance``
854+
843855
.. option:: --init_t <float>
844856

845857
The starting temperature of the anneal for the manual annealing schedule.

libs/libarchfpga/src/read_xml_arch_file_sg.cpp

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "pugixml_util.hpp"
55
#include "arch_error.h"
66
#include "switchblock_types.h"
7+
#include "vtr_util.h"
78

89
/**
910
* @brief Parses all <sg_link> tags under a <sg_link_list> tag.
@@ -26,32 +27,12 @@ static std::vector<t_sg_link> parse_sg_link_tags(pugi::xml_node sg_link_list_tag
2627
sg_link.seg_type = pugiutil::get_attribute(node, "seg_type", loc_data).as_string();
2728

2829
// Since the offset attributes are optional and might not exist, the as_int method will return a value of zero if the attribute is empty
29-
int x_offset = pugiutil::get_attribute(node, "x_offset", loc_data, pugiutil::OPTIONAL).as_int(0);
30-
int y_offset = pugiutil::get_attribute(node, "y_offset", loc_data, pugiutil::OPTIONAL).as_int(0);
31-
int z_offset = pugiutil::get_attribute(node, "z_offset", loc_data, pugiutil::OPTIONAL).as_int(0);
30+
sg_link.x_offset = pugiutil::get_attribute(node, "x_offset", loc_data, pugiutil::OPTIONAL).as_int(0);
31+
sg_link.y_offset = pugiutil::get_attribute(node, "y_offset", loc_data, pugiutil::OPTIONAL).as_int(0);
32+
sg_link.z_offset = pugiutil::get_attribute(node, "z_offset", loc_data, pugiutil::OPTIONAL).as_int(0);
3233

33-
if (x_offset == 0 && y_offset == 0 && z_offset == 0) {
34-
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "All offset fields in the <sg_link> are zero or missing.");
35-
}
36-
37-
// We expect exactly one non-zero offset so the gather and scatter points are joined by a node that can be represented by a straight wire.
38-
if (x_offset != 0) {
39-
sg_link.x_offset = x_offset;
40-
if (y_offset != 0 || z_offset != 0) {
41-
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "More than one of the offset fields in the <sg_link> are non-zero.");
42-
}
43-
}
44-
if (y_offset != 0) {
45-
sg_link.y_offset = y_offset;
46-
if (x_offset != 0 || z_offset != 0) {
47-
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "More than one of the offset fields in the <sg_link> are non-zero.");
48-
}
49-
}
50-
if (z_offset != 0) {
51-
sg_link.z_offset = z_offset;
52-
if (y_offset != 0 || x_offset != 0) {
53-
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "More than one of the offset fields in the <sg_link> are non-zero.");
54-
}
34+
if (!vtr::exactly_k_conditions(1, sg_link.x_offset != 0, sg_link.y_offset != 0, sg_link.z_offset != 0)) {
35+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "One and only one of the offset fields in the <sg_link> should be non-zero.");
5536
}
5637

5738
sg_link_list.push_back(sg_link);

libs/libarchfpga/src/switchblock_types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ enum e_directionality {
1818
/**
1919
* @brief At the intersection of routing channels, left, right, top and bottom specify the x- and y-directed channels
2020
* while above and under specify the switch block wires one a layer above or below the current one. above and below
21-
* are only used for multi-layer FPGAs.
21+
* are only used for multi-layer FPGAs. Note that the order of 2D sides is important, as it corresponds to the bit
22+
* order in t_rr_node_data::dir_side_.sides.
2223
*/
2324
enum e_side : unsigned char {
2425
TOP = 0,

libs/librrgraph/src/base/check_rr_graph.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ void check_rr_node(const RRGraphView& rr_graph,
473473

474474
e_pin_type class_type = e_pin_type::OPEN;
475475
int class_num_pins = -1;
476+
std::vector<e_side> rr_graph_sides;
477+
std::vector<e_side> arch_side_vec;
476478
switch (rr_type) {
477479
case e_rr_type::SOURCE:
478480
case e_rr_type::SINK:
@@ -511,6 +513,19 @@ void check_rr_node(const RRGraphView& rr_graph,
511513
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
512514
"in check_rr_node: inode %d (type %d) has a capacity of %d.\n", inode, rr_type, capacity);
513515
}
516+
rr_graph_sides = rr_graph.node_sides(rr_node);
517+
std::tie(std::ignore, std::ignore, arch_side_vec) = get_pin_coordinates(type, ptc_num, std::vector<e_side>(TOTAL_2D_SIDES.begin(), TOTAL_2D_SIDES.end()));
518+
// sides in the architecture are a superset of the sides for a pin in RR Graph. We iterate over the sides stored
519+
// in the RR Graph to ensure that all of them also exist in the architecture.
520+
for (size_t i = 0; i < rr_graph_sides.size(); i++) {
521+
if (std::find(arch_side_vec.begin(), arch_side_vec.end(), rr_graph_sides[i]) == arch_side_vec.end()) {
522+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
523+
"in check_rr_node: inode %d (type %d) has a different side '%s' in the RR graph and the architecture.\n",
524+
inode,
525+
rr_type,
526+
TOTAL_2D_SIDE_STRINGS[rr_graph_sides[i]]);
527+
}
528+
}
514529
break;
515530

516531
case e_rr_type::CHANX:

libs/librrgraph/src/base/rr_graph_storage.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,17 @@ const std::string& t_rr_graph_storage::node_direction_string(RRNodeId id) const
631631
return CONST_DIRECTION_STRING[int_direction];
632632
}
633633

634+
635+
const std::vector<e_side> t_rr_graph_storage::node_sides(RRNodeId id) const {
636+
std::vector<e_side> sides;
637+
for (const e_side& side : TOTAL_2D_SIDES) {
638+
if (is_node_on_specific_side(id, side)) {
639+
sides.push_back(side);
640+
}
641+
}
642+
return sides;
643+
}
644+
634645
const char* t_rr_graph_storage::node_side_string(RRNodeId id) const {
635646
for (const e_side& side : TOTAL_2D_SIDES) {
636647
if (is_node_on_specific_side(id, side)) {
@@ -807,7 +818,7 @@ void t_rr_graph_storage::set_node_direction(RRNodeId id, Direction new_direction
807818

808819
void t_rr_graph_storage::add_node_side(RRNodeId id, e_side new_side) {
809820
if (node_type(id) != e_rr_type::IPIN && node_type(id) != e_rr_type::OPIN) {
810-
VTR_LOG_ERROR("Attempted to set RR node 'side' for non-channel type '%s'", node_type_string(id));
821+
VTR_LOG_ERROR("Attempted to set RR node 'side' for non-pin type '%s'", node_type_string(id));
811822
}
812823
std::bitset<NUM_2D_SIDES> side_bits = node_storage_[id].dir_side_.sides;
813824
side_bits[size_t(new_side)] = true;

libs/librrgraph/src/base/rr_graph_storage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ class t_rr_graph_storage {
220220
id, side);
221221
}
222222

223+
/** @brief Get the sides where the node locates on. */
224+
const std::vector<e_side> node_sides(RRNodeId id) const;
225+
223226
/* FIXME: This function should be DEPRECATED!
224227
* Developers can easily use the following codes with more flexibility
225228
*

libs/librrgraph/src/base/rr_graph_view.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,11 @@ class RRGraphView {
432432
return node_storage_.is_node_on_specific_side(node, side);
433433
}
434434

435+
/** @brief Get the sides where the node locates on. */
436+
inline const std::vector<e_side> node_sides(RRNodeId node) const {
437+
return node_storage_.node_sides(node);
438+
}
439+
435440
/** @brief Return a string representing the side of a routing resource node.
436441
*/
437442
inline const char* node_side_string(RRNodeId node) const {

vpr/src/analytical_place/full_legalizer.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959

6060
#include "setup_grid.h"
6161
#include "stats.h"
62+
#ifndef NO_GRAPHICS
63+
#include "draw_global.h"
64+
#endif
6265

6366
std::unique_ptr<FullLegalizer> make_full_legalizer(e_ap_full_legalizer full_legalizer_type,
6467
const APNetlist& ap_netlist,
@@ -1001,6 +1004,7 @@ void FlatRecon::legalize(const PartialPlacement& p_placement) {
10011004

10021005
// Perform the initial placement on created clusters.
10031006
place_clusters(p_placement);
1007+
update_drawing_data_structures();
10041008
}
10051009

10061010
void NaiveFullLegalizer::create_clusters(const PartialPlacement& p_placement) {
@@ -1217,6 +1221,7 @@ void NaiveFullLegalizer::legalize(const PartialPlacement& p_placement) {
12171221
// made part of the placement and verify placement should check for
12181222
// it.
12191223
post_place_sync();
1224+
update_drawing_data_structures();
12201225
}
12211226

12221227
void APPack::legalize(const PartialPlacement& p_placement) {
@@ -1302,4 +1307,14 @@ void APPack::legalize(const PartialPlacement& p_placement) {
13021307

13031308
// Synchronize the pins in the clusters after placement.
13041309
post_place_sync();
1310+
update_drawing_data_structures();
13051311
}
1312+
1313+
void FullLegalizer::update_drawing_data_structures() {
1314+
#ifndef NO_GRAPHICS
1315+
// update graphic resources incase of clustering changes
1316+
if (get_draw_state_vars()) {
1317+
get_draw_state_vars()->refresh_graphic_resources_after_cluster_change();
1318+
}
1319+
#endif
1320+
}

vpr/src/analytical_place/full_legalizer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class FullLegalizer {
5959
* device grid and fixed blocks are observed.
6060
*/
6161
virtual void legalize(const PartialPlacement& p_placement) = 0;
62+
63+
/// @brief Update drawing data structure for current placement
64+
void update_drawing_data_structures();
6265

6366
protected:
6467
/// @brief The AP Netlist to fully legalize the flat placement of.

vpr/src/base/read_options.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "argparse.hpp"
77

88
#include "ap_flow_enums.h"
9+
#include "vpr_types.h"
910
#include "vtr_log.h"
1011
#include "vtr_path.h"
1112
#include "vtr_util.h"
@@ -690,6 +691,44 @@ struct ParsePlaceAgentSpace {
690691
}
691692
};
692693

694+
struct ParsePlaceInitTEstimator {
695+
ConvertedValue<e_anneal_init_t_estimator> from_str(const std::string& str) {
696+
ConvertedValue<e_anneal_init_t_estimator> conv_value;
697+
if (str == "cost_variance")
698+
conv_value.set_value(e_anneal_init_t_estimator::COST_VARIANCE);
699+
else if (str == "equilibrium")
700+
conv_value.set_value(e_anneal_init_t_estimator::EQUILIBRIUM);
701+
else {
702+
std::stringstream msg;
703+
msg << "Invalid conversion from '" << str << "' to e_anneal_init_t_estimator (expected one of: " << argparse::join(default_choices(), ", ") << ")";
704+
conv_value.set_error(msg.str());
705+
}
706+
return conv_value;
707+
}
708+
709+
ConvertedValue<std::string> to_str(e_anneal_init_t_estimator val) {
710+
ConvertedValue<std::string> conv_value;
711+
switch (val) {
712+
case e_anneal_init_t_estimator::COST_VARIANCE:
713+
conv_value.set_value("cost_variance");
714+
break;
715+
case e_anneal_init_t_estimator::EQUILIBRIUM:
716+
conv_value.set_value("equilibrium");
717+
break;
718+
default: {
719+
std::stringstream msg;
720+
msg << "Unknown e_anneal_init_t_estimator type.";
721+
conv_value.set_error(msg.str());
722+
}
723+
}
724+
return conv_value;
725+
}
726+
727+
std::vector<std::string> default_choices() {
728+
return {"cost_variance", "equilibrium"};
729+
}
730+
};
731+
693732
struct ParseFixPins {
694733
ConvertedValue<e_pad_loc_type> from_str(const std::string& str) {
695734
ConvertedValue<e_pad_loc_type> conv_value;
@@ -2273,6 +2312,20 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
22732312
.default_value("1.0")
22742313
.show_in(argparse::ShowIn::HELP_ONLY);
22752314

2315+
place_grp.add_argument<e_anneal_init_t_estimator, ParsePlaceInitTEstimator>(args.place_init_t_estimator, "--anneal_auto_init_t_estimator")
2316+
.help(
2317+
"Controls which estimation method is used when selecting the starting temperature "
2318+
"for the automatic annealing schedule.\n"
2319+
"\n"
2320+
"The options for estimators are:\n"
2321+
"\tcost_variance: Estimates the initial temperature using the variance "
2322+
"of cost after a set of trial swaps.\n"
2323+
"\tequilibrium: Estimates the initial temperature by trying to "
2324+
"predict the equilibrium temperature for the initial placement "
2325+
"(i.e. the temperature that would result in no change in cost).")
2326+
.default_value("cost_variance")
2327+
.show_in(argparse::ShowIn::HELP_ONLY);
2328+
22762329
place_grp.add_argument(args.PlaceInitT, "--init_t")
22772330
.help("Initial temperature for manual annealing schedule")
22782331
.default_value("100.0")

0 commit comments

Comments
 (0)