Skip to content

Commit d052dae

Browse files
authored
Merge pull request #9084 from gadfort/global-connect-force
odb: add force/verbose to global_connect
2 parents df5dea9 + 76ed634 commit d052dae

22 files changed

+608
-42
lines changed

src/OpenRoad.tcl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,14 @@ proc cpu_count { } {
320320
return [ord::cpu_count]
321321
}
322322

323-
sta::define_cmd_args "global_connect" {}
324-
proc global_connect { } {
325-
[ord::get_db_block] globalConnect
323+
sta::define_cmd_args "global_connect" { [-force] [-verbose] }
324+
proc global_connect { args } {
325+
sta::parse_key_args "global_connect" args \
326+
keys {} \
327+
flags {-force -verbose}
328+
329+
sta::check_argc_eq0 "add_global_connection" $args
330+
[ord::get_db_block] globalConnect [info exists flags(-force)] [info exists flags(-verbose)]
326331
}
327332

328333
sta::define_cmd_args "clear_global_connect" {}

src/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,16 @@ add_global_connection -net VSS -pin_pattern {^VSSE$}
263263
The `global_connect` command is used to connect power and ground pins on design instances to the appropriate supplies.
264264

265265
```
266-
global_connect
266+
global_connect [-force] [-verbose]
267267
```
268268

269+
##### Options
270+
271+
| Switch Name | Description |
272+
| ----- | ----- |
273+
| `-force` | If specified, global connections will overwrite existing connections |
274+
| `-verbose` | If specified, report the number of connections made and skipped. |
275+
269276
#### Clear global connection rules
270277

271278
The `clear_global_connect` command is used remove all defined global connection rules.
551 Bytes
Loading

src/gui/resources/resource.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
<file alias="cancel.png">google_icons/round_cancel_black_36dp.png</file>
1818
<file alias="expand_more.png">google_icons/round_unfold_more_black_36dp.png</file>
1919
<file alias="expand_less.png">google_icons/round_unfold_less_black_36dp.png</file>
20+
<file alias="resume.png">google_icons/resume.png</file>
2021
</qresource>
2122
</RCC>

src/gui/src/globalConnectDialog.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ GlobalConnectDialog::GlobalConnectDialog(odb::dbBlock* block, QWidget* parent)
5050
add_(new QPushButton(this)),
5151
clear_(new QPushButton(this)),
5252
run_(new QPushButton(this)),
53+
run_force_(new QPushButton(this)),
5354
rules_({}),
5455
inst_pattern_(new QLineEdit(this)),
5556
pin_pattern_(new QLineEdit(this)),
@@ -64,6 +65,7 @@ GlobalConnectDialog::GlobalConnectDialog(odb::dbBlock* block, QWidget* parent)
6465
QHBoxLayout* button_layout = new QHBoxLayout;
6566
button_layout->addWidget(clear_);
6667
button_layout->addWidget(run_);
68+
button_layout->addWidget(run_force_);
6769
layout->addLayout(button_layout);
6870
layout->addWidget(connections_);
6971

@@ -75,18 +77,27 @@ GlobalConnectDialog::GlobalConnectDialog(odb::dbBlock* block, QWidget* parent)
7577
add_->setDefault(false);
7678
add_->setEnabled(false);
7779

78-
run_->setIcon(QIcon(":/play.png"));
80+
run_->setIcon(QIcon(":/resume.png"));
7981
run_->setToolTip(tr("Run"));
8082
run_->setAutoDefault(false);
8183
run_->setDefault(false);
8284

85+
run_force_->setIcon(QIcon(":/play.png"));
86+
run_force_->setToolTip(tr("Run with forced connections"));
87+
run_force_->setAutoDefault(false);
88+
run_force_->setDefault(false);
89+
8390
clear_->setIcon(QIcon(":/delete.png"));
8491
clear_->setToolTip(tr("Clear"));
8592
clear_->setAutoDefault(false);
8693
clear_->setDefault(false);
8794

8895
connect(add_, &QPushButton::pressed, this, &GlobalConnectDialog::makeRule);
8996
connect(run_, &QPushButton::pressed, this, &GlobalConnectDialog::runRules);
97+
connect(run_force_,
98+
&QPushButton::pressed,
99+
this,
100+
&GlobalConnectDialog::runRulesWithForce);
90101
connect(
91102
clear_, &QPushButton::pressed, this, &GlobalConnectDialog::clearRules);
92103

@@ -157,7 +168,12 @@ GlobalConnectDialog::GlobalConnectDialog(odb::dbBlock* block, QWidget* parent)
157168

158169
void GlobalConnectDialog::runRules()
159170
{
160-
runRule(nullptr);
171+
runRule(nullptr, false);
172+
}
173+
174+
void GlobalConnectDialog::runRulesWithForce()
175+
{
176+
runRule(nullptr, true);
161177
}
162178

163179
void GlobalConnectDialog::clearRules()
@@ -242,7 +258,8 @@ void GlobalConnectDialog::addRule(odb::dbGlobalConnect* gc)
242258
widgets.run->setToolTip(tr("Run"));
243259
widgets.run->setAutoDefault(false);
244260
widgets.run->setDefault(false);
245-
connect(widgets.run, &QPushButton::pressed, [this, gc]() { runRule(gc); });
261+
connect(
262+
widgets.run, &QPushButton::pressed, [this, gc]() { runRule(gc, false); });
246263
layout_->addWidget(
247264
widgets.run, row_idx, toValue(GlobalConnectField::kRun), Qt::AlignCenter);
248265

@@ -311,15 +328,15 @@ void GlobalConnectDialog::announceConnections(int connections)
311328
QString::fromStdString(fmt::format("Connected {} pin(s)", connections)));
312329
}
313330

