Skip to content
Merged
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
5 changes: 5 additions & 0 deletions src/gpl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ long during routability-driven execution, consider raising the target RC value
value is calculated based on the weight coefficients. The algorithm will stop
if the RC is not decreasing for three consecutive iterations.

With timing-driven and routability-driven placement enabled, retained timing
repairs also inflate new cells in congested areas after routability refinement
finishes. This shares the inflation budget and removes fillers to pay for added
area, without raising density or restarting routability.

Initial-placement arguments
- They begin with `-initial_place`.
- `-initial_place_max_iter`, `-initial_place_max_fanout`
Expand Down
5 changes: 5 additions & 0 deletions src/gpl/doc/TclCommands.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ global_placement
* __skip_initial_place__ : Skip the initial placement (BiCGSTAB solving) before Nesterov placement. IP improves HPWL by ~5% on large designs.
* __incremental__ : Enable the incremental global placement. Users would need to tune other parameters (e.g. init_density_penalty) with the pre-placed solutions.

When timing-driven and routability-driven placement are both enabled, retained
timing-repair cells in congested areas are inflated after routability refinement
finishes. This uses the shared inflation allowance and available fillers without
raising density or restarting routability.

## Tuning Parameters
* __bin_grid_count__ : Set bin grid's count manually. Default: Defined by internal algorithm. [64,128,256,512,..., int]
* __density__ : Set target density. Default: 0.70 [0-1, float]
Expand Down
62 changes: 62 additions & 0 deletions src/gpl/src/nesterovBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,23 @@ void GCell::setCenterLocation(int cx, int cy)
}
}

int64_t GCell::getInflationArea() const
{
if (isFiller()) {
return 0;
}
// Instance geometry carries current master dimensions, placement padding
// and pin-density extension. A move callback can make the GCell unpadded;
// it must not change this reference or turn padding into congestion area.
int64_t physical_area = insts_.front()->getArea();
if (insts_.size() > 1) {
const GCell physical(insts_);
physical_area = static_cast<int64_t>(physical.dx()) * physical.dy();
}
return std::max<int64_t>(0,
static_cast<int64_t>(dx()) * dy() - physical_area);
}

// changing size and preserve center coordinates
void GCell::setSize(int dx, int dy, GCellChange change)
{
Expand Down Expand Up @@ -2770,6 +2787,20 @@ int64_t NesterovBase::getNesterovInstsArea() const
std::round(pb_->macroInstsArea() * targetDensity_));
}

int64_t NesterovBase::getInflationArea() const
{
int64_t area = 0;
for (const auto& cell : nb_gcells_) {
if (cell->isStdInstance()) {
area += cell->getInflationArea();
} else if (cell->isMacroInstance()) {
area += static_cast<int64_t>(
std::round(cell->getInflationArea() * targetDensity_));
}
}
return area;
}

float NesterovBase::getSumPhi() const
{
return sumPhi_;
Expand Down Expand Up @@ -2919,6 +2950,37 @@ void NesterovBase::updateDensitySize()
#endif
}

void NesterovBase::updateTimingDrivenDensity()
{
updateAreas();
// Macros contribute targetDensity * macro area to the density field.
// Solve D * whitespace = std + fillers + D * macros for D.
const int64_t available_area = getWhiteSpaceArea() - pb_->macroInstsArea();
if (available_area <= 0) {
// With only macros filling the region, the density equation holds for
// the current density. Any other nonpositive-space case is unsatisfiable.
if (available_area < 0 || stdInstsArea_ != 0 || getTotalFillerArea() != 0) {
auto* block = pb_->db()->getChip()->getBlock();
log_->error(GPL,
334,
"Cannot update timing-driven density in region '{}': "
"non-macro available area is {:.3f} um^2, standard-cell area "
"is {:.3f} um^2, and filler area is {:.3f} um^2.",
pb_->getGroup() ? pb_->getGroup()->getName() : "top-level",
block->dbuAreaToMicrons(available_area),
block->dbuAreaToMicrons(stdInstsArea_),
block->dbuAreaToMicrons(getTotalFillerArea()));
}
} else {
// Preserve the placer's existing float rounding when no macros are present.
// A one-ULP target change perturbs the subsequent optimization trajectory.
setTargetDensity(static_cast<float>(stdInstsArea_ + getTotalFillerArea())
/ static_cast<float>(available_area));
}
setMovableArea(getNesterovInstsArea() + getTotalFillerArea());
updateDensitySize();
}

