From 3620d7a2591f2bcefe4be410bdbbf224353d53f5 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sun, 27 Jul 2025 18:12:26 -0700 Subject: [PATCH] liberty min_period timing group support resolves #275 Signed-off-by: James Cherry --- dcalc/GraphDelayCalc.cc | 31 +++++++++++++++------- graph/Graph.cc | 24 +++++++++++++++++ include/sta/Graph.hh | 5 ++++ include/sta/GraphDelayCalc.hh | 4 ++- liberty/LibertyBuilder.cc | 2 ++ liberty/LibertyReader.cc | 1 + sdf/SdfWriter.cc | 2 +- search/CheckMinPeriods.cc | 50 +++++++++++++++++++++++------------ search/CheckMinPeriods.hh | 15 ++++++----- search/CheckMinPulseWidths.hh | 4 +-- search/Sta.cc | 6 +++-- 11 files changed, 105 insertions(+), 39 deletions(-) diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 14466228..01b03938 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -1597,28 +1597,39 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge, void GraphDelayCalc::minPeriod(const Pin *pin, + const Corner *corner, // Return values. float &min_period, bool &exists) { exists = false; const MinMax *min_max = MinMax::max(); - for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) { - // Sdf annotation. - float min_period1 = 0.0; - bool exists1 = false; - graph_->periodCheckAnnotation(pin, dcalc_ap->index(), - min_period, exists); - if (exists1 - && (!exists || min_period1 < min_period)) { - min_period = min_period1; + const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); + // Sdf annotation. + float min_period1 = 0.0; + bool exists1 = false; + graph_->periodCheckAnnotation(pin, dcalc_ap->index(), + min_period, exists); + if (exists1 + && (!exists || min_period1 < min_period)) { + min_period = min_period1; + exists = true; + } + if (!exists) { + // Liberty timing group timing_type minimum_period. + Vertex *vertex = graph_->pinLoadVertex(pin); + Edge *edge; + TimingArc *arc; + graph_->minPeriodArc(vertex, RiseFall::rise(), edge, arc); + if (edge) { exists = true; + min_period = delayAsFloat(graph_->arcDelay(edge, arc, dcalc_ap->index())); } } if (!exists) { + // Liberty port min_period attribute. LibertyPort *port = network_->libertyPort(pin); if (port) { - // Liberty library. Instance *inst = network_->instance(pin); OperatingConditions *op_cond = sdc_->operatingConditions(min_max); const Pvt *pvt = inst ? sdc_->pvt(inst, min_max) : nullptr; diff --git a/graph/Graph.cc b/graph/Graph.cc index b3bb0260..fc134d29 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -871,6 +871,30 @@ Graph::minPulseWidthArc(Vertex *vertex, arc = nullptr; } +void +Graph::minPeriodArc(Vertex *vertex, + const RiseFall *rf, + // Return values. + Edge *&edge, + TimingArc *&arc) +{ + VertexOutEdgeIterator edge_iter(vertex, this); + while (edge_iter.hasNext()) { + edge = edge_iter.next(); + TimingArcSet *arc_set = edge->timingArcSet(); + if (arc_set->role() == TimingRole::period()) { + for (TimingArc *arc1 : arc_set->arcs()) { + if (arc1->fromEdge()->asRiseFall() == rf) { + arc = arc1; + return; + } + } + } + } + edge = nullptr; + arc = nullptr; +} + //////////////////////////////////////////////////////////////// void diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 34e3e122..1e173361 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -171,6 +171,11 @@ public: // Return values. Edge *&edge, TimingArc *&arc); + void minPeriodArc(Vertex *vertex, + const RiseFall *rf, + // Return values. + Edge *&edge, + TimingArc *&arc); // Sdf period check annotation. void periodCheckAnnotation(const Pin *pin, DcalcAPIndex ap_index, diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index 216ebe03..b38e6654 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -114,8 +114,10 @@ public: ArcDelayCalc *arc_delay_calc); // Precedence: // SDF annotation - // Liberty library + // Liberty port timing group timing_type minimum_period. + // Liberty port min_period attribute. void minPeriod(const Pin *pin, + const Corner *corner, // Return values. float &min_period, bool &exists); diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index e5184345..46bde91a 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -289,6 +289,8 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell, return makeMinPulseWidthArcs(cell, from_port, to_port, related_out, TimingRole::width(), attrs); case TimingType::minimum_period: + return makeMinPulseWidthArcs(cell, from_port, to_port, related_out, + TimingRole::period(), attrs); case TimingType::nochange_high_high: case TimingType::nochange_high_low: case TimingType::nochange_low_high: diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index dd730770..9f066161 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -4235,6 +4235,7 @@ LibertyReader::endTiming(LibertyGroup *group) TimingType timing_type = timing_->attrs()->timingType(); if (timing_->relatedPortNames() == nullptr && !(timing_type == TimingType::min_pulse_width + || timing_type == TimingType::minimum_period || timing_type == TimingType::min_clock_tree_path || timing_type == TimingType::max_clock_tree_path)) libWarn(1243, group, "timing group missing related_pin/related_bus_pin."); diff --git a/sdf/SdfWriter.cc b/sdf/SdfWriter.cc index 043290e4..81b64396 100644 --- a/sdf/SdfWriter.cc +++ b/sdf/SdfWriter.cc @@ -546,7 +546,7 @@ SdfWriter::writeTimingChecks(const Instance *inst, } float min_period; bool exists; - graph_delay_calc_->minPeriod(pin, min_period, exists); + graph_delay_calc_->minPeriod(pin, corner_, min_period, exists); if (exists) { ensureTimingCheckheaders(check_header, inst, inst_header); writePeriodCheck(pin, min_period); diff --git a/search/CheckMinPeriods.cc b/search/CheckMinPeriods.cc index 7e3a14c9..06358382 100644 --- a/search/CheckMinPeriods.cc +++ b/search/CheckMinPeriods.cc @@ -39,12 +39,21 @@ namespace sta { class MinPeriodCheckVisitor { public: - MinPeriodCheckVisitor() {} + MinPeriodCheckVisitor(const Corner *corner); virtual ~MinPeriodCheckVisitor() {} virtual void visit(MinPeriodCheck &check, StaState *sta) = 0; + const Corner *corner() { return corner_; } + +protected: + const Corner *corner_; }; +MinPeriodCheckVisitor::MinPeriodCheckVisitor(const Corner *corner) : + corner_(corner) +{ +} + CheckMinPeriods::CheckMinPeriods(StaState *sta) : sta_(sta) { @@ -64,7 +73,8 @@ CheckMinPeriods::clear() class MinPeriodViolatorsVisitor : public MinPeriodCheckVisitor { public: - MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks); + MinPeriodViolatorsVisitor(const Corner *corner, + MinPeriodCheckSeq &checks); virtual void visit(MinPeriodCheck &check, StaState *sta); @@ -72,7 +82,9 @@ private: MinPeriodCheckSeq &checks_; }; -MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks): +MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(const Corner *corner, + MinPeriodCheckSeq &checks): + MinPeriodCheckVisitor(corner), checks_(checks) { } @@ -86,10 +98,10 @@ MinPeriodViolatorsVisitor::visit(MinPeriodCheck &check, } MinPeriodCheckSeq & -CheckMinPeriods::violations() +CheckMinPeriods::violations(const Corner *corner) { clear(); - MinPeriodViolatorsVisitor visitor(checks_); + MinPeriodViolatorsVisitor visitor(corner, checks_); visitMinPeriodChecks(&visitor); sort(checks_, MinPeriodSlackLess(sta_)); return checks_; @@ -113,16 +125,17 @@ CheckMinPeriods::visitMinPeriodChecks(Vertex *vertex, { Search *search = sta_->search(); GraphDelayCalc *graph_dcalc = sta_->graphDelayCalc(); + const Corner *corner = visitor->corner(); Pin *pin = vertex->pin(); float min_period; bool exists; - graph_dcalc->minPeriod(pin, min_period, exists); + graph_dcalc->minPeriod(pin, corner, min_period, exists); if (exists) { const ClockSet clks = search->clocks(vertex); ClockSet::ConstIterator clk_iter(clks); while (clk_iter.hasNext()) { Clock *clk = clk_iter.next(); - MinPeriodCheck check(pin, clk); + MinPeriodCheck check(pin, clk, corner); visitor->visit(check, sta_); } } @@ -133,16 +146,17 @@ CheckMinPeriods::visitMinPeriodChecks(Vertex *vertex, class MinPeriodSlackVisitor : public MinPeriodCheckVisitor { public: - MinPeriodSlackVisitor(); - virtual void visit(MinPeriodCheck &check, - StaState *sta); + MinPeriodSlackVisitor(const Corner *corner); + void visit(MinPeriodCheck &check, + StaState *sta) override; MinPeriodCheck *minSlackCheck(); private: MinPeriodCheck *min_slack_check_; }; -MinPeriodSlackVisitor::MinPeriodSlackVisitor() : +MinPeriodSlackVisitor::MinPeriodSlackVisitor(const Corner *corner) : + MinPeriodCheckVisitor(corner), min_slack_check_(nullptr) { } @@ -167,10 +181,10 @@ MinPeriodSlackVisitor::minSlackCheck() } MinPeriodCheck * -CheckMinPeriods::minSlackCheck() +CheckMinPeriods::minSlackCheck(const Corner *corner) { clear(); - MinPeriodSlackVisitor visitor; + MinPeriodSlackVisitor visitor(corner); visitMinPeriodChecks(&visitor); MinPeriodCheck *check = visitor.minSlackCheck(); // Save check for cleanup. @@ -181,16 +195,18 @@ CheckMinPeriods::minSlackCheck() //////////////////////////////////////////////////////////////// MinPeriodCheck::MinPeriodCheck(Pin *pin, - Clock *clk) : + Clock *clk, + const Corner *corner) : pin_(pin), - clk_(clk) + clk_(clk), + corner_(corner) { } MinPeriodCheck * MinPeriodCheck::copy() { - return new MinPeriodCheck(pin_, clk_); + return new MinPeriodCheck(pin_, clk_, corner_); } float @@ -205,7 +221,7 @@ MinPeriodCheck::minPeriod(const StaState *sta) const GraphDelayCalc *graph_dcalc = sta->graphDelayCalc(); float min_period; bool exists; - graph_dcalc->minPeriod(pin_, min_period, exists); + graph_dcalc->minPeriod(pin_, corner_, min_period, exists); return min_period; } diff --git a/search/CheckMinPeriods.hh b/search/CheckMinPeriods.hh index 871cec50..bcba3218 100644 --- a/search/CheckMinPeriods.hh +++ b/search/CheckMinPeriods.hh @@ -38,12 +38,12 @@ class MinPeriodCheckVisitor; class CheckMinPeriods { public: - explicit CheckMinPeriods(StaState *sta); + CheckMinPeriods(StaState *sta); ~CheckMinPeriods(); void clear(); - MinPeriodCheckSeq &violations(); + MinPeriodCheckSeq &violations(const Corner *corner); // Min period check with the least slack. - MinPeriodCheck *minSlackCheck(); + MinPeriodCheck *minSlackCheck(const Corner *corner); protected: void visitMinPeriodChecks(MinPeriodCheckVisitor *visitor); @@ -57,7 +57,9 @@ protected: class MinPeriodCheck { public: - MinPeriodCheck(Pin *pin, Clock *clk); + MinPeriodCheck(Pin *pin, + Clock *clk, + const Corner *corner); MinPeriodCheck *copy(); Pin *pin() const { return pin_; } Clock *clk() const { return clk_; } @@ -68,17 +70,18 @@ public: private: Pin *pin_; Clock *clk_; + const Corner *corner_; }; class MinPeriodSlackLess { public: - explicit MinPeriodSlackLess(StaState *sta); + MinPeriodSlackLess(StaState *sta); bool operator()(const MinPeriodCheck *check1, const MinPeriodCheck *check2) const; private: - const StaState *sta_; + const StaState *sta_; }; } // namespace diff --git a/search/CheckMinPulseWidths.hh b/search/CheckMinPulseWidths.hh index 8c6abeac..d250cc20 100644 --- a/search/CheckMinPulseWidths.hh +++ b/search/CheckMinPulseWidths.hh @@ -38,7 +38,7 @@ class MinPulseWidthCheckVisitor; class CheckMinPulseWidths { public: - explicit CheckMinPulseWidths(StaState *sta); + CheckMinPulseWidths(StaState *sta); ~CheckMinPulseWidths(); void clear(); // Min pulse width checks for pins. @@ -96,7 +96,7 @@ protected: class MinPulseWidthSlackLess { public: - explicit MinPulseWidthSlackLess(const StaState *sta); + MinPulseWidthSlackLess(const StaState *sta); bool operator()(const MinPulseWidthCheck *check1, const MinPulseWidthCheck *check2) const; diff --git a/search/Sta.cc b/search/Sta.cc index d86434af..7aa78d38 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -5554,14 +5554,16 @@ MinPeriodCheckSeq & Sta::minPeriodViolations() { minPeriodPreamble(); - return check_min_periods_->violations(); + const Corner *corner = cmdCorner(); + return check_min_periods_->violations(corner); } MinPeriodCheck * Sta::minPeriodSlack() { minPeriodPreamble(); - return check_min_periods_->minSlackCheck(); + const Corner *corner = cmdCorner(); + return check_min_periods_->minSlackCheck(corner); } void