Skip to content
Draft
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
2 changes: 2 additions & 0 deletions src/grt/src/fastroute/include/FastRoute.h
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,8 @@ class FastRouteCore
std::string congestion_file_name_;
std::vector<odb::dbTechLayerDir> layer_directions_;
std::vector<odb::dbTechLayer*> db_layers_;
double dbu_per_micron_ = 0.0;
std::vector<float> layer_res_per_micron_;
int num_threads_;
// When false, nets_ contains borrowed pointers from a parent
// FastRouteCore (snapshot-batch workers). Workers must not outlive
Expand Down
2 changes: 2 additions & 0 deletions src/grt/src/fastroute/src/FastRoute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,8 @@ std::unique_ptr<FastRouteCore> FastRouteCore::buildSnapshotBatchWorker() const
worker->congestion_file_name_ = congestion_file_name_;
worker->layer_directions_ = layer_directions_;
worker->db_layers_ = db_layers_;
worker->dbu_per_micron_ = dbu_per_micron_;
worker->layer_res_per_micron_ = layer_res_per_micron_;
worker->en_estimate_parasitics_ = en_estimate_parasitics_;
worker->resistance_aware_ = resistance_aware_;
worker->enable_resistance_aware_ = enable_resistance_aware_;
Expand Down
30 changes: 18 additions & 12 deletions src/grt/src/fastroute/src/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,11 +519,19 @@ void FastRouteCore::fixEdgeAssignment(int& net_layer,
// Optimize performance
void FastRouteCore::preProcessTechLayers()
{
dbu_per_micron_
= db_->getChip()->getBlock()->getTech()->getDbUnitsPerMicron();
layer_res_per_micron_.assign(num_layers_, 0.0f);

for (int layer = 0; layer < num_layers_; layer++) {
odb::dbTech* tech = db_->getTech();
odb::dbTechLayer* db_layer = tech->findRoutingLayer(layer + 1);
db_layers_.emplace_back(db_layer);

// Keep layer_width as float: other rounding perturbs getWireCost() results
const float layer_width = dbuToMicrons(db_layer->getWidth());
layer_res_per_micron_[layer] = db_layer->getResistance() / layer_width;
Comment on lines +531 to +533

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.

medium

If layer_width is 0.0f (e.g., due to an invalid or uninitialized layer width in the tech file), dividing by it will result in a division-by-zero error. It is safer to guard against this by checking if layer_width is greater than zero.

Suggested change
// Keep layer_width as float: other rounding perturbs getWireCost() results
const float layer_width = dbuToMicrons(db_layer->getWidth());
layer_res_per_micron_[layer] = db_layer->getResistance() / layer_width;
// Keep layer_width as float: other rounding perturbs getWireCost() results
const float layer_width = dbuToMicrons(db_layer->getWidth());
layer_res_per_micron_[layer] = layer_width > 0.0f ? db_layer->getResistance() / layer_width : 0.0f;


// Via
db_layer = tech->findRoutingLayer(layer + 1)->getUpperLayer();
db_layers_.emplace_back(db_layer);
Expand All @@ -543,25 +551,23 @@ float FastRouteCore::getWireResistance(const int layer,
const int length,
FrNet* net)
{
odb::dbTechLayer* db_layer = getTechLayer(layer, false);
if (layer < net->getMinLayer() || layer > net->getMaxLayer()) {
return BIG_INT;
}
Comment on lines +554 to +556

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

Accessing layer_res_per_micron_[layer] without verifying that layer is within the valid bounds of the vector can lead to undefined behavior or segmentation faults. Adding bounds checking ensures safety.

Suggested change
if (layer < net->getMinLayer() || layer > net->getMaxLayer()) {
return BIG_INT;
}
if (layer < 0 || layer >= layer_res_per_micron_.size() || layer < net->getMinLayer() || layer > net->getMaxLayer()) {
return BIG_INT;
}


int width = db_layer->getWidth();
double resistance = db_layer->getResistance();
// Default-width value cached by preProcessTechLayers()
float res_ohm_per_micron = layer_res_per_micron_[layer];

// If net has NDR, get the correct width value
odb::dbTechNonDefaultRule* ndr = net->getDbNet()->getNonDefaultRule();
if (ndr != nullptr) {
odb::dbTechLayer* db_layer = getTechLayer(layer, false);
odb::dbTechLayerRule* layerRule = ndr->getLayerRule(db_layer);
width = layerRule->getWidth();
const float layer_width = dbuToMicrons(layerRule->getWidth());
res_ohm_per_micron = db_layer->getResistance() / layer_width;
}
Comment on lines 561 to 568

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

Several potential issues exist here:

  1. getTechLayer could return nullptr.
  2. ndr->getLayerRule(db_layer) can return nullptr if the NDR does not define a rule for the given layer.
  3. layer_width could be 0.0f, leading to a division-by-zero error.

Adding defensive checks for these cases prevents potential crashes and undefined behavior.

  // If net has NDR, get the correct width value
  odb::dbTechNonDefaultRule* ndr = net->getDbNet()->getNonDefaultRule();
  if (ndr != nullptr) {
    odb::dbTechLayer* db_layer = getTechLayer(layer, false);
    if (db_layer != nullptr) {
      odb::dbTechLayerRule* layerRule = ndr->getLayerRule(db_layer);
      if (layerRule != nullptr) {
        const float layer_width = dbuToMicrons(layerRule->getWidth());
        if (layer_width > 0.0f) {
          res_ohm_per_micron = db_layer->getResistance() / layer_width;
        }
      }
    }
  }


const float layer_width = dbuToMicrons(width);
const float res_ohm_per_micron = resistance / layer_width;
float final_resistance = res_ohm_per_micron * dbuToMicrons(length);

if (layer < net->getMinLayer() || layer > net->getMaxLayer()) {
return BIG_INT;
}
const float final_resistance = res_ohm_per_micron * dbuToMicrons(length);

return final_resistance;
}
Expand Down Expand Up @@ -2808,7 +2814,7 @@ odb::Rect FastRouteCore::globalRoutingToBox(const GSegment& route)

double FastRouteCore::dbuToMicrons(const int dbu)
{
return db_->getChip()->getBlock()->dbuToMicrons(dbu);
return dbu / dbu_per_micron_;
}
Comment on lines 2815 to 2818

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.

medium

If dbu_per_micron_ is 0.0 (e.g., if dbuToMicrons is called before preProcessTechLayers initializes it, or if the database tech units are uninitialized), this will result in a division-by-zero error. Falling back to the original database-level implementation when dbu_per_micron_ is 0.0 provides a safe and robust fallback.

double FastRouteCore::dbuToMicrons(const int dbu)
{
  if (dbu_per_micron_ == 0.0) {
    return db_->getChip()->getBlock()->dbuToMicrons(dbu);
  }
  return dbu / dbu_per_micron_;
}


void FastRouteCore::saveCongestion(const int iter)
Expand Down
Loading