314-
void GlobalConnectDialog::runRule(odb::dbGlobalConnect* gc)
331+
void GlobalConnectDialog::runRule(odb::dbGlobalConnect* gc, bool force)
315332
{
316333
QApplication::setOverrideCursor(Qt::WaitCursor);
317334
QApplication::processEvents();
318335
int connections = 0;
319336
if (gc == nullptr) {
320-
connections = block_->globalConnect();
337+
connections = block_->globalConnect(force, true);
321338
} else {
322-
connections = block_->globalConnect(gc);
339+
connections = block_->globalConnect(gc, force, true);
323340
}
324341
QApplication::restoreOverrideCursor();
325342
emit connectionsMade(connections);

src/gui/src/globalConnectDialog.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class GlobalConnectDialog : public QDialog
2828

2929
private slots:
3030
void runRules();
31+
void runRulesWithForce();
3132
void clearRules();
3233
void deleteRule(odb::dbGlobalConnect* gconnect);
3334
void makeRule();
@@ -42,6 +43,7 @@ class GlobalConnectDialog : public QDialog
4243
QPushButton* add_;
4344
QPushButton* clear_;
4445
QPushButton* run_;
46+
QPushButton* run_force_;
4547

4648
struct GlobalConnectWidgets
4749
{
@@ -63,7 +65,7 @@ class GlobalConnectDialog : public QDialog
6365
QLabel* connections_;
6466

6567
void addRule(odb::dbGlobalConnect* gc);
66-
void runRule(odb::dbGlobalConnect* gc);
68+
void runRule(odb::dbGlobalConnect* gc, bool force);
6769
};
6870

6971
} // namespace gui

src/odb/include/odb/db.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -747,8 +747,8 @@ class dbBlock : public dbObject
747747
/// and helper functions for global connections
748748
/// on this block.
749749
///
750-
int globalConnect();
751-
int globalConnect(dbGlobalConnect* gc);
750+
int globalConnect(bool force, bool verbose);
751+
int globalConnect(dbGlobalConnect* gc, bool force, bool verbose);
752752
int addGlobalConnect(dbRegion* region,
753753
const char* instPattern,
754754
const char* pinPattern,
@@ -7864,7 +7864,7 @@ class dbGlobalConnect : public dbObject
78647864
// User Code Begin dbGlobalConnect
78657865
std::vector<dbInst*> getInsts() const;
78667866

7867-
int connect(dbInst* inst);
7867+
int connect(dbInst* inst, bool force);
78687868

78697869
static dbGlobalConnect* create(dbNet* net,
78707870
dbRegion* region,

src/odb/src/db/dbBlock.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3347,18 +3347,18 @@ void dbBlock::destroyNetWires()
33473347
}
33483348
}
33493349

