Skip to content

Commit 9542ce9

Browse files
Merge branch 'master' into interposer_parsing
2 parents b257a62 + 004339f commit 9542ce9

File tree

16 files changed

+8675
-6578
lines changed

16 files changed

+8675
-6578
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.

doc/src/vtr/get_vtr.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ How to Cite
99
Citations are important in academia, as they ensure contributors receive credit for their efforts.
1010
Therefore please use the following paper as a general citation whenever you use VTR:
1111

12-
M. A. Elgammal, A. Mohaghegh, S. G. Shahrouz, F. Mahmoudi, F. Koşar, K. Talaei, J. Fife, D. Khadivi, K. E. Murray, A. Boutros, K.B. Kent, J. Goeders, V. Betz "VTR 9: Open-Source CAD for Fabric and Beyond FPGA Architecture Exploration" ACM TRETS, 2024
12+
M. A. Elgammal, A. Mohaghegh, S. G. Shahrouz, F. Mahmoudi, F. Koşar, K. Talaei, J. Fife, D. Khadivi, K. E. Murray, A. Boutros, K.B. Kent, J. Goeders, V. Betz "VTR 9: Open-Source CAD for Fabric and Beyond FPGA Architecture Exploration" ACM TRETS, 2025
1313

1414
Bibtex:
1515

libs/libvqm/vqm_parser.l

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
^[ \t]*\/\/[^\n\r]*(\n|\r\n) /* skip one-line comments */
4141
^[ \t]*\(\*[^\n\r]*\*\) /* skip synthesis attributes and directives */
4242
[ \t]+ /* skip white spaces */
43-
! /* skip the logical operator ! applied on the input ports of the lut - this results in lut mask not being valid anoymore */
43+
! /* skip the logical operator ! applied on the input ports of the lut - this results in lut mask not being valid anoymore */
4444
(\n|\r\n) /* skip empty lines */
4545
module return TOKEN_MODULE;
4646
endmodule return TOKEN_ENDMODULE;
@@ -67,6 +67,11 @@ assign return TOKEN_ASSIGN;
6767
strcpy(yylval.string, yytext+1);
6868
return TOKEN_ESCAPEDID;
6969
}
70+
~\\[^ ^\t^;]+ {
71+
yylval.string = (char *)malloc(yyleng - 1);
72+
strcpy(yylval.string, yytext+2);
73+
return TOKEN_ESCAPEDID;
74+
}
7075
\"[^\"]*\" {
7176
yylval.string = (char *)malloc(yyleng-1);
7277
strncpy(yylval.string, yytext+1, yyleng-2);

utils/vqm2blif/src/base/vqm2blif_util.cpp

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
552552
reg_outputs = true;
553553
}
554554
} else {
555-
VTR_ASSERT(ram_info.mode == "dual_port" || ram_info.mode == "bidir_dual_port");
555+
VTR_ASSERT(ram_info.mode == "dual_port" || ram_info.mode == "bidir_dual_port" || ram_info.mode == "quad_port");
556556
VTR_ASSERT_MSG(ram_info.port_b_input_clock, "RAM inputs always assumed sequential");
557557

558558
if (ram_info.mode == "dual_port" && ram_info.port_b_output_clock) {
@@ -568,6 +568,16 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
568568
cout << " port A output sequential: " << bool(ram_info.port_a_output_clock) << "\n";
569569
cout << " port B output sequential: " << bool(ram_info.port_b_output_clock) << "\n";
570570
}
571+
} else {
572+
if (ram_info.port_a_output_clock && ram_info.port_b_output_clock) {
573+
reg_outputs = true; //Sequential output
574+
} else if (!ram_info.port_a_output_clock && !ram_info.port_b_output_clock) {
575+
reg_outputs = false; //Comb output
576+
} else {
577+
cout << "Unable to resolve whether quad port RAM " << vqm_node->name << " outputs are sequential or combinational:\n";
578+
cout << " port A output sequential: " << bool(ram_info.port_a_output_clock) << "\n";
579+
cout << " port B output sequential: " << bool(ram_info.port_b_output_clock) << "\n";
580+
}
571581
}
572582
}
573583

@@ -602,6 +612,8 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
602612
//&& (port_b_data_width == NULL) && (port_b_addr_width == NULL)) {
603613
if(ram_info.mode == "single_port" || ram_info.mode == "rom") {
604614
VTR_ASSERT(ram_info.port_b_addr_width == 0);
615+
VTR_ASSERT(ram_info.port_b_addr2_width == 0);
616+
VTR_ASSERT(ram_info.port_a_addr2_width == 0);
605617

606618
//Only print the address width, the data widths are handled by the VPR memory class
607619
mode_hash.append(".port_a_address_width{" + std::to_string(ram_info.port_a_addr_width) + "}");
@@ -613,8 +625,9 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
613625
}
614626

615627
//A dual port memory, both port A and B params have been found
616-
} else {
617-
VTR_ASSERT(ram_info.mode == "dual_port" || ram_info.mode == "bidir_dual_port");
628+
} else if (ram_info.mode == "dual_port" || ram_info.mode == "bidir_dual_port"){
629+
VTR_ASSERT(ram_info.port_b_addr2_width == 0);
630+
VTR_ASSERT(ram_info.port_a_addr2_width == 0);
618631

619632
//2) Both ports are the same size, so only append the address widths, the data widths are handled by the VPR memory class
620633
if ( (ram_info.port_a_data_width == ram_info.port_b_data_width)
@@ -645,6 +658,53 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
645658
tmp_mode_hash.append(".port_a_data_width{" + std::to_string(ram_info.port_a_data_width) + "}");
646659
tmp_mode_hash.append(".port_b_data_width{" + std::to_string(ram_info.port_b_data_width) + "}");
647660

661+
LogicalModelId arch_model_id = arch_models.get_model_by_name(tmp_mode_hash);
662+
if (!arch_model_id.is_valid()) {
663+
//3a) Not found, use the default name (no specific address/data widths)
664+
; // do nothing
665+
} else {
666+
//3b) Use the more detailed name, since it was found in the architecture
667+
mode_hash = tmp_mode_hash;
668+
}
669+
}
670+
} else {
671+
VTR_ASSERT(ram_info.mode == "quad_port");
672+
673+
//2) Both ports are the same size, so only append the address widths, the data widths are handled by the VPR memory class
674+
if ( (ram_info.port_a_data_width == ram_info.port_b_data_width)
675+
&& (ram_info.port_a_addr_width == ram_info.port_b_addr_width)
676+
&& (ram_info.port_a_addr_width == ram_info.port_b_addr2_width)
677+
&& (ram_info.port_a_addr2_width == ram_info.port_b_addr2_width)) {
678+
679+
mode_hash.append(".port_a_address_width{" + std::to_string(ram_info.port_a_addr_width) + "}");
680+
mode_hash.append(".port_a_address2_width{" + std::to_string(ram_info.port_a_addr2_width) + "}");
681+
mode_hash.append(".port_b_address_width{" + std::to_string(ram_info.port_b_addr_width) + "}");
682+
mode_hash.append(".port_b_address2_width{" + std::to_string(ram_info.port_b_addr2_width) + "}");
683+
684+
LogicalModelId arch_model_id = arch_models.get_model_by_name(mode_hash);
685+
if (!arch_model_id.is_valid()) {
686+
cout << "Error: could not find dual port (non-mixed_width) memory primitive '" << mode_hash << "' in architecture file";
687+
exit(1);
688+
}
689+
//3) Mixed width dual port ram
690+
} else {
691+
//Make a temporary copy of the mode hash
692+
string tmp_mode_hash = mode_hash;
693+
694+
/*
695+
* Try to see if the detailed version exists in the architecture,
696+
* if it does, use it. Otherwise use the operation mode only.
697+
*/
698+
699+
tmp_mode_hash.append(".port_a_address_width{" + std::to_string(ram_info.port_a_addr_width) + "}");
700+
tmp_mode_hash.append(".port_a_address2_width{" + std::to_string(ram_info.port_a_addr2_width) + "}");
701+
tmp_mode_hash.append(".port_b_address_width{" + std::to_string(ram_info.port_b_addr_width) + "}");
702+
tmp_mode_hash.append(".port_b_address2_width{" + std::to_string(ram_info.port_b_addr2_width) + "}");
703+
704+
//Each port has a different size, so print both the address and data widths. Mixed widths are not handled by the VPR memory class
705+
tmp_mode_hash.append(".port_a_data_width{" + std::to_string(ram_info.port_a_data_width) + "}");
706+
tmp_mode_hash.append(".port_b_data_width{" + std::to_string(ram_info.port_b_data_width) + "}");
707+
648708
LogicalModelId arch_model_id = arch_models.get_model_by_name(tmp_mode_hash);
649709
if (!arch_model_id.is_valid()) {
650710
//3a) Not found, use the default name (no specific address/data widths)
@@ -997,8 +1057,10 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
9971057
//We need to save the ram data and address widths, to identfy the RAM type (singel port, rom, simple dual port, true dual port)
9981058
t_node_parameter* port_a_data_width = NULL;
9991059
t_node_parameter* port_a_addr_width = NULL;
1060+
t_node_parameter* port_a_addr2_width = NULL;
10001061
t_node_parameter* port_b_data_width = NULL;
10011062
t_node_parameter* port_b_addr_width = NULL;
1063+
t_node_parameter* port_b_addr2_width = NULL;
10021064

10031065
for (int i = 0; i < vqm_node->number_of_params; i++){
10041066
//Each parameter specifies a configuration of the node in the circuit.
@@ -1020,6 +1082,11 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
10201082
port_a_addr_width = temp_param;
10211083
continue;
10221084
}
1085+
if (strcmp (temp_param->name, "port_a_address2_width") == 0){
1086+
VTR_ASSERT( temp_param->type == NODE_PARAMETER_INTEGER );
1087+
port_a_addr2_width = temp_param;
1088+
continue;
1089+
}
10231090
if (strcmp (temp_param->name, "port_b_data_width") == 0){
10241091
VTR_ASSERT( temp_param->type == NODE_PARAMETER_INTEGER );
10251092
port_b_data_width = temp_param;
@@ -1030,6 +1097,11 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
10301097
port_b_addr_width = temp_param;
10311098
continue;
10321099
}
1100+
if (strcmp (temp_param->name, "port_b_address2_width") == 0){
1101+
VTR_ASSERT( temp_param->type == NODE_PARAMETER_INTEGER );
1102+
port_b_addr2_width = temp_param;
1103+
continue;
1104+
}
10331105
if (strcmp (temp_param->name, "port_a_address_clock") == 0){ // This parameter doesn't exist for Stratix 10 - clock0 is always used for port address_a
10341106
VTR_ASSERT( temp_param->type == NODE_PARAMETER_STRING );
10351107
port_a_address_clock = temp_param;
@@ -1096,6 +1168,12 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
10961168
VTR_ASSERT(port_a_data_width);
10971169
ram_info.port_a_data_width = port_a_data_width->value.integer_value;
10981170

1171+
if (port_a_addr2_width) {
1172+
ram_info.port_a_addr2_width = port_a_addr2_width->value.integer_value;
1173+
}
1174+
if (port_b_addr2_width) {
1175+
ram_info.port_b_addr2_width = port_b_addr2_width->value.integer_value;
1176+
}
10991177
if (port_b_addr_width) {
11001178
ram_info.port_b_addr_width = port_b_addr_width->value.integer_value;
11011179
}

utils/vqm2blif/src/base/vqm2blif_util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ typedef pair <const char*, v_OptionBaseToken> tokpair;
9999
struct RamInfo {
100100
std::string mode = "";
101101
int port_a_addr_width = 0;
102+
int port_a_addr2_width = 0;
102103
int port_a_data_width = 0;
103104
t_node_port_association* port_a_input_clock = nullptr;
104105
t_node_port_association* port_a_input_ena = nullptr;
@@ -108,6 +109,7 @@ struct RamInfo {
108109
t_node_port_association* port_a_dataout_sclr = nullptr;
109110

110111
int port_b_addr_width = 0;
112+
int port_b_addr2_width = 0;
111113
int port_b_data_width = 0;
112114
t_node_port_association* port_b_input_clock = nullptr;
113115
t_node_port_association* port_b_input_ena = nullptr;

vpr/src/analytical_place/full_legalizer.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ FlatRecon::neighbor_clustering(ClusterLegalizer& cluster_legalizer,
492492
if (cluster_legalizer.is_mol_clustered(molecule_id))
493493
continue;
494494

495-
// Get 8-neighbouring tile locations of the current molecule in the same layer and same type.
495+
// Get 8-neighbouring tile locations of the current molecule in the same layer.
496496
std::vector<t_physical_tile_loc> neighbor_tile_locs;
497497
neighbor_tile_locs.reserve(8);
498498
auto [layers, width, height] = device_grid_.dim_sizes();
@@ -502,8 +502,6 @@ FlatRecon::neighbor_clustering(ClusterLegalizer& cluster_legalizer,
502502
int neighbor_x = loc.x + dx, neighbor_y = loc.y + dy;
503503
if (neighbor_x < 0 || neighbor_x >= (int)width || neighbor_y < 0 || neighbor_y >= (int)height)
504504
continue;
505-
if (device_grid_.get_physical_type(loc) != device_grid_.get_physical_type({neighbor_x, neighbor_y, loc.layer_num}))
506-
continue;
507505
neighbor_tile_locs.push_back({neighbor_x, neighbor_y, loc.layer_num});
508506
}
509507
}

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")

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct t_options {
133133
argparse::ArgValue<bool> ShowPlaceTiming;
134134
argparse::ArgValue<float> PlaceInnerNum;
135135
argparse::ArgValue<float> place_auto_init_t_scale;
136+
argparse::ArgValue<e_anneal_init_t_estimator> place_init_t_estimator;
136137
argparse::ArgValue<float> PlaceInitT;
137138
argparse::ArgValue<float> PlaceExitT;
138139
argparse::ArgValue<float> PlaceAlphaT;

vpr/src/base/setup_vpr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ static void setup_placer_opts(const t_options& Options, t_placer_opts* PlacerOpt
729729
PlacerOpts->placer_debug_net = Options.placer_debug_net;
730730

731731
PlacerOpts->place_auto_init_t_scale = Options.place_auto_init_t_scale.value();
732+
PlacerOpts->anneal_init_t_estimator = Options.place_init_t_estimator.value();
732733
}
733734

734735
static void setup_analysis_opts(const t_options& Options, t_analysis_opts& analysis_opts) {

vpr/src/base/vpr_types.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,15 @@ enum class e_place_delta_delay_algorithm {
967967
DIJKSTRA_EXPANSION,
968968
};
969969

970+
/**
971+
* @brief Enumeration of the different initial temperature estimators available
972+
* for the placer.
973+
*/
974+
enum class e_anneal_init_t_estimator {
975+
COST_VARIANCE, ///<Estimate the initial temperature using the variance in cost of a set of trial swaps.
976+
EQUILIBRIUM, ///<Estimate the initial temperature by predicting the equilibrium temperature for the initial placement.
977+
};
978+
970979
enum class e_move_type;
971980

972981
/**
@@ -1024,6 +1033,9 @@ enum class e_move_type;
10241033
* @param place_auto_init_t_scale
10251034
* When the annealer is using the automatic schedule, this option
10261035
* scales the initial temperature selected.
1036+
* @param anneal_init_t_estimator
1037+
* When the annealer is using the automatic schedule, this option
1038+
* selects which estimator is used to select an initial temperature.
10271039
*/
10281040
struct t_placer_opts {
10291041
t_place_algorithm place_algorithm;
@@ -1097,6 +1109,8 @@ struct t_placer_opts {
10971109
e_place_delta_delay_algorithm place_delta_delay_matrix_calculation_method;
10981110

10991111
float place_auto_init_t_scale;
1112+
1113+
e_anneal_init_t_estimator anneal_init_t_estimator;
11001114
};
11011115

11021116
/******************************************************************

0 commit comments

Comments
 (0)