Skip to content

Commit a4f8983

Browse files
committed
Fix handling of combined pin/segment <fc_overrides>
Previously these were not interpreted correctly leading to incorrect behaviour (and seg faults) on some complex switch block architectures. Also update rr graph Fc calculation to ensure Fc_in is only calculated for input pins, and Fc_out only for output pins.
1 parent 9691a27 commit a4f8983

File tree

5 files changed

+82
-35
lines changed

5 files changed

+82
-35
lines changed

libarchfpga/src/echo_arch.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ void EchoArch(const char *EchoFile, const t_type_descriptor* Types,
7878
fprintf(Echo, "\twidth: %d\n", Types[i].width);
7979
fprintf(Echo, "\theight: %d\n", Types[i].height);
8080
for (const t_fc_specification& fc_spec : Types[i].fc_specs) {
81-
fprintf(Echo, "fc_type: ");
82-
if (fc_spec.fc_type == e_fc_type::ABSOLUTE) {
81+
fprintf(Echo, "fc_value_type: ");
82+
if (fc_spec.fc_value_type == e_fc_value_type::ABSOLUTE) {
8383
fprintf(Echo, "ABSOLUTE");
84-
} else if (fc_spec.fc_type == e_fc_type::FRACTIONAL) {
84+
} else if (fc_spec.fc_value_type == e_fc_value_type::FRACTIONAL) {
8585
fprintf(Echo, "FRACTIONAL");
8686
} else {
8787
VTR_ASSERT(false);

libarchfpga/src/physical_types.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,16 +270,23 @@ struct s_port_power {
270270

271271
//The type of Fc specification
272272
enum class e_fc_type {
273+
IN, //The fc specification for an input pin
274+
OUT //The fc specification for an output pin
275+
};
276+
277+
//The value type of the Fc specification
278+
enum class e_fc_value_type {
273279
FRACTIONAL, //Fractional Fc specification (i.e. fraction of routing channel tracks)
274-
ABSOLUTE //Absolute Fc specification (i.e. absolute number of tracks)
280+
ABSOLUTE //Absolute Fc specification (i.e. absolute number of tracks)
275281
};
276282

277283
//Describes the Fc specification for a set of pins and a segment
278284
struct t_fc_specification {
279-
e_fc_type fc_type; //How to interpret the Fc value
280-
float fc_value; //The Fc value
281-
int seg_index; //The target segment index
282-
std::vector<int> pins; //The block pins collectively effected by this Fc
285+
e_fc_type fc_type; //What type of Fc
286+
e_fc_value_type fc_value_type; //How to interpret the Fc value
287+
float fc_value; //The Fc value
288+
int seg_index; //The target segment index
289+
std::vector<int> pins; //The block pins collectively effected by this Fc
283290
};
284291

285292
/* Describes the type for a physical logic block

libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ using namespace pugiutil;
6666
struct t_fc_override {
6767
std::string port_name;
6868
std::string seg_name;
69-
e_fc_type fc_type;
69+
e_fc_value_type fc_value_type;
7070
float fc_value;
7171
};
7272

@@ -103,7 +103,7 @@ static void ProcessMode(pugi::xml_node Parent, t_mode * mode, const t_arch& arch
103103
const pugiutil::loc_data& loc_data);
104104
static void Process_Fc(pugi::xml_node Node, t_type_descriptor * Type, t_segment_inf *segments, int num_segments, const pugiutil::loc_data& loc_data);
105105
static t_fc_override Process_Fc_override(pugi::xml_node node, const pugiutil::loc_data& loc_data);
106-
static e_fc_type string_to_fc_type(const std::string& str, pugi::xml_node node, const pugiutil::loc_data& loc_data);
106+
static e_fc_value_type string_to_fc_value_type(const std::string& str, pugi::xml_node node, const pugiutil::loc_data& loc_data);
107107
static void ProcessComplexBlockProps(pugi::xml_node Node, t_type_descriptor * Type, const pugiutil::loc_data& loc_data);
108108
static void ProcessSizingTimingIpinCblock(pugi::xml_node Node,
109109
struct s_arch *arch, const bool timing_enabled, const pugiutil::loc_data& loc_data);
@@ -1626,21 +1626,21 @@ static void ProcessMode(pugi::xml_node Parent, t_mode * mode, const t_arch& arch
16261626
/* Takes in the node ptr for the 'fc' elements and initializes
16271627
* the appropriate fields of type. */
16281628
static void Process_Fc(pugi::xml_node Node, t_type_descriptor * Type, t_segment_inf *segments, int num_segments, const pugiutil::loc_data& loc_data) {
1629-
e_fc_type default_fc_in_type = e_fc_type::FRACTIONAL;
1630-
e_fc_type default_fc_out_type = e_fc_type::FRACTIONAL;
1629+
e_fc_value_type default_fc_in_value_type = e_fc_value_type::FRACTIONAL;
1630+
e_fc_value_type default_fc_out_value_type = e_fc_value_type::FRACTIONAL;
16311631
float default_fc_in_value = std::numeric_limits<float>::quiet_NaN();
16321632
float default_fc_out_value = std::numeric_limits<float>::quiet_NaN();
16331633

16341634
/* Load the default fc_in */
16351635
auto default_fc_in_attrib = get_attribute(Node, "default_in_type", loc_data);
1636-
default_fc_in_type = string_to_fc_type(default_fc_in_attrib.value(), Node, loc_data);
1636+
default_fc_in_value_type = string_to_fc_value_type(default_fc_in_attrib.value(), Node, loc_data);
16371637

16381638
auto default_in_val_attrib = get_attribute(Node, "default_in_val", loc_data);
16391639
default_fc_in_value = vtr::atof(default_in_val_attrib.value());
16401640

16411641
/* Load the default fc_out */
16421642
auto default_fc_out_attrib = get_attribute(Node, "default_out_type", loc_data);
1643-
default_fc_out_type = string_to_fc_type(default_fc_out_attrib.value(), Node, loc_data);
1643+
default_fc_out_value_type = string_to_fc_value_type(default_fc_out_attrib.value(), Node, loc_data);
16441644

16451645
auto default_out_val_attrib = get_attribute(Node, "default_out_val", loc_data);
16461646
default_fc_out_value = vtr::atof(default_out_val_attrib.value());
@@ -1669,25 +1669,60 @@ static void Process_Fc(pugi::xml_node Node, t_type_descriptor * Type, t_segment_
16691669
const t_port* port = &pb_type->ports[iport];
16701670

16711671
t_fc_specification fc_spec;
1672+
16721673
fc_spec.seg_index = iseg;
16731674

1674-
//Apply the defaults
1675+
//Apply type and defaults
16751676
if (port->type == IN_PORT) {
1676-
fc_spec.fc_type = default_fc_in_type;
1677+
fc_spec.fc_type = e_fc_type::IN;
1678+
fc_spec.fc_value_type = default_fc_in_value_type;
16771679
fc_spec.fc_value = default_fc_in_value;
16781680
} else {
16791681
VTR_ASSERT(port->type == OUT_PORT);
1680-
fc_spec.fc_type = default_fc_out_type;
1682+
fc_spec.fc_type = e_fc_type::OUT;
1683+
fc_spec.fc_value_type = default_fc_out_value_type;
16811684
fc_spec.fc_value = default_fc_out_value;
16821685
}
16831686

16841687
//Apply any matching overrides
1688+
bool default_overriden = false;
16851689
for(const auto& fc_override : fc_overrides) {
1686-
if (fc_override.port_name == port->name || fc_override.seg_name == segments[iseg].name) {
1690+
bool apply_override = false;
1691+
if (!fc_override.port_name.empty() && !fc_override.seg_name.empty()) {
1692+
//Both port and seg names are specified require exact match on both
1693+
if (fc_override.port_name == port->name && fc_override.seg_name == segments[iseg].name) {
1694+
apply_override = true;
1695+
}
1696+
1697+
} else if (!fc_override.port_name.empty()) {
1698+
VTR_ASSERT(fc_override.seg_name.empty());
1699+
//Only the port name specified, require it to match
1700+
if (fc_override.port_name == port->name) {
1701+
apply_override = true;
1702+
}
1703+
} else {
1704+
VTR_ASSERT(!fc_override.seg_name.empty());
1705+
VTR_ASSERT(fc_override.port_name.empty());
1706+
//Only the seg name specified, require it to match
1707+
if (fc_override.seg_name == segments[iseg].name) {
1708+
apply_override = true;
1709+
}
1710+
}
1711+
1712+
if (apply_override) {
16871713
//Exact match, or partial match to either port or seg name
1688-
// Note that we continue searching, this ensures that the last matching override is applied last
1689-
fc_spec.fc_type = fc_override.fc_type;
1714+
// Note that we continue searching, this ensures that the last matching override (in file order)
1715+
// is applied last
1716+
1717+
if (default_overriden) {
1718+
//Warn if multiple overrides match
1719+
vtr::printf_warning(loc_data.filename_c_str(), loc_data.line(Node), "Multiple matching Fc overrides found; the last will be applied\n");
1720+
}
1721+
1722+
fc_spec.fc_value_type = fc_override.fc_value_type;
16901723
fc_spec.fc_value = fc_override.fc_value;
1724+
1725+
default_overriden = true;
16911726
}
16921727
}
16931728

@@ -1727,7 +1762,7 @@ static t_fc_override Process_Fc_override(pugi::xml_node node, const pugiutil::lo
17271762
fc_override.seg_name = attrib.value();
17281763
seen_port_or_seg |= true;
17291764
} else if (attrib.name() == std::string("fc_type")) {
1730-
fc_override.fc_type = string_to_fc_type(attrib.value(), node, loc_data);
1765+
fc_override.fc_value_type = string_to_fc_value_type(attrib.value(), node, loc_data);
17311766
seen_fc_type = true;
17321767
} else if (attrib.name() == std::string("fc_val")) {
17331768
fc_override.fc_value = vtr::atof(attrib.value());
@@ -1756,20 +1791,20 @@ static t_fc_override Process_Fc_override(pugi::xml_node node, const pugiutil::lo
17561791
return fc_override;
17571792
}
17581793

1759-
static e_fc_type string_to_fc_type(const std::string& str, pugi::xml_node node, const pugiutil::loc_data& loc_data) {
1760-
e_fc_type fc_type = e_fc_type::FRACTIONAL;
1794+
static e_fc_value_type string_to_fc_value_type(const std::string& str, pugi::xml_node node, const pugiutil::loc_data& loc_data) {
1795+
e_fc_value_type fc_value_type = e_fc_value_type::FRACTIONAL;
17611796

17621797
if (str == "frac") {
1763-
fc_type = e_fc_type::FRACTIONAL;
1798+
fc_value_type = e_fc_value_type::FRACTIONAL;
17641799
} else if (str == "abs") {
1765-
fc_type = e_fc_type::ABSOLUTE;
1800+
fc_value_type = e_fc_value_type::ABSOLUTE;
17661801
} else {
17671802
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node),
17681803
"Invalid fc_type '%s'. Must be 'abs' or 'frac'.\n",
17691804
str.c_str());
17701805
}
17711806

1772-
return fc_type;
1807+
return fc_value_type;
17731808
}
17741809

17751810
/* Thie processes attributes of the 'type' tag */

vpr/SRC/base/vpr_api.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ static void get_intercluster_switch_fanin_estimates(const t_vpr_setup& vpr_setup
526526
for (const t_fc_specification& fc_spec : FILL_TYPE->fc_specs) {
527527
float Fc = fc_spec.fc_value;
528528

529-
if (fc_spec.fc_type == e_fc_type::ABSOLUTE) {
529+
if (fc_spec.fc_value_type == e_fc_value_type::ABSOLUTE) {
530530
//Convert to estimated fractional
531531
Fc /= W;
532532
}

vpr/SRC/route/rr_graph.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ static t_seg_details *alloc_and_load_global_route_seg_details(
213213

214214
static int ***alloc_and_load_actual_fc(const int L_num_types, const t_type_ptr types, const int max_pins,
215215
const int num_seg_types, const int *sets_per_seg_type,
216-
const int max_chan_width,
216+
const int max_chan_width, const e_fc_type fc_type,
217217
const enum e_directionality directionality,
218218
bool *Fc_clipped, const bool ignore_Fc_0);
219219

@@ -340,27 +340,29 @@ void build_rr_graph(
340340
} else {
341341
bool Fc_clipped = false;
342342
Fc_in = alloc_and_load_actual_fc(L_num_types, types, max_pins, num_seg_types, sets_per_seg_type, max_chan_width,
343-
directionality, &Fc_clipped, ignore_Fc_0);
343+
e_fc_type::IN, directionality, &Fc_clipped, ignore_Fc_0);
344344
if (Fc_clipped) {
345345
*Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
346346
}
347347
Fc_clipped = false;
348348
Fc_out = alloc_and_load_actual_fc(L_num_types, types, max_pins, num_seg_types, sets_per_seg_type, max_chan_width,
349-
directionality, &Fc_clipped, ignore_Fc_0);
349+
e_fc_type::OUT, directionality, &Fc_clipped, ignore_Fc_0);
350350
if (Fc_clipped) {
351351
*Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
352352
}
353353

354-
#ifdef VERBOSE
355354
for (int i = 1; i < L_num_types; ++i) { /* Skip "<EMPTY>" */
356355
for (int j = 0; j < g_block_types[i].num_pins; ++j) {
357356
for (int k = 0; k < num_seg_types; k++){
357+
#ifdef VERBOSE
358358
vtr::printf_info("Fc Actual Values: type = %s, pin = %d, seg = %d (%s), Fc_out = %d, Fc_in = %d.\n",
359359
g_block_types[i].name, j, k, segment_inf[k].name, Fc_out[i][j][k], Fc_in[i][j][k]);
360+
#endif /* VERBOSE */
361+
VTR_ASSERT_MSG(Fc_out[i][j][k] == 0 || Fc_in[i][j][k] == 0,
362+
"Pins must be inputs or outputs (i.e. can not have both non-zero Fc_out and Fc_in)");
360363
}
361364
}
362365
}
363-
#endif /* VERBOSE */
364366
}
365367

366368
bool **perturb_ipins = alloc_and_load_perturb_ipins(L_num_types, num_seg_types,
@@ -890,7 +892,7 @@ static t_seg_details *alloc_and_load_global_route_seg_details(
890892
/* Calculates the number of track connections from each block pin to each segment type */
891893
static int ***alloc_and_load_actual_fc(const int L_num_types, const t_type_ptr types, const int max_pins,
892894
const int num_seg_types, const int *sets_per_seg_type,
893-
const int max_chan_width,
895+
const int max_chan_width, const e_fc_type fc_type,
894896
const enum e_directionality directionality,
895897
bool *Fc_clipped, const bool ignore_Fc_0) {
896898

@@ -920,6 +922,8 @@ static int ***alloc_and_load_actual_fc(const int L_num_types, const t_type_ptr t
920922
for (int itype = 1; itype < L_num_types; ++itype) { //Skip <EMPTY>
921923
for (const t_fc_specification fc_spec : types[itype].fc_specs) {
922924

925+
if (fc_type != fc_spec.fc_type) continue;
926+
923927
int iseg = fc_spec.seg_index;
924928

925929
if(fc_spec.fc_value == 0 && ignore_Fc_0 == false) {
@@ -932,11 +936,11 @@ static int ***alloc_and_load_actual_fc(const int L_num_types, const t_type_ptr t
932936

933937
//Calculate how many connections there should be accross all the pins in this fc_spec
934938
float flt_total_connections;
935-
if (fc_spec.fc_type == e_fc_type::FRACTIONAL) {
939+
if (fc_spec.fc_value_type == e_fc_value_type::FRACTIONAL) {
936940
float conns_per_pin = fac * sets_per_seg_type[iseg] * fc_spec.fc_value;
937941
flt_total_connections = conns_per_pin * fc_spec.pins.size();
938942
} else {
939-
VTR_ASSERT(fc_spec.fc_type == e_fc_type::ABSOLUTE);
943+
VTR_ASSERT(fc_spec.fc_value_type == e_fc_value_type::ABSOLUTE);
940944
flt_total_connections = fc_spec.fc_value * fc_spec.pins.size();
941945
}
942946

@@ -2188,6 +2192,7 @@ static vtr::t_ivec ****alloc_and_load_track_to_pin_lookup(
21882192

21892193
for (int conn = 0; conn < num_tracks; ++conn) {
21902194
int track = pin_to_track_map[pin][width][height][side][conn];
2195+
VTR_ASSERT(track < max_chan_width);
21912196
track_to_pin_lookup[track][width][height][side].nelem++;
21922197
}
21932198
}

0 commit comments

Comments
 (0)