3350-
int dbBlock::globalConnect()
3350+
int dbBlock::globalConnect(bool force, bool verbose)
33513351
{
33523352
dbSet<dbGlobalConnect> gcs = getGlobalConnects();
33533353
const std::vector<dbGlobalConnect*> connects(gcs.begin(), gcs.end());
33543354
_dbBlock* dbblock = (_dbBlock*) this;
3355-
return dbblock->globalConnect(connects);
3355+
return dbblock->globalConnect(connects, force, verbose);
33563356
}
33573357

3358-
int dbBlock::globalConnect(dbGlobalConnect* gc)
3358+
int dbBlock::globalConnect(dbGlobalConnect* gc, bool force, bool verbose)
33593359
{
33603360
_dbBlock* dbblock = (_dbBlock*) this;
3361-
return dbblock->globalConnect({gc});
3361+
return dbblock->globalConnect({gc}, force, verbose);
33623362
}
33633363

33643364
void dbBlock::clearGlobalConnect()
@@ -3419,12 +3419,14 @@ int dbBlock::addGlobalConnect(dbRegion* region,
34193419
= odb::dbGlobalConnect::create(net, region, instPattern, pinPattern);
34203420

34213421
if (gc != nullptr && do_connect) {
3422-
return globalConnect(gc);
3422+
return globalConnect(gc, false, false);
34233423
}
34243424
return 0;
34253425
}
34263426

3427-
int _dbBlock::globalConnect(const std::vector<dbGlobalConnect*>& connects)
3427+
int _dbBlock::globalConnect(const std::vector<dbGlobalConnect*>& connects,
3428+
bool force,
3429+
bool verbose)
34283430
{
34293431
_dbBlock* dbblock = (_dbBlock*) this;
34303432
utl::Logger* logger = dbblock->getImpl()->getLogger();
@@ -3439,6 +3441,7 @@ int _dbBlock::globalConnect(const std::vector<dbGlobalConnect*>& connects)
34393441
std::vector<_dbGlobalConnect*> region_rules;
34403442

34413443
std::set<dbITerm*> connected_iterms;
3444+
std::set<dbITerm*> skipped_iterms;
34423445
// only search for instances once
34433446
std::map<std::string, std::vector<dbInst*>> inst_map;
34443447
std::set<dbInst*> donottouchinsts;
@@ -3472,9 +3475,8 @@ int _dbBlock::globalConnect(const std::vector<dbGlobalConnect*>& connects)
34723475

34733476
inst_map[inst_pattern] = insts;
34743477

3475-
_dbGlobalConnect* connect_rule = (_dbGlobalConnect*) connect;
34763478
for (dbInst* inst : remove_insts) {
3477-
if (connect_rule->needsModification(inst)) {
3479+
if (gc->needsModification(inst)) {
34783480
donottouchinsts.insert(inst);
34793481
}
34803482
}
@@ -3491,12 +3493,25 @@ int _dbBlock::globalConnect(const std::vector<dbGlobalConnect*>& connects)
34913493
}
34923494

34933495
for (_dbGlobalConnect* connect : non_region_rules) {
3494-
const auto connections = connect->connect(inst_map[connect->inst_pattern_]);
3496+
const auto& [connections, skipped]
3497+
= connect->connect(inst_map[connect->inst_pattern_], force);
34953498
connected_iterms.insert(connections.begin(), connections.end());
3499+
skipped_iterms.insert(skipped.begin(), skipped.end());
34963500
}
34973501
for (_dbGlobalConnect* connect : region_rules) {
3498-
const auto connections = connect->connect(inst_map[connect->inst_pattern_]);
3502+
const auto& [connections, skipped]
3503+
= connect->connect(inst_map[connect->inst_pattern_], force);
34993504
connected_iterms.insert(connections.begin(), connections.end());
3505+
skipped_iterms.insert(skipped.begin(), skipped.end());
3506+
}
3507+
3508+
if (verbose) {
3509+
logger->info(utl::ODB,
3510+
403,
3511+
"{} connections made, {} conflicts skipped{}",
3512+
connected_iterms.size(),
3513+
skipped_iterms.size(),
3514+
skipped_iterms.empty() ? "." : ", use -force to connect.");
35003515
}
35013516

35023517
return connected_iterms.size();

src/odb/src/db/dbBlock.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ class _dbBlock : public _dbObject
163163
bool operator==(const _dbBlock& rhs) const;
164164
bool operator!=(const _dbBlock& rhs) const { return !operator==(rhs); }
165165

166-
int globalConnect(const std::vector<dbGlobalConnect*>& connects);
166+
int globalConnect(const std::vector<dbGlobalConnect*>& connects,
167+
bool force,
168+
bool verbose);
167169
_dbTech* getTech();
168170

169171
dbObjectTable* getObjectTable(dbObjectType type);

src/odb/src/db/dbGlobalConnect.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "dbTable.hpp"
1313
#include "odb/db.h"
1414
// User Code Begin Includes
15+
#include <utility>
16+
1517
#include "dbInst.h"
1618
#include "dbLib.h"
1719
#include "dbMTerm.h"
@@ -150,7 +152,7 @@ std::vector<dbInst*> dbGlobalConnect::getInsts() const
150152
return insts;
151153
}
152154

153-
int dbGlobalConnect::connect(dbInst* inst)
155+
int dbGlobalConnect::connect(dbInst* inst, bool force)
154156
{
155157
if (inst->isDoNotTouch()) {
156158
return 0;
@@ -161,7 +163,7 @@ int dbGlobalConnect::connect(dbInst* inst)
161163
return 0;
162164
}
163165

164-
const auto connections = obj->connect({inst});
166+
const auto& [connections, skipped] = obj->connect({inst}, force);
165167
return connections.size();
166168
}
167169

@@ -283,24 +285,28 @@ std::set<dbMTerm*> _dbGlobalConnect::getMTermMapping(
283285
return mterms;
284286
}
285287

286-
std::set<dbITerm*> _dbGlobalConnect::connect(const std::vector<dbInst*>& insts)
288+
std::pair<std::set<dbITerm*>, std::set<dbITerm*>> _dbGlobalConnect::connect(
289+
const std::vector<dbInst*>& insts,
290+
bool force)
287291
{
288292
utl::Logger* logger = getImpl()->getLogger();
289293
dbBlock* block = (dbBlock*) getImpl()->getOwner();
290294
dbNet* net = odb::dbNet::getNet(block, net_);
291295

296+
std::set<dbITerm*> iterms;
297+
std::set<dbITerm*> iterms_skipped;
298+
292299
if (net->isDoNotTouch()) {
293300
logger->warn(
294301
utl::ODB,
295302
379,
296-
"{} is marked do not touch, will be skipped for global conenctions",
303+
"{} is marked do not touch, will be skipped for global connections",
297304
net->getName());
298-
return {};
305+
return {iterms, iterms_skipped};
299306
}
300307

301308
const auto mterm_map = getMTermMapping();
302309

303-
std::set<dbITerm*> iterms;
304310
for (dbInst* inst : insts) {
305311
_dbInst* dbinst = (_dbInst*) inst;
306312
if (region_ != 0 && region_ != dbinst->region_) {
@@ -318,17 +324,25 @@ std::set<dbITerm*> _dbGlobalConnect::connect(const std::vector<dbInst*>& insts)
318324
auto* iterm = inst->getITerm(mterm);
319325

320326
auto* current_net = iterm->getNet();
327+
if (current_net == net) {
328+
// Already connected, nothing to do
329+
continue;
330+
}
321331
if (current_net != nullptr && current_net->isDoNotTouch()) {
322-
logger->warn(utl::ODB,
323-
380,
324-
"{}/{} is connected to {} which is marked do not touch, "
325-
"this connection will not be modified.",
326-
inst->getName(),
327-
mterm->getName(),
328-
current_net->getName());
332+
// Connected, but current net is marked do not touch, nothing to do
333+
if (force) {
334+
logger->warn(utl::ODB,
335+
380,
336+
"{} is connected to {} which is marked do not touch, "
337+
"this connection will not be modified.",
338+
iterm->getName(),
339+
current_net->getName());
340+
}
329341
continue;
330342
}
331-
if (current_net == net) {
343+
if (current_net != nullptr && !force) {
344+
// Already connected, so dont update unless force
345+
iterms_skipped.insert(iterm);
332346
continue;
333347
}
334348
iterm->connect(net);
@@ -338,7 +352,7 @@ std::set<dbITerm*> _dbGlobalConnect::connect(const std::vector<dbInst*>& insts)
338352
iterms.insert(iterm);
339353
}
340354
}
341-
return iterms;
355+
return {iterms, iterms_skipped};
342356
}
343357

344358
bool _dbGlobalConnect::appliesTo(dbInst* inst) const

0 commit comments

Comments
 (0)