liberty min_period timing group support resolves #275
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
253cca73ff
commit
3620d7a259
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue