Skip to content

Commit b678131

Browse files
authored
Merge pull request #10802 from eder-matheus/grt_cugr_vias
grt/cugr: improve via demand calculation
2 parents c912b88 + 6c3bd39 commit b678131

61 files changed

Lines changed: 14560 additions & 10154 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/grt/src/cugr/src/Design.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#include "Design.h"
22

3+
#include <cmath>
34
#include <cstdint>
45
#include <iostream>
56
#include <set>
7+
#include <tuple>
68
#include <utility>
79
#include <vector>
810

911
#include "CUGR.h"
1012
#include "GeoTypes.h"
13+
#include "Layers.h"
1114
#include "Netlist.h"
1215
#include "db_sta/dbSta.hh"
1316
#include "odb/PtrSetMap.h"
@@ -57,6 +60,8 @@ void Design::read()
5760

5861
computeGrid();
5962

63+
computeViaDemandLengths();
64+
6065
if (verbose_) {
6166
logger_->report("Design statistics");
6267
logger_->report("Nets: {}", nets_.size());
@@ -347,6 +352,135 @@ void Design::setUnitCosts()
347352
}
348353
}
349354

355+
odb::dbTechVia* Design::chooseViaForPair(odb::dbTechLayer* lower_tl,
356+
odb::dbTechLayer* upper_tl) const
357+
{
358+
// Rank vias connecting the pair by a drt-like priority: OR_DEFAULT, then
359+
// fewest cuts, then LEF-default, then smallest enclosure.
360+
odb::dbTechLayer* cut_tl = lower_tl->getUpperLayer();
361+
odb::dbTechVia* best = nullptr;
362+
std::tuple<bool, int, bool, int64_t> best_key;
363+
for (odb::dbTechVia* via : tech_->getVias()) {
364+
if (via->getBottomLayer() != lower_tl || via->getTopLayer() != upper_tl) {
365+
continue;
366+
}
367+
int cuts = 0;
368+
int64_t enc_area = 0;
369+
for (odb::dbBox* box : via->getBoxes()) {
370+
odb::dbTechLayer* bl = box->getTechLayer();
371+
if (bl == cut_tl) {
372+
cuts++;
373+
} else if (bl == lower_tl || bl == upper_tl) {
374+
enc_area += box->getBox().area();
375+
}
376+
}
377+
const bool or_default
378+
= odb::dbStringProperty::find(via, "OR_DEFAULT") != nullptr;
379+
const std::tuple<bool, int, bool, int64_t> key{
380+
!or_default, cuts, !via->isDefault(), enc_area};
381+
if (best == nullptr || key < best_key) {
382+
best = via;
383+
best_key = key;
384+
}
385+
}
386+
return best;
387+
}
388+
389+
void Design::computeViaDemandLengths()
390+
{
391+
const int num_layers = getNumLayers();
392+
// Fallback proxy (min-area stub x via_multiplier) for pairs with no via.
393+
via_demand_length_lower_.assign(num_layers, 0.0);
394+
via_demand_length_upper_.assign(num_layers, 0.0);
395+
396+
const bool debug = logger_->debugCheck(utl::GRT, "via_geom", 1);
397+
int fallback_pairs = 0;
398+
for (int i = 0; i + 1 < num_layers; i++) {
399+
const MetalLayer& lower = layers_[i];
400+
const MetalLayer& upper = layers_[i + 1];
401+
odb::dbTechLayer* lower_tl = lower.getTechLayer();
402+
odb::dbTechLayer* upper_tl = upper.getTechLayer();
403+
odb::dbTechVia* via = chooseViaForPair(lower_tl, upper_tl);
404+
if (via == nullptr) {
405+
fallback_pairs++;
406+
}
407+
408+
double num_lower = lower.getMinLength() * constants_.via_multiplier;
409+
double num_upper = upper.getMinLength() * constants_.via_multiplier;
410+
// Union the boxes on each layer; a via may have several rects per layer.
411+
odb::Rect lo_box, up_box;
412+
lo_box.mergeInit();
413+
up_box.mergeInit();
414+
if (via != nullptr) {
415+
for (odb::dbBox* box : via->getBoxes()) {
416+
if (box->getTechLayer() == lower_tl) {
417+
lo_box.merge(box->getBox());
418+
} else if (box->getTechLayer() == upper_tl) {
419+
up_box.merge(box->getBox());
420+
}
421+
}
422+
if (!lo_box.isInverted() && lo_box.dx() > 0 && lo_box.dy() > 0) {
423+
num_lower = viaDemandLength(lower, lo_box.dx(), lo_box.dy());
424+
}
425+
if (!up_box.isInverted() && up_box.dx() > 0 && up_box.dy() > 0) {
426+
num_upper = viaDemandLength(upper, up_box.dx(), up_box.dy());
427+
}
428+
}
429+
via_demand_length_lower_[i] = num_lower;
430+
via_demand_length_upper_[i] = num_upper;
431+
432+
if (debug) {
433+
// Report enclosures, lengths, and per-track demand for each pair.
434+
const int gcell = default_gridline_spacing_;
435+
const std::string via_src
436+
= via != nullptr ? via->getName() : std::string("min_area-fallback");
437+
debugPrint(
438+
logger_,
439+
utl::GRT,
440+
"via_geom",
441+
1,
442+
"via {}->{} [{}]: encl lower={}x{} upper={}x{} -> len "
443+
"lower={:.1f} upper={:.1f} -> demand lower={:.4f} upper={:.4f}",
444+
lower.getName(),
445+
upper.getName(),
446+
via_src,
447+
lo_box.isInverted() ? 0 : lo_box.dx(),
448+
lo_box.isInverted() ? 0 : lo_box.dy(),
449+
up_box.isInverted() ? 0 : up_box.dx(),
450+
up_box.isInverted() ? 0 : up_box.dy(),
451+
num_lower,
452+
num_upper,
453+
gcell > 0 ? num_lower / gcell : 0.0,
454+
gcell > 0 ? num_upper / gcell : 0.0);
455+
}
456+
}
457+
458+
if (fallback_pairs > 0) {
459+
logger_->warn(utl::GRT,
460+
173,
461+
"{} layer pair(s) have no via; using min-area via demand.",
462+
fallback_pairs);
463+
}
464+
}
465+
466+
double Design::viaDemandLength(const MetalLayer& layer,
467+
const int dx,
468+
const int dy) const
469+
{
470+
const int pitch = layer.getPitch();
471+
// getSpacing() is 0 on parallel-table-only techs; use default spacing then.
472+
const int spacing
473+
= layer.getSpacing() > 0 ? layer.getSpacing() : layer.getDefaultSpacing();
474+
// Split the pad into extent along the routing direction and across tracks.
475+
const int along = (layer.getDirection() == MetalLayer::H) ? dx : dy;
476+
const int perp = (layer.getDirection() == MetalLayer::H) ? dy : dx;
477+
// A via blocks whole tracks; ceil the keep-out to an integer track count.
478+
const double tracks_blocked
479+
= pitch > 0 ? std::ceil(static_cast<double>(perp + 2 * spacing) / pitch)
480+
: 1.0;
481+
return along * tracks_blocked;
482+
}
483+
350484
void Design::getAllObstacles(std::vector<std::vector<BoxT>>& all_obstacles,
351485
const bool skip_m1) const
352486
{

src/grt/src/cugr/src/Design.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class dbDatabase;
1717
class dbITerm;
1818
class dbNet;
1919
class dbTech;
20+
class dbTechLayer;
21+
class dbTechVia;
2022
} // namespace odb
2123

2224
namespace sta {
@@ -56,6 +58,15 @@ class Design
5658
{
5759
return layers_[layer_index];
5860
}
61+
// Effective via demand length charged to the lower / upper layer of via i.
62+
double getViaDemandLengthLower(int i) const
63+
{
64+
return via_demand_length_lower_[i];
65+
}
66+
double getViaDemandLengthUpper(int i) const
67+
{
68+
return via_demand_length_upper_[i];
69+
}
5970

6071
// For global routing
6172
const std::vector<std::vector<int>>& getGridlines() const
@@ -85,6 +96,13 @@ class Design
8596
void readDesignObstructions();
8697
void computeGrid();
8798
void setUnitCosts();
99+
// Fill via_demand_length_{lower,upper}_ from each pair's via geometry.
100+
void computeViaDemandLengths();
101+
// Pick the via for a layer pair, ranked to approximate drt's choice.
102+
odb::dbTechVia* chooseViaForPair(odb::dbTechLayer* lower_tl,
103+
odb::dbTechLayer* upper_tl) const;
104+
// Via pad demand length: extent along routing dir x tracks blocked across.
105+
double viaDemandLength(const MetalLayer& layer, int dx, int dy) const;
88106

89107
// debug functions
90108
void printNets() const;
@@ -93,6 +111,9 @@ class Design
93111
int lib_dbu_;
94112
BoxT die_region_;
95113
std::vector<MetalLayer> layers_;
114+
// Effective via demand length per lower layer i (lower_ = i, upper_ = i+1).
115+
std::vector<double> via_demand_length_lower_;
116+
std::vector<double> via_demand_length_upper_;
96117
std::vector<CUGRNet> nets_;
97118
std::unordered_map<odb::dbNet*, int> db_net_to_id_;
98119
std::vector<BoxOnLayer> obstacles_;

src/grt/src/cugr/src/GridGraph.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,10 @@ GridGraph::GridGraph(const Design* design,
5555

5656
layer_names_.resize(num_layers_);
5757
layer_directions_.resize(num_layers_);
58-
layer_min_lengths_.resize(num_layers_);
5958
for (int layer_index = 0; layer_index < num_layers_; layer_index++) {
6059
const auto& layer = design->getLayer(layer_index);
6160
layer_names_[layer_index] = layer.getName();
6261
layer_directions_[layer_index] = layer.getDirection();
63-
layer_min_lengths_[layer_index] = layer.getMinLength();
6462
// First non-zero sheet/via resistance is the res-aware cost reference.
6563
if (ref_resistance_ <= 0.0 && layer.getResistance() > 0.0) {
6664
ref_resistance_ = layer.getResistance();
@@ -295,6 +293,17 @@ GridGraph::GridGraph(const Design* design,
295293
}
296294
}
297295

296+
CapacityT GridGraph::viaDemand(const int layer_index,
297+
const int l,
298+
const int edge_sum) const
299+
{
300+
// Spread the layer's precomputed via demand length over its two edges.
301+
const double via_num = (l == layer_index)
302+
? design_->getViaDemandLengthLower(layer_index)
303+
: design_->getViaDemandLengthUpper(layer_index);
304+
return edge_sum > 0 ? (CapacityT) via_num / edge_sum : (CapacityT) 0;
305+
}
306+
298307
void GridGraph::computeCongestionInformation()
299308
{
300309
if (!congestion_info_dirty_) {
@@ -508,9 +517,8 @@ CostT GridGraph::getViaCost(const int layer_index,
508517

509518
// Prevent division by zero
510519
if (lower_edge_length > 0 || higher_edge_length > 0) {
511-
const CapacityT demand = (CapacityT) layer_min_lengths_[l]
512-
/ (lower_edge_length + higher_edge_length)
513-
* constants_.via_multiplier;
520+
const CapacityT demand
521+
= viaDemand(layer_index, l, lower_edge_length + higher_edge_length);
514522
const double layer_factor
515523
= std::cmp_less(l, net_costs.size()) ? net_costs[l] : 1.0;
516524
if (lower_edge_length > 0) {
@@ -870,9 +878,8 @@ void GridGraph::commitVia(const int layer_index,
870878

871879
// Prevent division by zero
872880
if (lower_edge_length > 0 || higher_edge_length > 0) {
873-
const CapacityT demand = (CapacityT) layer_min_lengths_[l]
874-
/ (lower_edge_length + higher_edge_length)
875-
* constants_.via_multiplier;
881+
const CapacityT demand
882+
= viaDemand(layer_index, l, lower_edge_length + higher_edge_length);
876883
// Use the per-layer NDR factor for `l`, not a net-wide value.
877884
const double layer_factor
878885
= std::cmp_less(l, net_costs.size()) ? net_costs[l] : 1.0;

src/grt/src/cugr/src/GridGraph.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,14 @@ class GridGraph
354354
void commitTree(const std::shared_ptr<GRTreeNode>& tree,
355355
bool rip_up = false,
356356
const std::vector<double>& net_costs = {});
357+
// Per-via demand on layer `l` of via `layer_index`, spread over `edge_sum`.
358+
CapacityT viaDemand(int layer_index, int l, int edge_sum) const;
357359

358360
utl::Logger* logger_;
359361
const std::vector<std::vector<int>> gridlines_;
360362
std::vector<std::vector<int>> grid_centers_;
361363
std::vector<std::string> layer_names_;
362364
std::vector<int> layer_directions_;
363-
std::vector<int> layer_min_lengths_;
364365

365366
const int lib_dbu_;
366367
const int m2_pitch_;

src/grt/src/cugr/src/Layers.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ namespace grt {
1414
MetalLayer::MetalLayer(odb::dbTechLayer* tech_layer,
1515
odb::dbTrackGrid* track_grid)
1616
{
17+
tech_layer_ = tech_layer;
1718
name_ = tech_layer->getName();
1819
index_ = tech_layer->getRoutingLevel() - 1;
1920
direction_
2021
= tech_layer->getDirection() == odb::dbTechLayerDir::HORIZONTAL ? H : V;
2122
width_ = tech_layer->getWidth();
2223
min_width_ = tech_layer->getMinWidth();
24+
spacing_ = tech_layer->getSpacing();
2325

2426
// Sheet R and the via-cut R above (for the res-aware cost); 0 when the
2527
// tech leaves them undefined.

src/grt/src/cugr/src/Layers.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class MetalLayer
2121
int getDirection() const { return direction_; }
2222
int getWidth() const { return width_; }
2323
int getPitch() const { return pitch_; }
24+
// Min spacing to a neighbour on this layer; used for the via-demand model.
25+
int getSpacing() const { return spacing_; }
26+
odb::dbTechLayer* getTechLayer() const { return tech_layer_; }
2427
// Sheet resistance (ohms/square) of this routing layer.
2528
double getResistance() const { return resistance_; }
2629
// Per-cut resistance (ohms) of the via layer just above this routing
@@ -39,11 +42,13 @@ class MetalLayer
3942
void setAdjustment(float adjustment) { adjustment_ = adjustment; }
4043

4144
private:
45+
odb::dbTechLayer* tech_layer_ = nullptr;
4246
std::string name_;
4347
int index_;
4448
int direction_;
4549
int width_;
4650
int min_width_;
51+
int spacing_ = 0;
4752
double resistance_ = 0.0;
4853
double via_resistance_ = 0.0;
4954

src/grt/test/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ TESTS = [
118118
"tracks3",
119119
"unplaced_inst",
120120
"upper_layer_net",
121+
"via_geometry_cugr",
122+
"via_multirect_cugr",
123+
"via_priority_cugr",
121124
"write_segments1",
122125
"write_segments2",
123126
]

src/grt/test/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ or_integration_tests(
115115
tracks3
116116
unplaced_inst
117117
upper_layer_net
118+
via_geometry_cugr
119+
via_multirect_cugr
120+
via_priority_cugr
118121
write_segments1
119122
write_segments2
120123
PASSFAIL_TESTS

src/grt/test/clock_route_cugr.ok

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ Bottleneck: (5, 0, 0)
4848
Layer Resource Demand Usage (%) Max H / Max V / Total Congestion
4949
---------------------------------------------------------------------------------------
5050
li1 0 0 0.00% 0 / 0 / 0
51-
met1 27555 74 0.27% 0 / 0 / 0
51+
met1 27555 68 0.25% 0 / 0 / 0
5252
met2 21571 63 0.29% 0 / 0 / 0
53-
met3 14023 25 0.18% 0 / 0 / 0
54-
met4 10804 13 0.12% 0 / 0 / 0
53+
met3 14023 24 0.17% 0 / 0 / 0
54+
met4 10804 12 0.11% 0 / 0 / 0
5555
met5 3108 0 0.00% 0 / 0 / 0
5656
---------------------------------------------------------------------------------------
57-
Total 77061 175 0.23% 0 / 0 / 0
57+
Total 77061 167 0.22% 0 / 0 / 0
5858

5959
[INFO GRT-0018] Total wirelength: 1641 um
6060
[INFO GRT-0014] Routed nets: 15

0 commit comments

Comments
 (0)