Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/pad/src/ICeWall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,15 @@ void ICeWall::assignBump(odb::dbInst* inst,
if (iterm->getNet() != net) {
iterm->connect(net);
}

routing_map_.erase(iterm);
if (auto* prop = odb::dbStringProperty::find(iterm, kRdlRouteTargetProperty)) {
odb::dbProperty::destroy(prop);
}
if (auto* prop = odb::dbBoolProperty::find(iterm, kRdlDontRouteProperty)) {
odb::dbProperty::destroy(prop);
}

if (terminal) {
auto already_assigned = std::ranges::find_if(
routing_map_,
Expand All @@ -275,10 +284,16 @@ void ICeWall::assignBump(odb::dbInst* inst,
terminal->getNet()->getName());
}
routing_map_[iterm] = terminal;
const std::string target_name
= std::string(terminal->getInst()->getName()) + "/"
+ terminal->getMTerm()->getName();
odb::dbStringProperty::create(
iterm, kRdlRouteTargetProperty, target_name.c_str());
terminal = nullptr;
}
if (dont_route) {
routing_map_[iterm] = nullptr;
odb::dbBoolProperty::create(iterm, kRdlDontRouteProperty, true);
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/pad/src/RDLRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,18 @@ void RDLRouter::buildIntialRouteSet()
if (assigned_route->second != nullptr) {
iterm_pairs.push_back(assigned_route->second);
}
} else if (auto* dont_route
= odb::dbBoolProperty::find(iterm, kRdlDontRouteProperty);
dont_route != nullptr && dont_route->getValue()) {
// Explicit -dont_route intent is persisted on the bump terminal so it
// survives write_db/read_db.
continue;
} else if (auto* target
= odb::dbStringProperty::find(iterm, kRdlRouteTargetProperty);
target != nullptr) {
if (auto* target_iterm = block_->findITerm(target->getValue().c_str())) {
iterm_pairs.push_back(target_iterm);
}
Comment on lines +249 to +254

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When restoring the explicit routing target from the persisted string property, there are two potential correctness and robustness issues:

  1. Silent Failure on Missing Target: If the target ITerm is not found in the design (e.g., due to design changes or renaming), the routing is silently skipped because the else block is bypassed. This should be logged as a warning/error.
  2. Net Mismatch: If the restored target ITerm belongs to a different net than the bump ITerm, routing them together would create a short or net mismatch. We should perform a defensive check to ensure their nets match before adding the target to iterm_pairs.
      } else if (auto* target
                 = odb::dbStringProperty::find(iterm, kRdlRouteTargetProperty);
                 target != nullptr) {
        auto* target_iterm = block_->findITerm(target->getValue().c_str());
        if (target_iterm != nullptr) {
          if (target_iterm->getNet() == iterm->getNet()) {
            iterm_pairs.push_back(target_iterm);
          } else {
            logger_->warn(utl::PAD,
                          100,
                          "Persisted RDL routing target {} net {} does not match bump {}/{} net {}",
                          target->getValue(),
                          target_iterm->getNet() ? target_iterm->getNet()->getName() : "NULL",
                          iterm->getInst()->getName(),
                          iterm->getMTerm()->getName(),
                          iterm->getNet() ? iterm->getNet()->getName() : "NULL");
          }
        } else {
          logger_->warn(utl::PAD,
                        101,
                        "Persisted RDL routing target {} for bump {}/{} not found in design",
                        target->getValue(),
                        iterm->getInst()->getName(),
                        iterm->getMTerm()->getName());
        }
      }

} else {
for (const auto& [piterm, targets] : iterm_targets) {
if (iterm->getInst() != piterm->getInst()) {
Expand Down
3 changes: 3 additions & 0 deletions src/pad/src/RDLRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class Logger;

namespace pad {

inline constexpr char kRdlRouteTargetProperty[] = "PAD_RDL_ROUTE_TARGET";
inline constexpr char kRdlDontRouteProperty[] = "PAD_RDL_DONT_ROUTE";

struct DbNetPtrLess
{
bool operator()(const odb::dbNet* lhs, const odb::dbNet* rhs) const
Expand Down
12 changes: 12 additions & 0 deletions src/pad/test/rdl_route_assignments.reload.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2026, The OpenROAD Authors

source "helpers.tcl"

read_db [make_result_file "rdl_route_assignments.odb"]

rdl_route -layer metal10 -width 4 -spacing 4 "DVDD"

set def_file [make_result_file "rdl_route_assignments.def"]
write_def $def_file
diff_files $def_file "rdl_route_assignments.defok"
10 changes: 6 additions & 4 deletions src/pad/test/rdl_route_assignments.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,10 @@ assign_io_bump -net VDD BUMP_11_11 -dont_route
assign_io_bump -net DVDD BUMP_15_10 -terminal u_v18_16/DVDD
assign_io_bump -net DVDD BUMP_14_12 -terminal u_v18_14/DVDD

rdl_route -layer metal10 -width 4 -spacing 4 "DVDD"
write_db [make_result_file "rdl_route_assignments.odb"]

set def_file [make_result_file "rdl_route_assignments.def"]
write_def $def_file
diff_files $def_file "rdl_route_assignments.defok"
# Reload in a separate process to verify explicit -terminal/-dont_route bump
# assignments survive a database checkpoint.
puts [exec [info nameofexecutable] -no_splash -no_init -exit \
-threads [thread_count] \
[file join [file dirname [info script]] "rdl_route_assignments.reload.tcl"] 2>@1]
Loading