void NesterovBase::updateAreas()
{
// bloating can change the following :
Expand Down
14 changes: 14 additions & 0 deletions src/gpl/src/nesterovBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class GCell
void setCenterLocation(int cx, int cy);
// void setLocation(int x, int y);
void setSize(int dx, int dy, GCellChange change = GCellChange::kNone);
int64_t getInflationArea() const;
void setAreaChangeType(GCellChange change) { change_ = change; }
GCellChange changeType() const { return change_; }
void setAllLocations(int lx, int ly, int ux, int uy);
Expand Down Expand Up @@ -1082,6 +1083,13 @@ class NesterovBase

const std::vector<GCellHandle>& getGCells() const { return nb_gcells_; }

// Live instances created since the last optimizer-state update. Their
// callbacks have already built GCells; some may since have been resized.
const std::unordered_set<odb::dbInst*>& getNewInstances() const
{
return new_instances_;
}

float getSumOverflow() const { return sum_overflow_; }
float getSumOverflowUnscaled() const { return sum_overflow_unscaled_; }
float getBaseWireLengthCoef() const { return baseWireLengthCoef_; }
Expand Down Expand Up @@ -1128,9 +1136,13 @@ class NesterovBase
// update density sizes with changed dx and dy
void updateDensitySize();

// Account for retained timing repair and congestion inflation in this region.
void updateTimingDrivenDensity();

// should be separately defined.
// This is mainly used for NesterovLoop
int64_t getNesterovInstsArea() const;
int64_t getInflationArea() const;
int64_t getStdInstArea() const { return this->stdInstsArea_; }
int64_t getMacroInstArea() const { return this->macroInstsArea_; }

Expand Down Expand Up @@ -1328,6 +1340,8 @@ class NesterovBase
void setIoPins(std::unique_ptr<IoPinBase> io_pins);

private:
friend class TimingRepairIntegrationTest;

NesterovBaseVars nbVars_;
std::shared_ptr<PlacerBase> pb_;
std::shared_ptr<NesterovBaseCommon> nbc_;
Expand Down
59 changes: 44 additions & 15 deletions src/gpl/src/nesterovPlace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,11 @@ void NesterovPlace::runTimingDriven(int iter,
int nbc_total_gcells_before_td = nbc_->getGCells().size();

for (auto& nb : nbVec_) {
nb_gcells_before_td += nb->getGCells().size();
for (const auto& cell : nb->getGCells()) {
if (cell->isInstance()) {
++nb_gcells_before_td;
}
}
}

bool enable_repair_timing = npVars_.timingDrivenIterCounter
Expand All @@ -473,6 +477,15 @@ void NesterovPlace::runTimingDriven(int iter,
= tb_->executeTimingDriven(virtual_td_iter, enable_repair_timing);
// fixPointers() may have moved the GPins the IO pins point at.
getTopLevelNB()->refreshIoPins();
// is_routability_need_ stays true before/during ordinary refinement.
// Only runRoutability() clears it, after the final pass and any restore.
const bool retained_inflation = !virtual_td_iter
&& npVars_.routability_driven_mode
&& !is_routability_need_;
if (retained_inflation) {
// Inflate before initializing the new cells' optimizer/device state.
rb_->inflateNewCells();
}
// Device-side sync (no-op on the CPU path). Non-virtual iterations ran
// repair_design, whose callbacks created/destroyed/resized instances —
// the DeviceState topology must be rebuilt from the repaired host
Expand All @@ -495,7 +508,11 @@ void NesterovPlace::runTimingDriven(int iter,
= nbc_->getNewGcellsCount() - nbc_->getDeletedGcellsCount();
td_accumulated_delta_area += nbc_->getDeltaArea();
for (auto& nb : nbVec_) {
nb_gcells_after_td += nb->getGCells().size();
for (const auto& cell : nb->getGCells()) {
if (cell->isInstance()) {
++nb_gcells_after_td;
}
}
}
const int nb_total_gcells_delta = nb_gcells_after_td - nb_gcells_before_td;
if (nb_total_gcells_delta != nbc_total_gcells_delta) {
Expand Down Expand Up @@ -526,19 +543,27 @@ void NesterovPlace::runTimingDriven(int iter,
// 3. updateareas
// 4. updateDensitySize

nesterov->setTargetDensity(
static_cast<float>(nbc_->getDeltaArea()
+ nesterov->getNesterovInstsArea()
+ nesterov->getTotalFillerArea())
/ static_cast<float>(nesterov->getWhiteSpaceArea()));

nesterov->setMovableArea(nesterov->getTargetDensity()
* nesterov->getWhiteSpaceArea());
const int64_t previous_area = nesterov->getNesterovInstsArea();
if (retained_inflation) {
// New inflation needs region-local live area, not a global repair
// delta. Keep this accounting out of the ordinary placement path.
nesterov->updateTimingDrivenDensity();
} else {
nesterov->setTargetDensity(
static_cast<float>(nbc_->getDeltaArea()
+ nesterov->getNesterovInstsArea()
+ nesterov->getTotalFillerArea())
/ static_cast<float>(nesterov->getWhiteSpaceArea()));
nesterov->setMovableArea(nesterov->getTargetDensity()
* nesterov->getWhiteSpaceArea());
}
float rsz_delta_area_microns
= block->dbuAreaToMicrons(nbc_->getDeltaArea());
float rsz_delta_area_percentage
= (nbc_->getDeltaArea()
/ static_cast<float>(nesterov->getNesterovInstsArea()))
/ static_cast<float>(retained_inflation
? previous_area
: nesterov->getNesterovInstsArea()))
* 100.0f;
log_->info(
GPL,
Expand Down Expand Up @@ -571,12 +596,16 @@ void NesterovPlace::runTimingDriven(int iter,
110,
"Timing-driven: new target density: {}",
nesterov->getTargetDensity());
nbc_->resetDeltaArea();
nbc_->resetNewGcellsCount();
nesterov->updateAreas();
nesterov->updateDensitySize();
if (!retained_inflation) {
nbc_->resetDeltaArea();
nbc_->resetNewGcellsCount();
nesterov->updateAreas();
nesterov->updateDensitySize();
}
nesterov->checkConsistency();
}
nbc_->resetDeltaArea();
nbc_->resetNewGcellsCount();

refreshCurGradients();

Expand Down
2 changes: 2 additions & 0 deletions src/gpl/src/nesterovPlace.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class NesterovPlace
void destroyCbkITerm(odb::dbITerm*);

private:
friend class TimingRepairIntegrationTest;

void updateIterGraphics(int iter,
const std::string& reports_dir,
const std::string& routability_driven_dir,
Expand Down
Loading
Loading