Skip to content

Commit c4c8f95

Browse files
[Pack] Cleaned Up try_pack API
The try_pack API required an approximation for the inter-cluster delay; however, this approximation was always being made the same way and did not need to be brought in externally. Inlined this into the packer itself to make the interface easier to work with.
1 parent 1279554 commit c4c8f95

File tree

3 files changed

+177
-161
lines changed

3 files changed

+177
-161
lines changed

vpr/src/base/vpr_api.cpp

Lines changed: 3 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,6 @@ static void free_complex_block_types();
109109
static void free_device(const t_det_routing_arch& routing_arch);
110110
static void free_circuit();
111111

112-
static void get_intercluster_switch_fanin_estimates(const t_vpr_setup& vpr_setup,
113-
const t_arch& arch,
114-
const int wire_segment_length,
115-
int* opin_switch_fanin,
116-
int* wire_switch_fanin,
117-
int* ipin_switch_fanin);
118112
/* Local subroutines end */
119113

120114
///@brief Display general VPR information
@@ -641,53 +635,6 @@ bool vpr_pack_flow(t_vpr_setup& vpr_setup, const t_arch& arch) {
641635
bool vpr_pack(t_vpr_setup& vpr_setup, const t_arch& arch) {
642636
vtr::ScopedStartFinishTimer timer("Packing");
643637

644-
/* If needed, estimate inter-cluster delay. Assume the average routing hop goes out of
645-
* a block through an opin switch to a length-4 wire, then through a wire switch to another
646-
* length-4 wire, then through a wire-to-ipin-switch into another block. */
647-
int wire_segment_length = 4;
648-
649-
float inter_cluster_delay = UNDEFINED;
650-
if (vpr_setup.PackerOpts.timing_driven
651-
&& vpr_setup.PackerOpts.auto_compute_inter_cluster_net_delay) {
652-
/* We want to determine a reasonable fan-in to the opin, wire, and ipin switches, based
653-
* on which the intercluster delays can be estimated. The fan-in of a switch influences its
654-
* delay.
655-
*
656-
* The fan-in of the switch depends on the architecture (unidirectional/bidirectional), as
657-
* well as Fc_in/out and Fs */
658-
int opin_switch_fanin, wire_switch_fanin, ipin_switch_fanin;
659-
get_intercluster_switch_fanin_estimates(vpr_setup, arch, wire_segment_length, &opin_switch_fanin,
660-
&wire_switch_fanin, &ipin_switch_fanin);
661-
662-
float Tdel_opin_switch, R_opin_switch, Cout_opin_switch;
663-
float opin_switch_del = get_arch_switch_info(arch.Segments[0].arch_opin_switch, opin_switch_fanin,
664-
Tdel_opin_switch, R_opin_switch, Cout_opin_switch);
665-
666-
float Tdel_wire_switch, R_wire_switch, Cout_wire_switch;
667-
float wire_switch_del = get_arch_switch_info(arch.Segments[0].arch_wire_switch, wire_switch_fanin,
668-
Tdel_wire_switch, R_wire_switch, Cout_wire_switch);
669-
670-
float Tdel_wtoi_switch, R_wtoi_switch, Cout_wtoi_switch;
671-
float wtoi_switch_del = get_arch_switch_info(vpr_setup.RoutingArch.wire_to_arch_ipin_switch, ipin_switch_fanin,
672-
Tdel_wtoi_switch, R_wtoi_switch, Cout_wtoi_switch);
673-
674-
float Rmetal = arch.Segments[0].Rmetal;
675-
float Cmetal = arch.Segments[0].Cmetal;
676-
677-
/* The delay of a wire with its driving switch is the switch delay plus the
678-
* product of the equivalent resistance and capacitance experienced by the wire. */
679-
680-
float first_wire_seg_delay = opin_switch_del
681-
+ (R_opin_switch + Rmetal * (float)wire_segment_length / 2)
682-
* (Cout_opin_switch + Cmetal * (float)wire_segment_length);
683-
float second_wire_seg_delay = wire_switch_del
684-
+ (R_wire_switch + Rmetal * (float)wire_segment_length / 2)
685-
* (Cout_wire_switch + Cmetal * (float)wire_segment_length);
686-
inter_cluster_delay = 4
687-
* (first_wire_seg_delay + second_wire_seg_delay
688-
+ wtoi_switch_del); /* multiply by 4 to get a more conservative estimate */
689-
}
690-
691638
// Read in the flat placement if a flat placement file is provided and it
692639
// has not been loaded already.
693640
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty() &&
@@ -698,8 +645,9 @@ bool vpr_pack(t_vpr_setup& vpr_setup, const t_arch& arch) {
698645
}
699646

700647
return try_pack(&vpr_setup.PackerOpts, &vpr_setup.AnalysisOpts,
701-
&arch, vpr_setup.user_models,
702-
vpr_setup.library_models, inter_cluster_delay,
648+
arch, vpr_setup.RoutingArch,
649+
vpr_setup.user_models,
650+
vpr_setup.library_models,
703651
vpr_setup.PackerRRGraph, g_vpr_ctx.atom().flat_placement_info);
704652
}
705653

@@ -1212,100 +1160,6 @@ void vpr_close_graphics(const t_vpr_setup& /*vpr_setup*/) {
12121160
free_draw_structs();
12131161
}
12141162

1215-
/**
1216-
* Since the parameters of a switch may change as a function of its fanin,
1217-
* to get an estimation of inter-cluster delays we need a reasonable estimation
1218-
* of the fan-ins of switches that connect clusters together. These switches are
1219-
* 1) opin to wire switch
1220-
* 2) wire to wire switch
1221-
* 3) wire to ipin switch
1222-
* We can estimate the fan-in of these switches based on the Fc_in/Fc_out of
1223-
* a logic block, and the switch block Fs value
1224-
*/
1225-
static void get_intercluster_switch_fanin_estimates(const t_vpr_setup& vpr_setup,
1226-
const t_arch& arch,
1227-
const int wire_segment_length,
1228-
int* opin_switch_fanin,
1229-
int* wire_switch_fanin,
1230-
int* ipin_switch_fanin) {
1231-
e_directionality directionality;
1232-
int Fs;
1233-
float Fc_in, Fc_out;
1234-
int W = 100; //W is unknown pre-packing, so *if* we need W here, we will assume a value of 100
1235-
1236-
directionality = vpr_setup.RoutingArch.directionality;
1237-
Fs = vpr_setup.RoutingArch.Fs;
1238-
Fc_in = 0, Fc_out = 0;
1239-
1240-
//Build a dummy 10x10 device to determine the 'best' block type to use
1241-
auto grid = create_device_grid(vpr_setup.device_layout, arch.grid_layouts, 10, 10);
1242-
1243-
auto type = find_most_common_tile_type(grid);
1244-
/* get Fc_in/out for most common block (e.g. logic blocks) */
1245-
VTR_ASSERT(!type->fc_specs.empty());
1246-
1247-
//Estimate the maximum Fc_in/Fc_out
1248-
1249-
for (const t_fc_specification& fc_spec : type->fc_specs) {
1250-
float Fc = fc_spec.fc_value;
1251-
1252-
if (fc_spec.fc_value_type == e_fc_value_type::ABSOLUTE) {
1253-
//Convert to estimated fractional
1254-
Fc /= W;
1255-
}
1256-
VTR_ASSERT_MSG(Fc >= 0 && Fc <= 1., "Fc should be fractional");
1257-
1258-
for (int ipin : fc_spec.pins) {
1259-
e_pin_type pin_type = get_pin_type_from_pin_physical_num(type, ipin);
1260-
1261-
if (pin_type == DRIVER) {
1262-
Fc_out = std::max(Fc, Fc_out);
1263-
} else {
1264-
VTR_ASSERT(pin_type == RECEIVER);
1265-
Fc_in = std::max(Fc, Fc_in);
1266-
}
1267-
}
1268-
}
1269-
1270-
/* Estimates of switch fan-in are done as follows:
1271-
* 1) opin to wire switch:
1272-
* 2 CLBs connect to a channel, each with #opins/4 pins. Each pin has Fc_out*W
1273-
* switches, and then we assume the switches are distributed evenly over the W wires.
1274-
* In the unidirectional case, all these switches are then crammed down to W/wire_segment_length wires.
1275-
*
1276-
* Unidirectional: 2 * #opins_per_side * Fc_out * wire_segment_length
1277-
* Bidirectional: 2 * #opins_per_side * Fc_out
1278-
*
1279-
* 2) wire to wire switch
1280-
* A wire segment in a switchblock connects to Fs other wires. Assuming these connections are evenly
1281-
* distributed, each target wire receives Fs connections as well. In the unidirectional case,
1282-
* source wires can only connect to W/wire_segment_length wires.
1283-
*
1284-
* Unidirectional: Fs * wire_segment_length
1285-
* Bidirectional: Fs
1286-
*
1287-
* 3) wire to ipin switch
1288-
* An input pin of a CLB simply receives Fc_in connections.
1289-
*
1290-
* Unidirectional: Fc_in
1291-
* Bidirectional: Fc_in
1292-
*/
1293-
1294-
/* Fan-in to opin/ipin/wire switches depends on whether the architecture is unidirectional/bidirectional */
1295-
(*opin_switch_fanin) = 2 * type->num_drivers / 4 * Fc_out;
1296-
(*wire_switch_fanin) = Fs;
1297-
(*ipin_switch_fanin) = Fc_in;
1298-
if (directionality == UNI_DIRECTIONAL) {
1299-
/* adjustments to opin-to-wire and wire-to-wire switch fan-ins */
1300-
(*opin_switch_fanin) *= wire_segment_length;
1301-
(*wire_switch_fanin) *= wire_segment_length;
1302-
} else if (directionality == BI_DIRECTIONAL) {
1303-
/* no adjustments need to be made here */
1304-
} else {
1305-
VPR_FATAL_ERROR(VPR_ERROR_PACK, "Unrecognized directionality: %d\n", (int)directionality);
1306-
}
1307-
}
1308-
13091163
///@brief Free architecture data structures
13101164
void free_device(const t_det_routing_arch& /*routing_arch*/) {
13111165
auto& device_ctx = g_vpr_ctx.mutable_device();

0 commit comments

Comments
 (0)