[GPL] Add set_net_weight/unset_net_weight commands#10049
[GPL] Add set_net_weight/unset_net_weight commands#10049jeffrey-song-melten wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
Conversation
Add TCL commands to set per-net custom placement weights via
persistent ODB properties. This enables external tools to guide
global placement by annotating nets with importance weights
(e.g., from IP-level timing characterization).
Implementation:
- set_net_weight stores weight as dbDoubleProperty("gpl_weight")
on the target dbNet. Persists across write_db/read_db.
- unset_net_weight removes the property.
- NesterovBase reads gpl_weight during GNet construction and
applies it via the existing setCustomWeight() method.
- TCL validation: positive finite float, design block required.
New commands:
set_net_weight <net_name> <weight>
unset_net_weight <net_name>
Signed-off-by: Jeffrey Song <jeffrey@melten.ai>
Signed-off-by: Jeffrey Song <jonguk@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces the ability to set and unset custom net weights for global placement. It adds Tcl commands (set_net_weight, unset_net_weight), underlying C++ implementation using ODB properties to ensure persistence, and comprehensive functional and negative tests. The review feedback highlights several improvement opportunities: adding return statements after error logging to prevent potential null pointer dereferences if the program continues, using named constants instead of magic strings for property names, and optimizing property updates by modifying existing values instead of destroying and recreating them.
| if (!net) { | ||
| ord::OpenRoad::openRoad()->getLogger()->error( | ||
| utl::GPL, 500, "Net '{}' not found.", net_name); | ||
| } | ||
| // Store as persistent ODB property so it survives write_db/read_db | ||
| auto* existing = odb::dbDoubleProperty::find(net, "gpl_weight"); | ||
| if (existing) { | ||
| odb::dbDoubleProperty::destroy(existing); | ||
| } | ||
| odb::dbDoubleProperty::create(net, "gpl_weight", weight); |
There was a problem hiding this comment.
There are a couple of improvements that can be made here:
- Robustness: While
logger->erroris expected to terminate the program, the code proceeds to dereferenceneton the following lines, which will cause a crash ifnetis null and termination does not occur. It's safer to add areturnstatement after callingerror. - Maintainability: To avoid magic strings, it's a good practice to define property names like
"gpl_weight"as a constant. - Efficiency: It's more efficient to update the property value if it exists, instead of destroying and recreating it.
The suggested code applies these improvements.
if (!net) {
ord::OpenRoad::openRoad()->getLogger()->error(
utl::GPL, 500, "Net '{}' not found.", net_name);
return;
}
// Store as persistent ODB property so it survives write_db/read_db
static const char* gpl_weight_prop_name = "gpl_weight";
if (auto* prop = odb::dbDoubleProperty::find(net, gpl_weight_prop_name)) {
prop->setValue(weight);
} else {
odb::dbDoubleProperty::create(net, gpl_weight_prop_name, weight);
}
References
- Define tunable parameters as named constants instead of using hardcoded magic numbers.
| if (!net) { | ||
| ord::OpenRoad::openRoad()->getLogger()->error( | ||
| utl::GPL, 501, "Net '{}' not found.", net_name); | ||
| } | ||
| auto* existing = odb::dbDoubleProperty::find(net, "gpl_weight"); | ||
| if (existing) { | ||
| odb::dbDoubleProperty::destroy(existing); | ||
| } |
There was a problem hiding this comment.
There are a couple of improvements that can be made here:
- Robustness: While
logger->erroris expected to terminate, the code proceeds to dereferenceneton the following lines, which will cause a crash ifnetis null and termination does not occur. It's safer to add areturnstatement after callingerror. - Maintainability: To avoid magic strings, it's a good practice to define property names like
"gpl_weight"as a constant.
The suggested code applies these improvements and uses a more concise if statement with an initializer.
if (!net) {
ord::OpenRoad::openRoad()->getLogger()->error(
utl::GPL, 501, "Net '{}' not found.", net_name);
return;
}
static const char* gpl_weight_prop_name = "gpl_weight";
if (auto* existing = odb::dbDoubleProperty::find(net, gpl_weight_prop_name)) {
odb::dbDoubleProperty::destroy(existing);
}
References
- Define tunable parameters as named constants instead of using hardcoded magic numbers.
| odb::dbDoubleProperty* wp | ||
| = odb::dbDoubleProperty::find(net->getDbNet(), "gpl_weight"); | ||
| if (wp) { | ||
| myGNet.setCustomWeight(static_cast<float>(wp->getValue())); | ||
| } |
There was a problem hiding this comment.
To improve maintainability and avoid magic strings, it's a good practice to define property names as constants. This also allows for a more concise check using an if statement with an initializer.
A similar change should be applied in src/gpl/src/replace.i where this property is set.
static const char* gpl_weight_prop_name = "gpl_weight";
if (auto* wp = odb::dbDoubleProperty::find(net->getDbNet(), gpl_weight_prop_name)) {
myGNet.setCustomWeight(static_cast<float>(wp->getValue()));
}References
- Define tunable parameters as named constants instead of using hardcoded magic numbers.
| for (auto& net : pbc_->getNets()) { | ||
| GNet myGNet(net); | ||
| // Read custom placement weight from ODB property (set by set_net_weight) | ||
| odb::dbDoubleProperty* wp |
There was a problem hiding this comment.
Would be nice to have better names for variables, for example renaming wp and myGNet. Perhaps net_property, and temp_gnet?
There was a problem hiding this comment.
Most importantly, the setting of timing-driven weights does not originally happen here. This is currently not protected by timing-driven mode being activated.
I believe this should happen at:
OpenROAD/src/gpl/src/timingBase.cpp
Line 120 in 29d97c4
Notice how we originally set weights at the following, after RSZ is executed:
OpenROAD/src/gpl/src/timingBase.cpp
Line 173 in 29d97c4
There was a problem hiding this comment.
This is an interesting new feature!
Summary
set_net_weight/unset_net_weightTCL commands for per-net custom placement weightdbDoubleProperty("gpl_weight")ondbNet— persistent acrosswrite_db/read_dbNesterovBasereads the property duringGNetconstruction via existingsetCustomWeight()Motivation
External tools (e.g., timing-driven convergence loops) need to guide global placement by annotating specific nets with higher importance. This is useful for IP-level characterization → integration PnR workflows where sensitive nets identified during standalone analysis should receive higher placement priority.
Test plan
net_weight01.tcl: 7 positive tests (set, verify ODB property, unset, multiple nets, global_placement with weights, overwrite, write_db persistence)net_weight_negative.tcl: 7 negative tests (non-existent net, zero weight, negative weight, unset non-existent, wrong arg count, non-numeric, unset without prior set).okfiles generatedRelated
🤖 Generated with Claude Code