Skip to content

Commit 6c111c8

Browse files
[AP] Optimized Primitive Vector Class
The primitive vector class was assumed to be quite sparse, and as such used an unordered map as its internal data structure. Found through experimentation that most of the time in the partial legalizer was being spent in the operations of the primitive vector class. Also, while improving the mass abstraction, I found a need to separate logical models from the dimensions of the primitive vector to allow multiple models to point to the same dimension in the primitive vector. This PR kills two birds with one stone by turning the unordered map into a VTR vector map and creating a new PrimitiveVectorDim which can allow the models to be separate from the dimensions. Future PRs will make use of this feature to improve the mass abstraction.
1 parent 45945b8 commit 6c111c8

16 files changed

+875
-411
lines changed

vpr/src/analytical_place/analytical_placement_flow.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ static PartialPlacement run_global_placer(const t_ap_opts& ap_opts,
151151
device_ctx.grid,
152152
device_ctx.logical_block_types,
153153
device_ctx.physical_tile_types,
154+
device_ctx.arch->models,
154155
pre_cluster_timing_manager,
155156
place_delay_model,
156157
ap_opts.ap_timing_tradeoff,

vpr/src/analytical_place/ap_mass_report.cpp

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "logic_types.h"
1919
#include "physical_types.h"
2020
#include "physical_types_util.h"
21+
#include "primitive_dim_manager.h"
2122
#include "primitive_vector.h"
2223
#include "vpr_context.h"
2324
#include "vpr_error.h"
@@ -245,30 +246,30 @@ void print_physical_tiles(std::ofstream& os,
245246
* The output file stream to print the primtive vector to.
246247
* @param primitive_vec
247248
* The primitive vector to print.
248-
* @param models
249-
* All models in the architecture (used to get the name of the model.
249+
* @param dim_manager
250+
* The manager class which handles all of the dims of this vector.
250251
* @param prefix
251252
* The prefix to print ahead of each entry in the primitive vector print.
252253
*/
253254
void print_primitive_vector(std::ofstream& os,
254255
const PrimitiveVector& primitive_vec,
255-
const LogicalModels& models,
256+
const PrimitiveDimManager& dim_manager,
256257
const std::string& prefix) {
257-
std::vector<int> contained_models = primitive_vec.get_non_zero_dims();
258+
std::vector<PrimitiveVectorDim> contained_dims = primitive_vec.get_non_zero_dims();
258259

259-
// Get the max name length of the contained models for pretty printing.
260+
// Get the max name length of the contained dim name for pretty printing.
260261
size_t max_model_name_len = 0;
261-
for (int model_id : contained_models) {
262-
std::string model_name = models.model_name((LogicalModelId)model_id);
262+
for (PrimitiveVectorDim dim : contained_dims) {
263+
std::string dim_name = dim_manager.get_dim_name(dim);
263264
max_model_name_len = std::max(max_model_name_len,
264-
model_name.size());
265+
dim_name.size());
265266
}
266267

267-
// Print the capacity of each model.
268-
for (int model_id : contained_models) {
269-
std::string model_name = models.model_name((LogicalModelId)model_id);
270-
os << prefix << std::setw(max_model_name_len) << model_name;
271-
os << ": " << primitive_vec.get_dim_val(model_id);
268+
// Print the capacity of each dim.
269+
for (PrimitiveVectorDim dim : contained_dims) {
270+
std::string dim_name = dim_manager.get_dim_name(dim);
271+
os << prefix << std::setw(max_model_name_len) << dim_name;
272+
os << ": " << primitive_vec.get_dim_val(dim);
272273
os << "\n";
273274
}
274275
}
@@ -279,7 +280,7 @@ void print_primitive_vector(std::ofstream& os,
279280
void print_logical_block_type_capacities(std::ofstream& os,
280281
const std::vector<t_logical_block_type>& logical_block_types,
281282
const std::vector<PrimitiveVector>& logical_block_type_capacities,
282-
const LogicalModels& models) {
283+
const PrimitiveDimManager& dim_manager) {
283284
os << "=================================================================\n";
284285
os << "Logical Block Type Capacities:\n";
285286
os << "=================================================================\n";
@@ -293,7 +294,7 @@ void print_logical_block_type_capacities(std::ofstream& os,
293294

294295
// Print the capacity of the logical block type.
295296
const PrimitiveVector& cap = logical_block_type_capacities[block_type.index];
296-
print_primitive_vector(os, cap, models, "\t");
297+
print_primitive_vector(os, cap, dim_manager, "\t");
297298
os << "\n";
298299
}
299300
}
@@ -304,7 +305,7 @@ void print_logical_block_type_capacities(std::ofstream& os,
304305
void print_physical_tile_type_capacities(std::ofstream& os,
305306
const std::vector<t_physical_tile_type>& physical_tile_types,
306307
const std::vector<PrimitiveVector>& physical_tile_type_capacities,
307-
const LogicalModels& models) {
308+
const PrimitiveDimManager& dim_manager) {
308309
os << "=================================================================\n";
309310
os << "Physical Tile Type Capacities:\n";
310311
os << "=================================================================\n";
@@ -318,7 +319,7 @@ void print_physical_tile_type_capacities(std::ofstream& os,
318319

319320
// Print the capacity of the tile type.
320321
const PrimitiveVector& cap = physical_tile_type_capacities[tile_type.index];
321-
print_primitive_vector(os, cap, models, "\t");
322+
print_primitive_vector(os, cap, dim_manager, "\t");
322323
os << "\n";
323324
}
324325
}
@@ -345,6 +346,7 @@ void print_netlist_mass_utilization(std::ofstream& os,
345346
const APNetlist& ap_netlist,
346347
const vtr::vector<APBlockId, PrimitiveVector>& block_mass,
347348
const std::vector<PrimitiveVector>& physical_tile_type_capacities,
349+
const PrimitiveDimManager& dim_manager,
348350
const DeviceGrid& device_grid,
349351
const LogicalModels& models) {
350352
os << "=================================================================\n";
@@ -371,44 +373,49 @@ void print_netlist_mass_utilization(std::ofstream& os,
371373
// Get the mass of all blocks in the netlist.
372374
PrimitiveVector total_netlist_mass = calc_total_netlist_mass(ap_netlist, block_mass);
373375

374-
PrimitiveVector netlist_per_model_counts;
376+
PrimitiveVector netlist_per_dim_counts;
375377
for (APBlockId ap_blk_id : ap_netlist.blocks()) {
376-
for (int dim : block_mass[ap_blk_id].get_non_zero_dims()) {
377-
netlist_per_model_counts.add_val_to_dim(1, dim);
378+
for (PrimitiveVectorDim dim : block_mass[ap_blk_id].get_non_zero_dims()) {
379+
netlist_per_dim_counts.add_val_to_dim(1, dim);
378380
}
379381
}
380382

381383
// Get the max string length of any model to make the printing prettier.
382-
size_t max_model_name_len = 0;
383-
for (LogicalModelId model_id : models.all_models()) {
384-
max_model_name_len = std::max(max_model_name_len, std::strlen(models.model_name(model_id).c_str()));
384+
size_t max_dim_name_len = 0;
385+
for (PrimitiveVectorDim dim : dim_manager.dims()) {
386+
std::string dim_name = dim_manager.get_dim_name(dim);
387+
max_dim_name_len = std::max(max_dim_name_len, dim_name.size());
385388
}
386389

387390
// Print a breakdown of the mass utilization of the netlist.
388-
os << std::setw(max_model_name_len) << "Model";
391+
os << std::setw(max_dim_name_len) << "Dim";
389392
os << ": Total Netlist Mass | Total Grid Mass | Mass Utilization\n";
390393
for (LogicalModelId model_id : models.all_models()) {
391-
float model_netlist_mass = total_netlist_mass.get_dim_val((size_t)model_id);
392-
float model_grid_capacity = total_grid_capacity.get_dim_val((size_t)model_id);
393-
os << std::setw(max_model_name_len) << models.model_name(model_id);
394-
os << ": " << std::setw(18) << model_netlist_mass;
395-
os << " | " << std::setw(15) << model_grid_capacity;
396-
os << " | " << std::setw(16) << model_netlist_mass / model_grid_capacity;
394+
PrimitiveVectorDim dim = dim_manager.get_model_dim(model_id);
395+
std::string dim_name = dim_manager.get_dim_name(dim);
396+
float dim_netlist_mass = total_netlist_mass.get_dim_val(dim);
397+
float dim_grid_capacity = total_grid_capacity.get_dim_val(dim);
398+
os << std::setw(max_dim_name_len) << dim_name;
399+
os << ": " << std::setw(18) << dim_netlist_mass;
400+
os << " | " << std::setw(15) << dim_grid_capacity;
401+
os << " | " << std::setw(16) << dim_netlist_mass / dim_grid_capacity;
397402
os << "\n";
398403
}
399404
os << "\n";
400405

401-
os << std::setw(max_model_name_len) << "Model";
406+
os << std::setw(max_dim_name_len) << "Dim";
402407
os << ": Total Netlist Mass | Number of Blocks | Average Mass per Block\n";
403408
for (LogicalModelId model_id : models.all_models()) {
404-
float model_netlist_mass = total_netlist_mass.get_dim_val((size_t)model_id);
405-
float num_blocks = netlist_per_model_counts.get_dim_val((size_t)model_id);
409+
PrimitiveVectorDim dim = dim_manager.get_model_dim(model_id);
410+
std::string dim_name = dim_manager.get_dim_name(dim);
411+
float dim_netlist_mass = total_netlist_mass.get_dim_val(dim);
412+
float num_blocks = netlist_per_dim_counts.get_dim_val(dim);
406413
float average_mass_per_block = 0.0f;
407414
if (num_blocks > 0.0f) {
408-
average_mass_per_block = model_netlist_mass / num_blocks;
415+
average_mass_per_block = dim_netlist_mass / num_blocks;
409416
}
410-
os << std::setw(max_model_name_len) << models.model_name(model_id);
411-
os << ": " << std::setw(18) << model_netlist_mass;
417+
os << std::setw(max_dim_name_len) << dim_name;
418+
os << ": " << std::setw(18) << dim_netlist_mass;
412419
os << " | " << std::setw(16) << num_blocks;
413420
os << " | " << std::setw(22) << average_mass_per_block;
414421
os << "\n";
@@ -442,9 +449,9 @@ void print_expected_device_utilization(std::ofstream& os,
442449
// instances to support the most utilized model.
443450
const PrimitiveVector block_type_cap = logical_block_type_capacities[block_type.index];
444451
unsigned num_blocks_of_this_type = 0;
445-
for (int model_id : block_type_cap.get_non_zero_dims()) {
446-
float netlist_model_mass = total_netlist_mass.get_dim_val(model_id);
447-
float model_mass_per_block = block_type_cap.get_dim_val(model_id);
452+
for (PrimitiveVectorDim dim : block_type_cap.get_non_zero_dims()) {
453+
float netlist_model_mass = total_netlist_mass.get_dim_val(dim);
454+
float model_mass_per_block = block_type_cap.get_dim_val(dim);
448455
unsigned num_blocks_needed_for_model = std::ceil(netlist_model_mass / model_mass_per_block);
449456
num_blocks_of_this_type = std::max(num_blocks_of_this_type, num_blocks_needed_for_model);
450457
}
@@ -498,6 +505,7 @@ void print_expected_device_utilization(std::ofstream& os,
498505
void generate_ap_mass_report(const std::vector<PrimitiveVector>& logical_block_type_capacities,
499506
const std::vector<PrimitiveVector>& physical_tile_type_capacities,
500507
const vtr::vector<APBlockId, PrimitiveVector>& block_mass,
508+
const PrimitiveDimManager& dim_manager,
501509
const APNetlist& ap_netlist) {
502510

503511
vtr::ScopedStartFinishTimer timer("Generating AP Mass Report");
@@ -524,17 +532,17 @@ void generate_ap_mass_report(const std::vector<PrimitiveVector>& logical_block_t
524532
// Print information on the physical tiles.
525533
print_physical_tiles(os, physical_tile_types);
526534

527-
// TODO: Print a lookup between the model names and IDs
535+
// TODO: Print a lookup between the model names and IDs and Primitive Dim
528536

529537
// Print the computed capacities of each logical block type.
530-
print_logical_block_type_capacities(os, logical_block_types, logical_block_type_capacities, models);
538+
print_logical_block_type_capacities(os, logical_block_types, logical_block_type_capacities, dim_manager);
531539

532540
// Print the computed capacities of each physical tile type.
533-
print_physical_tile_type_capacities(os, physical_tile_types, physical_tile_type_capacities, models);
541+
print_physical_tile_type_capacities(os, physical_tile_types, physical_tile_type_capacities, dim_manager);
534542

535543
// Print information on how much mass is utilized by the netlist relative
536544
// to the device.
537-
print_netlist_mass_utilization(os, ap_netlist, block_mass, physical_tile_type_capacities, device_grid, models);
545+
print_netlist_mass_utilization(os, ap_netlist, block_mass, physical_tile_type_capacities, dim_manager, device_grid, models);
538546

539547
// Print the expected device utilization, given the mass of the netlist
540548
// and the capacity of the device grid.

vpr/src/analytical_place/ap_mass_report.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
*/
1010

1111
#include <vector>
12-
#include <ap_netlist_fwd.h>
12+
#include "ap_netlist_fwd.h"
13+
#include "primitive_vector_fwd.h"
1314
#include "vtr_vector.h"
1415

1516
// Forward declarations
16-
class PrimitiveVector;
17+
class PrimitiveDimManager;
1718

1819
/**
1920
* @brief Generate a mass report for the given AP netlist with the given block
@@ -30,4 +31,5 @@ class PrimitiveVector;
3031
void generate_ap_mass_report(const std::vector<PrimitiveVector>& logical_block_type_capacities,
3132
const std::vector<PrimitiveVector>& physical_tile_type_capacities,
3233
const vtr::vector<APBlockId, PrimitiveVector>& block_mass,
34+
const PrimitiveDimManager& dim_manager,
3335
const APNetlist& ap_netlist);

vpr/src/analytical_place/flat_placement_density_manager.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
#include "atom_netlist.h"
1313
#include "flat_placement_bins.h"
1414
#include "flat_placement_mass_calculator.h"
15+
#include "logic_types.h"
1516
#include "partial_placement.h"
1617
#include "physical_types.h"
1718
#include "prepack.h"
19+
#include "primitive_dim_manager.h"
20+
#include "primitive_vector.h"
1821
#include "vtr_assert.h"
1922
#include "vtr_geometry.h"
2023
#include "vtr_vector.h"
@@ -48,10 +51,11 @@ FlatPlacementDensityManager::FlatPlacementDensityManager(const APNetlist& ap_net
4851
const DeviceGrid& device_grid,
4952
const std::vector<t_logical_block_type>& logical_block_types,
5053
const std::vector<t_physical_tile_type>& physical_tile_types,
54+
const LogicalModels& models,
5155
int log_verbosity)
5256
: ap_netlist_(ap_netlist)
5357
, bins_(ap_netlist)
54-
, mass_calculator_(ap_netlist, prepacker, atom_netlist, logical_block_types, physical_tile_types, log_verbosity)
58+
, mass_calculator_(ap_netlist, prepacker, atom_netlist, logical_block_types, physical_tile_types, models, log_verbosity)
5559
, log_verbosity_(log_verbosity) {
5660
// Initialize the bin spatial lookup object.
5761
size_t num_layers, width, height;
@@ -96,12 +100,24 @@ FlatPlacementDensityManager::FlatPlacementDensityManager(const APNetlist& ap_net
96100
}
97101
}
98102

103+
// Get the used primitive dims. This is used to ignore the unused dims during
104+
// partial legalization.
105+
const PrimitiveDimManager& dim_manager = mass_calculator_.get_dim_manager();
106+
for (AtomBlockId blk_id : atom_netlist.blocks()) {
107+
LogicalModelId model_id = atom_netlist.block_model(blk_id);
108+
PrimitiveVectorDim dim = dim_manager.get_model_dim(model_id);
109+
used_dims_mask_.set_dim_val(dim, 1);
110+
}
111+
99112
// Initialize the bin capacities to the mass capacity of the physical tile
100113
// this bin represents.
101114
bin_capacity_.resize(bins_.bins().size());
102115
for (FlatPlacementBinId bin_id : bins_.bins()) {
103116
size_t physical_tile_type_index = bin_phy_tile_type_idx[bin_id];
104117
bin_capacity_[bin_id] = mass_calculator_.get_physical_tile_type_capacity(physical_tile_type_index);
118+
// Only allocate capacity to dims which are actually used. This prevents
119+
// the capacity vectors from getting too large, saving run time.
120+
bin_capacity_[bin_id].project(used_dims_mask_);
105121
}
106122

107123
// Initialize the bin utilizations to be zero (there is nothing in the bin

vpr/src/analytical_place/flat_placement_density_manager.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
#include <vector>
1515
#include "flat_placement_bins.h"
1616
#include "flat_placement_mass_calculator.h"
17+
#include "primitive_vector.h"
1718
#include "vtr_assert.h"
1819
#include "vtr_ndmatrix.h"
1920
#include "vtr_vector.h"
2021

2122
class APNetlist;
2223
class AtomNetlist;
2324
class DeviceGrid;
25+
class LogicalModels;
2426
class Prepacker;
2527
struct PartialPlacement;
2628
struct t_logical_block_type;
@@ -66,6 +68,7 @@ class FlatPlacementDensityManager {
6668
* @param device_grid
6769
* @param logical_block_types
6870
* @param physical_tile_types
71+
* @param models
6972
* @param log_verbosity
7073
*/
7174
FlatPlacementDensityManager(const APNetlist& ap_netlist,
@@ -74,6 +77,7 @@ class FlatPlacementDensityManager {
7477
const DeviceGrid& device_grid,
7578
const std::vector<t_logical_block_type>& logical_block_types,
7679
const std::vector<t_physical_tile_type>& physical_tile_types,
80+
const LogicalModels& models,
7781
int log_verbosity);
7882

7983
/**
@@ -217,6 +221,16 @@ class FlatPlacementDensityManager {
217221
const vtr::Rect<double>& bin_region,
218222
const PartialPlacement& p_placement) const;
219223

224+
/**
225+
* @brief Return a primitive vector where any dim which is used in the netlist
226+
* is set to 1, and any unused dim is set to 0.
227+
*
228+
* This information can be used to ignore dims which are unused.
229+
*/
230+
const PrimitiveVector& get_used_dims_mask() const {
231+
return used_dims_mask_;
232+
}
233+
220234
/**
221235
* @brief Resets all bins by emptying them.
222236
*/
@@ -273,6 +287,11 @@ class FlatPlacementDensityManager {
273287
/// @brief The set of overfilled bins.
274288
std::unordered_set<FlatPlacementBinId> overfilled_bins_;
275289

290+
/// @brief A vector mask representing the used primitive vector dimensions
291+
/// in the netlist. If a dimension is used, its value will be set to
292+
/// 1 in this vector, and 0 otherwise.
293+
PrimitiveVector used_dims_mask_;
294+
276295
/// @brief The verbosity of log messages in this class.
277296
const int log_verbosity_;
278297
};

0 commit comments

Comments
 (0)