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
|
void
|
||||||
GraphDelayCalc::minPeriod(const Pin *pin,
|
GraphDelayCalc::minPeriod(const Pin *pin,
|
||||||
|
const Corner *corner,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &min_period,
|
float &min_period,
|
||||||
bool &exists)
|
bool &exists)
|
||||||
{
|
{
|
||||||
exists = false;
|
exists = false;
|
||||||
const MinMax *min_max = MinMax::max();
|
const MinMax *min_max = MinMax::max();
|
||||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||||
// Sdf annotation.
|
// Sdf annotation.
|
||||||
float min_period1 = 0.0;
|
float min_period1 = 0.0;
|
||||||
bool exists1 = false;
|
bool exists1 = false;
|
||||||
graph_->periodCheckAnnotation(pin, dcalc_ap->index(),
|
graph_->periodCheckAnnotation(pin, dcalc_ap->index(),
|
||||||
min_period, exists);
|
min_period, exists);
|
||||||
if (exists1
|
if (exists1
|
||||||
&& (!exists || min_period1 < min_period)) {
|
&& (!exists || min_period1 < min_period)) {
|
||||||
min_period = min_period1;
|
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;
|
exists = true;
|
||||||
|
min_period = delayAsFloat(graph_->arcDelay(edge, arc, dcalc_ap->index()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
|
// Liberty port min_period attribute.
|
||||||
LibertyPort *port = network_->libertyPort(pin);
|
LibertyPort *port = network_->libertyPort(pin);
|
||||||
if (port) {
|
if (port) {
|
||||||
// Liberty library.
|
|
||||||
Instance *inst = network_->instance(pin);
|
Instance *inst = network_->instance(pin);
|
||||||
OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
|
OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
|
||||||
const Pvt *pvt = inst ? sdc_->pvt(inst, min_max) : nullptr;
|
const Pvt *pvt = inst ? sdc_->pvt(inst, min_max) : nullptr;
|
||||||
|
|
|
||||||
|
|
@ -871,6 +871,30 @@ Graph::minPulseWidthArc(Vertex *vertex,
|
||||||
arc = nullptr;
|
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
|
void
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,11 @@ public:
|
||||||
// Return values.
|
// Return values.
|
||||||
Edge *&edge,
|
Edge *&edge,
|
||||||
TimingArc *&arc);
|
TimingArc *&arc);
|
||||||
|
void minPeriodArc(Vertex *vertex,
|
||||||
|
const RiseFall *rf,
|
||||||
|
// Return values.
|
||||||
|
Edge *&edge,
|
||||||
|
TimingArc *&arc);
|
||||||
// Sdf period check annotation.
|
// Sdf period check annotation.
|
||||||
void periodCheckAnnotation(const Pin *pin,
|
void periodCheckAnnotation(const Pin *pin,
|
||||||
DcalcAPIndex ap_index,
|
DcalcAPIndex ap_index,
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,10 @@ public:
|
||||||
ArcDelayCalc *arc_delay_calc);
|
ArcDelayCalc *arc_delay_calc);
|
||||||
// Precedence:
|
// Precedence:
|
||||||
// SDF annotation
|
// SDF annotation
|
||||||
// Liberty library
|
// Liberty port timing group timing_type minimum_period.
|
||||||
|
// Liberty port min_period attribute.
|
||||||
void minPeriod(const Pin *pin,
|
void minPeriod(const Pin *pin,
|
||||||
|
const Corner *corner,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &min_period,
|
float &min_period,
|
||||||
bool &exists);
|
bool &exists);
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,8 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell,
|
||||||
return makeMinPulseWidthArcs(cell, from_port, to_port, related_out,
|
return makeMinPulseWidthArcs(cell, from_port, to_port, related_out,
|
||||||
TimingRole::width(), attrs);
|
TimingRole::width(), attrs);
|
||||||
case TimingType::minimum_period:
|
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_high:
|
||||||
case TimingType::nochange_high_low:
|
case TimingType::nochange_high_low:
|
||||||
case TimingType::nochange_low_high:
|
case TimingType::nochange_low_high:
|
||||||
|
|
|
||||||
|
|
@ -4235,6 +4235,7 @@ LibertyReader::endTiming(LibertyGroup *group)
|
||||||
TimingType timing_type = timing_->attrs()->timingType();
|
TimingType timing_type = timing_->attrs()->timingType();
|
||||||
if (timing_->relatedPortNames() == nullptr
|
if (timing_->relatedPortNames() == nullptr
|
||||||
&& !(timing_type == TimingType::min_pulse_width
|
&& !(timing_type == TimingType::min_pulse_width
|
||||||
|
|| timing_type == TimingType::minimum_period
|
||||||
|| timing_type == TimingType::min_clock_tree_path
|
|| timing_type == TimingType::min_clock_tree_path
|
||||||
|| timing_type == TimingType::max_clock_tree_path))
|
|| timing_type == TimingType::max_clock_tree_path))
|
||||||
libWarn(1243, group, "timing group missing related_pin/related_bus_pin.");
|
libWarn(1243, group, "timing group missing related_pin/related_bus_pin.");
|
||||||
|
|
|
||||||
|
|
@ -546,7 +546,7 @@ SdfWriter::writeTimingChecks(const Instance *inst,
|
||||||
}
|
}
|
||||||
float min_period;
|
float min_period;
|
||||||
bool exists;
|
bool exists;
|
||||||
graph_delay_calc_->minPeriod(pin, min_period, exists);
|
graph_delay_calc_->minPeriod(pin, corner_, min_period, exists);
|
||||||
if (exists) {
|
if (exists) {
|
||||||
ensureTimingCheckheaders(check_header, inst, inst_header);
|
ensureTimingCheckheaders(check_header, inst, inst_header);
|
||||||
writePeriodCheck(pin, min_period);
|
writePeriodCheck(pin, min_period);
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,21 @@ namespace sta {
|
||||||
class MinPeriodCheckVisitor
|
class MinPeriodCheckVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MinPeriodCheckVisitor() {}
|
MinPeriodCheckVisitor(const Corner *corner);
|
||||||
virtual ~MinPeriodCheckVisitor() {}
|
virtual ~MinPeriodCheckVisitor() {}
|
||||||
virtual void visit(MinPeriodCheck &check,
|
virtual void visit(MinPeriodCheck &check,
|
||||||
StaState *sta) = 0;
|
StaState *sta) = 0;
|
||||||
|
const Corner *corner() { return corner_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const Corner *corner_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MinPeriodCheckVisitor::MinPeriodCheckVisitor(const Corner *corner) :
|
||||||
|
corner_(corner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CheckMinPeriods::CheckMinPeriods(StaState *sta) :
|
CheckMinPeriods::CheckMinPeriods(StaState *sta) :
|
||||||
sta_(sta)
|
sta_(sta)
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +73,8 @@ CheckMinPeriods::clear()
|
||||||
class MinPeriodViolatorsVisitor : public MinPeriodCheckVisitor
|
class MinPeriodViolatorsVisitor : public MinPeriodCheckVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks);
|
MinPeriodViolatorsVisitor(const Corner *corner,
|
||||||
|
MinPeriodCheckSeq &checks);
|
||||||
virtual void visit(MinPeriodCheck &check,
|
virtual void visit(MinPeriodCheck &check,
|
||||||
StaState *sta);
|
StaState *sta);
|
||||||
|
|
||||||
|
|
@ -72,7 +82,9 @@ private:
|
||||||
MinPeriodCheckSeq &checks_;
|
MinPeriodCheckSeq &checks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks):
|
MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(const Corner *corner,
|
||||||
|
MinPeriodCheckSeq &checks):
|
||||||
|
MinPeriodCheckVisitor(corner),
|
||||||
checks_(checks)
|
checks_(checks)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -86,10 +98,10 @@ MinPeriodViolatorsVisitor::visit(MinPeriodCheck &check,
|
||||||
}
|
}
|
||||||
|
|
||||||
MinPeriodCheckSeq &
|
MinPeriodCheckSeq &
|
||||||
CheckMinPeriods::violations()
|
CheckMinPeriods::violations(const Corner *corner)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
MinPeriodViolatorsVisitor visitor(checks_);
|
MinPeriodViolatorsVisitor visitor(corner, checks_);
|
||||||
visitMinPeriodChecks(&visitor);
|
visitMinPeriodChecks(&visitor);
|
||||||
sort(checks_, MinPeriodSlackLess(sta_));
|
sort(checks_, MinPeriodSlackLess(sta_));
|
||||||
return checks_;
|
return checks_;
|
||||||
|
|
@ -113,16 +125,17 @@ CheckMinPeriods::visitMinPeriodChecks(Vertex *vertex,
|
||||||
{
|
{
|
||||||
Search *search = sta_->search();
|
Search *search = sta_->search();
|
||||||
GraphDelayCalc *graph_dcalc = sta_->graphDelayCalc();
|
GraphDelayCalc *graph_dcalc = sta_->graphDelayCalc();
|
||||||
|
const Corner *corner = visitor->corner();
|
||||||
Pin *pin = vertex->pin();
|
Pin *pin = vertex->pin();
|
||||||
float min_period;
|
float min_period;
|
||||||
bool exists;
|
bool exists;
|
||||||
graph_dcalc->minPeriod(pin, min_period, exists);
|
graph_dcalc->minPeriod(pin, corner, min_period, exists);
|
||||||
if (exists) {
|
if (exists) {
|
||||||
const ClockSet clks = search->clocks(vertex);
|
const ClockSet clks = search->clocks(vertex);
|
||||||
ClockSet::ConstIterator clk_iter(clks);
|
ClockSet::ConstIterator clk_iter(clks);
|
||||||
while (clk_iter.hasNext()) {
|
while (clk_iter.hasNext()) {
|
||||||
Clock *clk = clk_iter.next();
|
Clock *clk = clk_iter.next();
|
||||||
MinPeriodCheck check(pin, clk);
|
MinPeriodCheck check(pin, clk, corner);
|
||||||
visitor->visit(check, sta_);
|
visitor->visit(check, sta_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,16 +146,17 @@ CheckMinPeriods::visitMinPeriodChecks(Vertex *vertex,
|
||||||
class MinPeriodSlackVisitor : public MinPeriodCheckVisitor
|
class MinPeriodSlackVisitor : public MinPeriodCheckVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MinPeriodSlackVisitor();
|
MinPeriodSlackVisitor(const Corner *corner);
|
||||||
virtual void visit(MinPeriodCheck &check,
|
void visit(MinPeriodCheck &check,
|
||||||
StaState *sta);
|
StaState *sta) override;
|
||||||
MinPeriodCheck *minSlackCheck();
|
MinPeriodCheck *minSlackCheck();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MinPeriodCheck *min_slack_check_;
|
MinPeriodCheck *min_slack_check_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MinPeriodSlackVisitor::MinPeriodSlackVisitor() :
|
MinPeriodSlackVisitor::MinPeriodSlackVisitor(const Corner *corner) :
|
||||||
|
MinPeriodCheckVisitor(corner),
|
||||||
min_slack_check_(nullptr)
|
min_slack_check_(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -167,10 +181,10 @@ MinPeriodSlackVisitor::minSlackCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
MinPeriodCheck *
|
MinPeriodCheck *
|
||||||
CheckMinPeriods::minSlackCheck()
|
CheckMinPeriods::minSlackCheck(const Corner *corner)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
MinPeriodSlackVisitor visitor;
|
MinPeriodSlackVisitor visitor(corner);
|
||||||
visitMinPeriodChecks(&visitor);
|
visitMinPeriodChecks(&visitor);
|
||||||
MinPeriodCheck *check = visitor.minSlackCheck();
|
MinPeriodCheck *check = visitor.minSlackCheck();
|
||||||
// Save check for cleanup.
|
// Save check for cleanup.
|
||||||
|
|
@ -181,16 +195,18 @@ CheckMinPeriods::minSlackCheck()
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MinPeriodCheck::MinPeriodCheck(Pin *pin,
|
MinPeriodCheck::MinPeriodCheck(Pin *pin,
|
||||||
Clock *clk) :
|
Clock *clk,
|
||||||
|
const Corner *corner) :
|
||||||
pin_(pin),
|
pin_(pin),
|
||||||
clk_(clk)
|
clk_(clk),
|
||||||
|
corner_(corner)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MinPeriodCheck *
|
MinPeriodCheck *
|
||||||
MinPeriodCheck::copy()
|
MinPeriodCheck::copy()
|
||||||
{
|
{
|
||||||
return new MinPeriodCheck(pin_, clk_);
|
return new MinPeriodCheck(pin_, clk_, corner_);
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
|
|
@ -205,7 +221,7 @@ MinPeriodCheck::minPeriod(const StaState *sta) const
|
||||||
GraphDelayCalc *graph_dcalc = sta->graphDelayCalc();
|
GraphDelayCalc *graph_dcalc = sta->graphDelayCalc();
|
||||||
float min_period;
|
float min_period;
|
||||||
bool exists;
|
bool exists;
|
||||||
graph_dcalc->minPeriod(pin_, min_period, exists);
|
graph_dcalc->minPeriod(pin_, corner_, min_period, exists);
|
||||||
return min_period;
|
return min_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ class MinPeriodCheckVisitor;
|
||||||
class CheckMinPeriods
|
class CheckMinPeriods
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CheckMinPeriods(StaState *sta);
|
CheckMinPeriods(StaState *sta);
|
||||||
~CheckMinPeriods();
|
~CheckMinPeriods();
|
||||||
void clear();
|
void clear();
|
||||||
MinPeriodCheckSeq &violations();
|
MinPeriodCheckSeq &violations(const Corner *corner);
|
||||||
// Min period check with the least slack.
|
// Min period check with the least slack.
|
||||||
MinPeriodCheck *minSlackCheck();
|
MinPeriodCheck *minSlackCheck(const Corner *corner);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void visitMinPeriodChecks(MinPeriodCheckVisitor *visitor);
|
void visitMinPeriodChecks(MinPeriodCheckVisitor *visitor);
|
||||||
|
|
@ -57,7 +57,9 @@ protected:
|
||||||
class MinPeriodCheck
|
class MinPeriodCheck
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MinPeriodCheck(Pin *pin, Clock *clk);
|
MinPeriodCheck(Pin *pin,
|
||||||
|
Clock *clk,
|
||||||
|
const Corner *corner);
|
||||||
MinPeriodCheck *copy();
|
MinPeriodCheck *copy();
|
||||||
Pin *pin() const { return pin_; }
|
Pin *pin() const { return pin_; }
|
||||||
Clock *clk() const { return clk_; }
|
Clock *clk() const { return clk_; }
|
||||||
|
|
@ -68,17 +70,18 @@ public:
|
||||||
private:
|
private:
|
||||||
Pin *pin_;
|
Pin *pin_;
|
||||||
Clock *clk_;
|
Clock *clk_;
|
||||||
|
const Corner *corner_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MinPeriodSlackLess
|
class MinPeriodSlackLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MinPeriodSlackLess(StaState *sta);
|
MinPeriodSlackLess(StaState *sta);
|
||||||
bool operator()(const MinPeriodCheck *check1,
|
bool operator()(const MinPeriodCheck *check1,
|
||||||
const MinPeriodCheck *check2) const;
|
const MinPeriodCheck *check2) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const StaState *sta_;
|
const StaState *sta_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class MinPulseWidthCheckVisitor;
|
||||||
class CheckMinPulseWidths
|
class CheckMinPulseWidths
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CheckMinPulseWidths(StaState *sta);
|
CheckMinPulseWidths(StaState *sta);
|
||||||
~CheckMinPulseWidths();
|
~CheckMinPulseWidths();
|
||||||
void clear();
|
void clear();
|
||||||
// Min pulse width checks for pins.
|
// Min pulse width checks for pins.
|
||||||
|
|
@ -96,7 +96,7 @@ protected:
|
||||||
class MinPulseWidthSlackLess
|
class MinPulseWidthSlackLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MinPulseWidthSlackLess(const StaState *sta);
|
MinPulseWidthSlackLess(const StaState *sta);
|
||||||
bool operator()(const MinPulseWidthCheck *check1,
|
bool operator()(const MinPulseWidthCheck *check1,
|
||||||
const MinPulseWidthCheck *check2) const;
|
const MinPulseWidthCheck *check2) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5554,14 +5554,16 @@ MinPeriodCheckSeq &
|
||||||
Sta::minPeriodViolations()
|
Sta::minPeriodViolations()
|
||||||
{
|
{
|
||||||
minPeriodPreamble();
|
minPeriodPreamble();
|
||||||
return check_min_periods_->violations();
|
const Corner *corner = cmdCorner();
|
||||||
|
return check_min_periods_->violations(corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
MinPeriodCheck *
|
MinPeriodCheck *
|
||||||
Sta::minPeriodSlack()
|
Sta::minPeriodSlack()
|
||||||
{
|
{
|
||||||
minPeriodPreamble();
|
minPeriodPreamble();
|
||||||
return check_min_periods_->minSlackCheck();
|
const Corner *corner = cmdCorner();
|
||||||
|
return check_min_periods_->minSlackCheck(corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue