Skip to content

Commit d5b7931

Browse files
authored
Merge pull request #7906 from gadfort/pdn-stagger
pdn: add support for staggering split cuts
2 parents 814048c + 2e55034 commit d5b7931

16 files changed

+3639
-57
lines changed

src/pdn/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ add_pdn_connect
358358
[-max_rows rows]
359359
[-ongrid ongrid_layers]
360360
[-split_cuts split_cuts_mapping]
361+
[-split_cuts_staggered]
361362
```
362363

363364
#### Options
@@ -373,6 +374,7 @@ add_pdn_connect
373374
| `[-max_rows]` | Maximum number of rows when adding arrays of vias. |
374375
| `[-ongrid]` | List of intermediate layers in a via stack to snap onto a routing grid. |
375376
| `[-split_cuts]` | Specifies layers to use split cuts on with an associated pitch, for example `{metal3 0.380 metal5 0.500}`. |
377+
| `[-split_cuts_staggered]` | Specified if the split cuts should be staggered, ie. the ground vias will appear with an offset of pitch / 2. |
376378

377379
### Repairing power grid vias after detailed routing
378380

src/pdn/include/pdn/PdnGen.hh

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,19 @@ class PdnGen
145145
StartsWith starts_with,
146146
ExtensionMode extend,
147147
const std::vector<odb::dbNet*>& nets);
148-
void makeConnect(Grid* grid,
149-
odb::dbTechLayer* layer0,
150-
odb::dbTechLayer* layer1,
151-
int cut_pitch_x,
152-
int cut_pitch_y,
153-
const std::vector<odb::dbTechViaGenerateRule*>& vias,
154-
const std::vector<odb::dbTechVia*>& techvias,
155-
int max_rows,
156-
int max_columns,
157-
const std::vector<odb::dbTechLayer*>& ongrid,
158-
const std::map<odb::dbTechLayer*, int>& split_cuts,
159-
const std::string& dont_use_vias);
148+
void makeConnect(
149+
Grid* grid,
150+
odb::dbTechLayer* layer0,
151+
odb::dbTechLayer* layer1,
152+
int cut_pitch_x,
153+
int cut_pitch_y,
154+
const std::vector<odb::dbTechViaGenerateRule*>& vias,
155+
const std::vector<odb::dbTechVia*>& techvias,
156+
int max_rows,
157+
int max_columns,
158+
const std::vector<odb::dbTechLayer*>& ongrid,
159+
const std::map<odb::dbTechLayer*, std::pair<int, bool>>& split_cuts,
160+
const std::string& dont_use_vias);
160161

161162
void writeToDb(bool add_pins, const std::string& report_file = "") const;
162163
void ripUp(odb::dbNet* net);

src/pdn/src/PdnGen-py.i

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ using namespace pdn;
1616
%include <std_vector.i>
1717
%include <std_array.i>
1818
%include <std_map.i>
19+
%include <std_pair.i>
1920
%include <std_set.i>
2021
%include <std_string.i>
2122

22-
%include typemaps.i
23-
2423
%import "odb.i"
2524
%clear int & x, int & y; // defined in dbtypes.i, must be cleared here.
2625

@@ -29,9 +28,10 @@ using namespace pdn;
2928
// that you must %include (not %import) <std_vector.i> and <std_array.i>
3029
// before these definitions
3130
namespace std {
31+
%template() std::pair<int, bool>;
3232
%template(split_cuts_stuff) std::vector<int>;
3333
%template(stuff) std::array<int, 4>;
34-
%template(split_map) std::map<odb::dbTechLayer *, int>;
34+
%template(split_map) std::map<odb::dbTechLayer *, std::pair<int, bool>>;
3535
%template(grid_list) std::vector<pdn::Grid *>;
3636
%template(domain_list) std::vector<pdn::VoltageDomain *>;
3737
%template(net_list) std::vector<odb::dbNet *>;

src/pdn/src/PdnGen.cc

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -599,18 +599,19 @@ void PdnGen::makeStrap(Grid* grid,
599599
grid->addStrap(std::move(strap));
600600
}
601601

602-
void PdnGen::makeConnect(Grid* grid,
603-
odb::dbTechLayer* layer0,
604-
odb::dbTechLayer* layer1,
605-
int cut_pitch_x,
606-
int cut_pitch_y,
607-
const std::vector<odb::dbTechViaGenerateRule*>& vias,
608-
const std::vector<odb::dbTechVia*>& techvias,
609-
int max_rows,
610-
int max_columns,
611-
const std::vector<odb::dbTechLayer*>& ongrid,
612-
const std::map<odb::dbTechLayer*, int>& split_cuts,
613-
const std::string& dont_use_vias)
602+
void PdnGen::makeConnect(
603+
Grid* grid,
604+
odb::dbTechLayer* layer0,
605+
odb::dbTechLayer* layer1,
606+
int cut_pitch_x,
607+
int cut_pitch_y,
608+
const std::vector<odb::dbTechViaGenerateRule*>& vias,
609+
const std::vector<odb::dbTechVia*>& techvias,
610+
int max_rows,
611+
int max_columns,
612+
const std::vector<odb::dbTechLayer*>& ongrid,
613+
const std::map<odb::dbTechLayer*, std::pair<int, bool>>& split_cuts,
614+
const std::string& dont_use_vias)
614615
{
615616
auto con = std::make_unique<Connect>(grid, layer0, layer1);
616617
con->setCutPitch(cut_pitch_x, cut_pitch_y);
@@ -626,7 +627,13 @@ void PdnGen::makeConnect(Grid* grid,
626627
con->setMaxRows(max_rows);
627628
con->setMaxColumns(max_columns);
628629
con->setOnGrid(ongrid);
629-
con->setSplitCuts(split_cuts);
630+
631+
std::map<odb::dbTechLayer*, Connect::SplitCut> split_cuts_map;
632+
for (const auto& [layer, cut_def] : split_cuts) {
633+
split_cuts_map[layer]
634+
= Connect::SplitCut{std::get<0>(cut_def), std::get<1>(cut_def)};
635+
}
636+
con->setSplitCuts(split_cuts_map);
630637

631638
if (!dont_use_vias.empty()) {
632639
con->filterVias(dont_use_vias);

src/pdn/src/PdnGen.i

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,13 @@ void make_connect(const char* grid_name,
267267
const std::vector<odb::dbTechLayer*>& ongrid,
268268
const std::vector<odb::dbTechLayer*>& split_cuts_layers,
269269
const std::vector<int>& split_cut_pitches,
270+
const bool split_cut_stagger,
270271
const char* dont_use_vias)
271272
{
272273
PdnGen* pdngen = ord::getPdnGen();
273-
std::map<odb::dbTechLayer*, int> split_cuts;
274+
std::map<odb::dbTechLayer*, std::pair<int, bool>> split_cuts;
274275
for (size_t i = 0; i < split_cuts_layers.size(); i++) {
275-
split_cuts[split_cuts_layers[i]] = split_cut_pitches[i];
276+
split_cuts[split_cuts_layers[i]] = {split_cut_pitches[i], split_cut_stagger};
276277
}
277278
for (auto* grid : pdngen->findGrid(grid_name)) {
278279
pdngen->makeConnect(grid, layer0, layer1, cut_pitch_x, cut_pitch_y, vias, techvias, max_rows, max_columns, ongrid, split_cuts, dont_use_vias);

src/pdn/src/connect.cpp

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void Connect::setOnGrid(const std::vector<odb::dbTechLayer*>& layers)
9292
ongrid_.insert(layers.begin(), layers.end());
9393
}
9494

95-
void Connect::setSplitCuts(const std::map<odb::dbTechLayer*, int>& splits)
95+
void Connect::setSplitCuts(const std::map<odb::dbTechLayer*, SplitCut>& splits)
9696
{
9797
split_cuts_ = splits;
9898
// remove top and bottom layers of the stack
@@ -107,7 +107,17 @@ int Connect::getSplitCutPitch(odb::dbTechLayer* layer) const
107107
return 0;
108108
}
109109

110-
return layer_itr->second;
110+
return layer_itr->second.pitch;
111+
}
112+
113+
bool Connect::getSplitCutStagger(odb::dbTechLayer* layer) const
114+
{
115+
auto layer_itr = split_cuts_.find(layer);
116+
if (layer_itr == split_cuts_.end()) {
117+
return false;
118+
}
119+
120+
return layer_itr->second.stagger;
111121
}
112122

113123
bool Connect::appliesToVia(const ViaPtr& via) const
@@ -417,10 +427,11 @@ void Connect::report() const
417427
}
418428
if (!split_cuts_.empty()) {
419429
logger->report(" Split cuts:");
420-
for (const auto& [layer, pitch] : split_cuts_) {
421-
logger->report(" Layer: {} with pitch {:.4f}",
430+
for (const auto& [layer, cut_def] : split_cuts_) {
431+
logger->report(" Layer: {} with pitch {:.4f}{}",
422432
layer->getName(),
423-
pitch / dbu_per_micron);
433+
cut_def.pitch / dbu_per_micron,
434+
cut_def.stagger ? " staggered" : "");
424435
}
425436
}
426437
}
@@ -448,10 +459,27 @@ void Connect::makeVia(odb::dbSWire* wire,
448459
return;
449460
}
450461

462+
odb::dbNet* index_net = nullptr;
463+
if (!split_cuts_.empty()) {
464+
index_net = wire->getNet();
465+
}
466+
451467
const ViaIndex via_index
452-
= std::make_pair(intersection.dx(), intersection.dy());
468+
= std::make_tuple(index_net, intersection.dx(), intersection.dy());
453469
auto& via = vias_[via_index];
454470

471+
debugPrint(grid_->getLogger(),
472+
utl::PDN,
473+
"Via",
474+
2,
475+
"Cache {} at {} / {} / {}",
476+
via == nullptr ? "miss" : "hit",
477+
std::get<0>(via_index) != nullptr
478+
? std::get<0>(via_index)->getName()
479+
: "null",
480+
std::get<1>(via_index),
481+
std::get<2>(via_index));
482+
455483
bool skip_caching = false;
456484
// make the via stack if one is not available for the given size
457485
if (via == nullptr) {
@@ -509,7 +537,8 @@ void Connect::makeVia(odb::dbSWire* wire,
509537
}
510538
}
511539

512-
auto* new_via = makeSingleLayerVia(wire->getBlock(),
540+
auto* new_via = makeSingleLayerVia(wire->getNet(),
541+
wire->getBlock(),
513542
l0,
514543
via_lower_rects,
515544
lower_constraint,
@@ -550,6 +579,7 @@ void Connect::makeVia(odb::dbSWire* wire,
550579
}
551580

552581
DbVia* Connect::generateDbVia(
582+
odb::dbNet* net,
553583
const std::vector<std::shared_ptr<ViaGenerator>>& generators,
554584
odb::dbBlock* block) const
555585
{
@@ -571,13 +601,19 @@ DbVia* Connect::generateDbVia(
571601
via->getCutLayer()->getName(),
572602
via->hasCutClass() ? via->getCutClass()->getName() : "none");
573603

574-
const int lower_split = getSplitCut(via->getBottomLayer());
575-
const int upper_split = getSplitCut(via->getTopLayer());
576-
if (lower_split != 0 || upper_split != 0) {
577-
const int pitch = std::max(lower_split, upper_split);
578-
via->setSplitCutArray(lower_split != 0, upper_split != 0);
604+
const auto lower_split = getSplitCut(via->getBottomLayer());
605+
const auto upper_split = getSplitCut(via->getTopLayer());
606+
if (lower_split.pitch != 0 || upper_split.pitch != 0) {
607+
const int pitch = std::max(lower_split.pitch, upper_split.pitch);
608+
via->setSplitCutArray(lower_split.pitch != 0, upper_split.pitch != 0);
579609
via->setCutPitchX(pitch);
580610
via->setCutPitchY(pitch);
611+
if (lower_split.stagger || upper_split.stagger) {
612+
if (net->getSigType() == odb::dbSigType::GROUND) {
613+
via->setCutOffsetX(pitch / 2);
614+
via->setCutOffsetY(pitch / 2);
615+
}
616+
}
581617
}
582618

583619
const bool lower_is_internal = via->getBottomLayer() != layer0_;
@@ -628,6 +664,7 @@ DbVia* Connect::generateDbVia(
628664
}
629665

630666
DbVia* Connect::makeSingleLayerVia(
667+
odb::dbNet* net,
631668
odb::dbBlock* block,
632669
odb::dbTechLayer* lower,
633670
const std::set<odb::Rect>& lower_rects,
@@ -678,7 +715,7 @@ DbVia* Connect::makeSingleLayerVia(
678715
generate_vias.size(),
679716
generate_via_rules_.size());
680717

681-
DbVia* generate_via = generateDbVia(generate_vias, block);
718+
DbVia* generate_via = generateDbVia(net, generate_vias, block);
682719

683720
if (generate_via != nullptr) {
684721
return generate_via;
@@ -720,7 +757,7 @@ DbVia* Connect::makeSingleLayerVia(
720757
tech_vias.size(),
721758
tech_vias_.size());
722759

723-
return generateDbVia(tech_vias, block);
760+
return generateDbVia(net, tech_vias, block);
724761
}
725762

726763
void Connect::populateGenerateRules()
@@ -831,13 +868,13 @@ bool Connect::techViaContains(odb::dbTechVia* via,
831868
return via->getBottomLayer() == lower && via->getTopLayer() == upper;
832869
}
833870

834-
int Connect::getSplitCut(odb::dbTechLayer* layer) const
871+
Connect::SplitCut Connect::getSplitCut(odb::dbTechLayer* layer) const
835872
{
836873
auto split_itr = split_cuts_.find(layer);
837874
if (split_itr != split_cuts_.end()) {
838875
return split_itr->second;
839876
}
840-
return 0;
877+
return SplitCut{};
841878
}
842879

843880
void Connect::clearShapes()

src/pdn/src/connect.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <memory>
88
#include <set>
99
#include <string>
10+
#include <tuple>
1011
#include <utility>
1112
#include <vector>
1213

@@ -19,6 +20,12 @@ namespace pdn {
1920
class Connect
2021
{
2122
public:
23+
struct SplitCut
24+
{
25+
int pitch{0};
26+
bool stagger{false};
27+
};
28+
2229
Connect(Grid* grid, odb::dbTechLayer* layer0, odb::dbTechLayer* layer1);
2330

2431
void addFixedVia(odb::dbTechViaGenerateRule* via);
@@ -36,8 +43,9 @@ class Connect
3643

3744
void setOnGrid(const std::vector<odb::dbTechLayer*>& layers);
3845

39-
void setSplitCuts(const std::map<odb::dbTechLayer*, int>& splits);
46+
void setSplitCuts(const std::map<odb::dbTechLayer*, SplitCut>& splits);
4047
int getSplitCutPitch(odb::dbTechLayer* layer) const;
48+
bool getSplitCutStagger(odb::dbTechLayer* layer) const;
4149

4250
void report() const;
4351

@@ -98,11 +106,11 @@ class Connect
98106
int max_columns_ = 0;
99107

100108
std::set<odb::dbTechLayer*> ongrid_;
101-
std::map<odb::dbTechLayer*, int> split_cuts_;
109+
std::map<odb::dbTechLayer*, SplitCut> split_cuts_;
102110

103111
// map of built vias, where the key is the width and height of the via
104112
// intersection, and the value points of the associated via stack.
105-
using ViaIndex = std::pair<int, int>;
113+
using ViaIndex = std::tuple<odb::dbNet*, int, int>;
106114
std::map<ViaIndex, std::unique_ptr<DbGenerateStackedVia>> vias_;
107115
std::vector<odb::dbTechViaGenerateRule*> generate_via_rules_;
108116
std::vector<odb::dbTechVia*> tech_vias_;
@@ -114,6 +122,7 @@ class Connect
114122
failed_vias_;
115123

116124
DbVia* makeSingleLayerVia(
125+
odb::dbNet* net,
117126
odb::dbBlock* block,
118127
odb::dbTechLayer* lower,
119128
const std::set<odb::Rect>& lower_rects,
@@ -133,9 +142,10 @@ class Connect
133142
odb::dbTechLayer* lower,
134143
odb::dbTechLayer* upper) const;
135144

136-
int getSplitCut(odb::dbTechLayer* layer) const;
145+
SplitCut getSplitCut(odb::dbTechLayer* layer) const;
137146

138147
DbVia* generateDbVia(
148+
odb::dbNet* net,
139149
const std::vector<std::shared_ptr<ViaGenerator>>& generators,
140150
odb::dbBlock* block) const;
141151

src/pdn/src/pdn.tcl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,14 +545,15 @@ sta::define_cmd_args "add_pdn_connect" {[-grid grid_name] \
545545
[-max_rows rows] \
546546
[-max_columns columns] \
547547
[-ongrid ongrid_layers] \
548-
[-split_cuts split_cuts_mapping]
548+
[-split_cuts split_cuts_mapping] \
549+
[-split_cuts_staggered]
549550
}
550551

551552
proc add_pdn_connect { args } {
552553
sta::parse_key_args "add_pdn_connect" args \
553554
keys {-grid -layers -cut_pitch -fixed_vias -max_rows -max_columns -ongrid -split_cuts \
554555
-dont_use_vias} \
555-
flags {}
556+
flags {-split_cuts_staggered}
556557

557558
sta::check_argc_eq0 "add_pdn_connect" $args
558559

@@ -616,11 +617,13 @@ proc add_pdn_connect { args } {
616617

617618
set split_cuts_layers {}
618619
set split_cuts_pitches {}
620+
set split_cuts_staggered false
619621
if { [info exists keys(-split_cuts)] } {
620622
foreach {l pitch} $keys(-split_cuts) {
621623
lappend split_cuts_layers [pdn::get_layer $l]
622624
lappend split_cuts_pitches [ord::microns_to_dbu $pitch]
623625
}
626+
set split_cuts_staggered [info exists flags(-split_cuts_staggered)]
624627
}
625628

626629
set dont_use ""
@@ -640,6 +643,7 @@ proc add_pdn_connect { args } {
640643
$ongrid \
641644
$split_cuts_layers \
642645
$split_cuts_pitches \
646+
$split_cuts_staggered \
643647
$dont_use
644648
}
645649

0 commit comments

Comments
 (0)