LibertyCell::timingArcSets() range iteration

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-06-12 08:21:34 -07:00
parent bad3dae60f
commit 8c5b0fcaa5
13 changed files with 80 additions and 158 deletions

View File

@ -710,9 +710,7 @@ GraphDelayCalc1::driveCellDefaultFromPort(LibertyCell *cell,
{
LibertyPort *from_port = 0;
int from_port_index = 0;
LibertyCellTimingArcSetIterator set_iter(cell, nullptr, to_port);
while (set_iter.hasNext()) {
TimingArcSet *arc_set = set_iter.next();
for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, to_port)) {
LibertyPort *set_from_port = arc_set->from();
int set_from_port_index = findPortIndex(cell, set_from_port);
if (from_port == nullptr
@ -754,9 +752,7 @@ GraphDelayCalc1::findInputDriverDelay(LibertyCell *drvr_cell,
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
drvr_cell->name(),
rf->asString());
LibertyCellTimingArcSetIterator set_iter(drvr_cell, from_port, to_port);
while (set_iter.hasNext()) {
TimingArcSet *arc_set = set_iter.next();
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
TimingArcSetArcIterator arc_iter(arc_set);
while (arc_iter.hasNext()) {
TimingArc *arc = arc_iter.next();

View File

@ -185,9 +185,7 @@ Graph::makePortInstanceEdges(const Instance *inst,
LibertyCell *cell,
LibertyPort *from_to_port)
{
LibertyCellTimingArcSetIterator timing_iter(cell);
while (timing_iter.hasNext()) {
TimingArcSet *arc_set = timing_iter.next();
for (TimingArcSet *arc_set : cell->timingArcSets()) {
LibertyPort *from_port = arc_set->from();
LibertyPort *to_port = arc_set->to();
if ((from_to_port == nullptr

View File

@ -424,9 +424,10 @@ public:
bool isClockGateOther() const;
bool isClockGate() const;
void setClockGateType(ClockGateType type);
const TimingArcSetSeq &timingArcSets() const { return timing_arc_sets_; }
// from or to may be nullptr to wildcard.
TimingArcSetSeq *timingArcSets(const LibertyPort *from,
const LibertyPort *to) const;
const TimingArcSetSeq &timingArcSets(const LibertyPort *from,
const LibertyPort *to) const;
size_t timingArcSetCount() const;
// Find a timing arc set equivalent to key.
TimingArcSet *findTimingArcSet(TimingArcSet *key) const;
@ -583,7 +584,6 @@ private:
friend class LibertyCellPgPortIterator;
friend class LibertyPort;
friend class LibertyBuilder;
friend class LibertyCellTimingArcSetIterator;
friend class LibertyCellSequentialIterator;
};
@ -621,16 +621,6 @@ private:
LibertyPgPortMap::Iterator iter_;
};
class LibertyCellTimingArcSetIterator : public TimingArcSetSeq::ConstIterator
{
public:
LibertyCellTimingArcSetIterator(const LibertyCell *cell);
// from or to may be nullptr to wildcard.
LibertyCellTimingArcSetIterator(const LibertyCell *cell,
const LibertyPort *from,
const LibertyPort *to);
};
class LibertyCellSequentialIterator : public SequentialSeq::ConstIterator
{
public:

View File

@ -355,11 +355,9 @@ equivCellTimingArcSets(const LibertyCell *cell1,
if (cell1->timingArcSetCount() != cell2->timingArcSetCount())
return false;
else {
LibertyCellTimingArcSetIterator set_iter1(cell1);
while (set_iter1.hasNext()) {
TimingArcSet *set1 = set_iter1.next();
TimingArcSet *set2 = cell2->findTimingArcSet(set1);
if (!(set2 && TimingArcSet::equiv(set1, set2)))
for (TimingArcSet *arc_set1 : cell1->timingArcSets()) {
TimingArcSet *arc_set2 = cell2->findTimingArcSet(arc_set1);
if (!(arc_set2 && TimingArcSet::equiv(arc_set1, arc_set2)))
return false;
}
return true;

View File

@ -1353,20 +1353,26 @@ LibertyCell::makeTimingArcPortMaps()
}
}
TimingArcSetSeq *
const TimingArcSetSeq &
LibertyCell::timingArcSets(const LibertyPort *from,
const LibertyPort *to) const
{
TimingArcSetSeq *arc_sets = nullptr;
if (from && to) {
LibertyPortPair port_pair(from, to);
return port_timing_arc_set_map_.findKey(port_pair);
arc_sets = port_timing_arc_set_map_.findKey(port_pair);
}
else if (from)
return timing_arc_set_from_map_.findKey(from);
arc_sets = timing_arc_set_from_map_.findKey(from);
else if (to)
return timing_arc_set_to_map_.findKey(to);
else
return nullptr;
arc_sets = timing_arc_set_to_map_.findKey(to);
if (arc_sets)
return *arc_sets;
else {
static TimingArcSetSeq null_set;
return null_set;
}
}
TimingArcSet *
@ -1461,11 +1467,13 @@ LibertyCell::addScaledCell(OperatingConditions *op_cond,
port->addScaledPort(op_cond, scaled_port);
}
LibertyCellTimingArcSetIterator set_iter1(this);
LibertyCellTimingArcSetIterator set_iter2(scaled_cell);
while (set_iter1.hasNext() && set_iter2.hasNext()) {
TimingArcSet *arc_set1 = set_iter1.next();
TimingArcSet *arc_set2 = set_iter2.next();
const TimingArcSetSeq &arc_sets1 = this->timingArcSets();
const TimingArcSetSeq &arc_sets2 = scaled_cell->timingArcSets();
for (auto set_itr1 = arc_sets1.begin(), set_itr2 = arc_sets2.begin();
set_itr1 != arc_sets1.end() && set_itr2 != arc_sets2.end();
set_itr1++, set_itr2++) {
TimingArcSet *arc_set1 = *set_itr1;
TimingArcSet *arc_set2 = *set_itr2;
TimingArcSetArcIterator arc_iter1(arc_set1);
TimingArcSetArcIterator arc_iter2(arc_set2);
while (arc_iter1.hasNext() && arc_iter2.hasNext()) {
@ -1566,20 +1574,6 @@ LibertyCell::addOcvDerate(OcvDerate *derate)
////////////////////////////////////////////////////////////////
LibertyCellTimingArcSetIterator::LibertyCellTimingArcSetIterator(const LibertyCell *cell) :
TimingArcSetSeq::ConstIterator(&cell->timing_arc_sets_)
{
}
LibertyCellTimingArcSetIterator::LibertyCellTimingArcSetIterator(const LibertyCell *cell,
const LibertyPort *from,
const LibertyPort *to):
TimingArcSetSeq::ConstIterator(cell->timingArcSets(from, to))
{
}
////////////////////////////////////////////////////////////////
// Latch enable port/function for a latch D->Q timing arc set.
class LatchEnable
{
@ -1644,14 +1638,11 @@ LibertyCell::makeLatchEnables(Report *report,
if (en_to_q->role() == TimingRole::latchEnToQ()) {
LibertyPort *en = en_to_q->from();
LibertyPort *q = en_to_q->to();
LibertyCellTimingArcSetIterator to_iter(this, nullptr, q);
while (to_iter.hasNext()) {
TimingArcSet *d_to_q = to_iter.next();
for (TimingArcSet *d_to_q : timingArcSets(nullptr, q)) {
if (d_to_q->role() == TimingRole::latchDtoQ()) {
LibertyPort *d = d_to_q->from();
LibertyCellTimingArcSetIterator check_iter(this, en, d);
while (check_iter.hasNext()) {
TimingArcSet *setup_check = check_iter.next();
for (TimingArcSet *setup_check : timingArcSets(en, d)) {
if (setup_check->role() == TimingRole::setup()) {
LatchEnable *latch_enable = makeLatchEnable(d, en, q, d_to_q,
en_to_q,
@ -1749,16 +1740,12 @@ LibertyCell::inferLatchRoles(Debug *debug)
if (hasInferedRegTimingArcs()) {
// Hunt down potential latch D/EN/Q triples.
LatchEnableSet latch_enables;
LibertyCellTimingArcSetIterator set_iter(this);
while (set_iter.hasNext()) {
TimingArcSet *en_to_q = set_iter.next();
for (TimingArcSet *en_to_q : timingArcSets()) {
// Locate potential d->q arcs from reg clk->q arcs.
if (en_to_q->role() == TimingRole::regClkToQ()) {
LibertyPort *en = en_to_q->from();
LibertyPort *q = en_to_q->to();
LibertyCellTimingArcSetIterator to_iter(this, nullptr, q);
while (to_iter.hasNext()) {
TimingArcSet *d_to_q = to_iter.next();
for (TimingArcSet *d_to_q : timingArcSets(nullptr, q)) {
// Look for combinational d->q arcs.
TimingRole *d_to_q_role = d_to_q->role();
if ((d_to_q_role == TimingRole::combinational()
@ -1770,9 +1757,7 @@ LibertyCell::inferLatchRoles(Debug *debug)
|| d_to_q_role == TimingRole::latchDtoQ()) {
LibertyPort *d = d_to_q->from();
// Check for setup check from en -> d.
LibertyCellTimingArcSetIterator check_iter(this, en, d);
while (check_iter.hasNext()) {
TimingArcSet *setup_check = check_iter.next();
for (TimingArcSet *setup_check : timingArcSets(en, d)) {
if (setup_check->role() == TimingRole::setup()) {
makeLatchEnable(d, en, q, d_to_q, en_to_q, setup_check, debug);
d_to_q->setRole(TimingRole::latchDtoQ());
@ -2035,11 +2020,9 @@ LibertyPort::driveResistance(const RiseFall *rf,
{
float max_drive = min_max->initValue();
bool found_drive = false;
LibertyCellTimingArcSetIterator set_iter(liberty_cell_, nullptr, this);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
if (!set->role()->isTimingCheck()) {
TimingArcSetArcIterator arc_iter(set);
for (TimingArcSet *arc_set : liberty_cell_->timingArcSets(nullptr, this)) {
if (!arc_set->role()->isTimingCheck()) {
TimingArcSetArcIterator arc_iter(arc_set);
while (arc_iter.hasNext()) {
TimingArc *arc = arc_iter.next();
if (rf == nullptr
@ -2073,11 +2056,9 @@ LibertyPort::intrinsicDelay(const RiseFall *rf,
{
ArcDelay max_delay = min_max->initValue();
bool found_delay = false;
LibertyCellTimingArcSetIterator set_iter(liberty_cell_, nullptr, this);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
if (!set->role()->isTimingCheck()) {
TimingArcSetArcIterator arc_iter(set);
for (TimingArcSet *arc_set : liberty_cell_->timingArcSets(nullptr, this)) {
if (!arc_set->role()->isTimingCheck()) {
TimingArcSetArcIterator arc_iter(arc_set);
while (arc_iter.hasNext()) {
TimingArc *arc = arc_iter.next();
if (rf == nullptr

View File

@ -354,12 +354,8 @@ LibertyWriter::writePortAttrs(const LibertyPort *port)
fprintf(stream_, " max_capacitance : %s;\n",
cap_unit_->asString(limit, 3));
LibertyCellTimingArcSetIterator set_iter(port->libertyCell(),
nullptr, port);
while (set_iter.hasNext()) {
const TimingArcSet *arc_set = set_iter.next();
for (TimingArcSet *arc_set : port->libertyCell()->timingArcSets(nullptr,port))
writeTimingArcSet(arc_set);
}
}
void

View File

@ -382,11 +382,8 @@ Sdc::removeLibertyAnnotations()
LibertyPortPair *pair = from_to_iter.next();
const LibertyPort *from = pair->first;
const LibertyPort *to = pair->second;
LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
while (arc_iter.hasNext()) {
TimingArcSet *arc_set = arc_iter.next();
for (TimingArcSet *arc_set : cell->timingArcSets(from, to))
arc_set->setIsDisabledConstraint(false);
}
}
}
@ -3408,11 +3405,8 @@ Sdc::disable(LibertyCell *cell,
}
if (from && to) {
disabled_cell->setDisabledFromTo(from, to);
LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
while (arc_iter.hasNext()) {
TimingArcSet *arc_set = arc_iter.next();
for (TimingArcSet *arc_set : cell->timingArcSets(from, to))
arc_set->setIsDisabledConstraint(true);
}
}
else if (from) {
disabled_cell->setDisabledFrom(from);
@ -3437,11 +3431,8 @@ Sdc::removeDisable(LibertyCell *cell,
if (disabled_cell) {
if (from && to) {
disabled_cell->removeDisabledFromTo(from, to);
LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
while (arc_iter.hasNext()) {
TimingArcSet *arc_set = arc_iter.next();
arc_set->setIsDisabledConstraint(false);
}
for (TimingArcSet *arc_set : cell->timingArcSets(from, to))
arc_set->setIsDisabledConstraint(false);
}
else if (from) {
disabled_cell->removeDisabledFrom(from);
@ -3884,10 +3875,8 @@ Sdc::exceptionToInvalid(const Pin *pin)
LibertyPort *port = network_->libertyPort(pin);
if (port) {
LibertyCell *cell = port->libertyCell();
LibertyCellTimingArcSetIterator set_iter(cell, nullptr, port);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
TimingRole *role = set->role();
for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) {
TimingRole *role = arc_set->role();
if (role->genericRole() == TimingRole::regClkToQ())
return true;
}
@ -4050,9 +4039,7 @@ Sdc::hasLibertyChecks(const Pin *pin)
if (cell) {
LibertyPort *port = network_->libertyPort(pin);
if (port) {
LibertyCellTimingArcSetIterator timing_iter(cell, nullptr, port);
while (timing_iter.hasNext()) {
TimingArcSet *arc_set = timing_iter.next();
for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) {
if (arc_set->role()->isTimingCheck())
return true;
}

View File

@ -273,10 +273,8 @@ FindRegVisitor::findInferedSequential(LibertyCell *cell,
{
bool matches = false;
const RiseFall *clk_rf1 = clk_rf->asRiseFall();
LibertyCellTimingArcSetIterator set_iter(cell);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
TimingArcSetArcIterator arc_iter(set);
for (TimingArcSet *arc_set : cell->timingArcSets()) {
TimingArcSetArcIterator arc_iter(arc_set);
TimingArc *arc = arc_iter.next();
RiseFall *arc_clk_rf = arc->fromEdge()->asRiseFall();
bool tr_matches = (clk_rf == RiseFallBoth::riseFall()
@ -284,7 +282,7 @@ FindRegVisitor::findInferedSequential(LibertyCell *cell,
&& clk_sense == TimingSense::positive_unate)
|| (arc_clk_rf == clk_rf1->opposite()
&& clk_sense == TimingSense::negative_unate));
TimingRole *role = set->role();
TimingRole *role = arc_set->role();
if (tr_matches
&& ((role == TimingRole::regClkToQ()
&& edge_triggered)
@ -302,10 +300,8 @@ FindRegVisitor::hasTimingCheck(LibertyCell *cell,
LibertyPort *clk,
LibertyPort *d)
{
LibertyCellTimingArcSetIterator set_iter(cell, clk, d);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
TimingRole *role = set->role();
for (TimingArcSet *arc_set : cell->timingArcSets(clk, d)) {
TimingRole *role = arc_set->role();
if (role->isTimingCheck())
return true;
}
@ -541,10 +537,8 @@ FindRegClkPins::matchPin(Pin *pin)
{
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *cell = port->libertyCell();
LibertyCellTimingArcSetIterator set_iter(cell, port, nullptr);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
TimingRole *role = set->role();
for (TimingArcSet *arc_set : cell->timingArcSets(port, nullptr)) {
TimingRole *role = arc_set->role();
if (role->isTimingCheck())
return true;
}
@ -598,10 +592,8 @@ FindRegAsyncPins::matchPin(Pin *pin)
{
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *cell = port->libertyCell();
LibertyCellTimingArcSetIterator set_iter(cell, port, nullptr);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
TimingRole *role = set->role();
for (TimingArcSet *arc_set : cell->timingArcSets(port, nullptr)) {
TimingRole *role = arc_set->role();
if (role == TimingRole::regSetClr())
return true;
}
@ -647,10 +639,8 @@ FindRegOutputPins::matchPin(Pin *pin)
{
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *cell = port->libertyCell();
LibertyCellTimingArcSetIterator set_iter(cell, nullptr, port);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
TimingRole *role = set->role();
for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) {
TimingRole *role = arc_set->role();
if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ()
|| role == TimingRole::latchDtoQ())

View File

@ -489,9 +489,7 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin,
const LibertyPort *drvr_port = network_->libertyPort(drvr_pin);
if (drvr_port) {
const LibertyCell *drvr_cell = drvr_port->libertyCell();
LibertyCellTimingArcSetIterator set_iter(drvr_cell, nullptr, drvr_port);
while (set_iter.hasNext()) {
TimingArcSet *arc_set = set_iter.next();
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(nullptr, drvr_port)) {
TimingArcSetArcIterator arc_iter(arc_set);
while (arc_iter.hasNext()) {
TimingArc *drvr_arc = arc_iter.next();

View File

@ -911,9 +911,9 @@ isPositiveUnate(const LibertyCell *cell,
const LibertyPort *from,
const LibertyPort *to)
{
TimingArcSetSeq *arc_sets = cell->timingArcSets(from, to);
if (arc_sets && !arc_sets->empty()) {
TimingSense sense = (*arc_sets)[0]->sense();
const TimingArcSetSeq &arc_sets = cell->timingArcSets(from, to);
if (!arc_sets.empty()) {
TimingSense sense = arc_sets[0]->sense();
return sense == TimingSense::positive_unate
|| sense == TimingSense::non_unate;
}

View File

@ -1244,10 +1244,8 @@ isCondDisabled(Edge *edge,
LibertyCell *cell = network->libertyCell(inst);
LibertyPort *from_port = network->libertyPort(from_pin);
LibertyPort *to_port = network->libertyPort(to_pin);
LibertyCellTimingArcSetIterator cond_iter(cell, from_port, to_port);
is_disabled = false;
while (cond_iter.hasNext()) {
TimingArcSet *cond_set = cond_iter.next();
for (TimingArcSet *cond_set : cell->timingArcSets(from_port, to_port)) {
FuncExpr *cond = cond_set->cond();
if (cond && sim->evalExpr(cond, inst) == LogicValue::one) {
disable_cond = cond;

View File

@ -1268,7 +1268,7 @@ proc get_timing_arcs_objects { object_arg } {
} elseif { $libcells != {} } {
set arc_sets {}
foreach libcell $libcells {
lappend arc_sets [libcell_timing_arc_sets $libcell]
lappend arc_sets [$libcell timing_arc_sets]
}
return $arc_sets
}

View File

@ -576,6 +576,16 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
%typemap(out) const TimingArcSetSeq& {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
const TimingArcSetSeq *arc_sets = $1;
for (TimingArcSet *arc_set : *arc_sets) {
Tcl_Obj *obj = SWIG_NewInstanceObj(arc_set, SWIGTYPE_p_TimingArcSet, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) Wireload* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
@ -1238,16 +1248,6 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
%typemap(out) TimingArcSetArcIterator* {
Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibertyCellTimingArcSetIterator* {
Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) CheckErrorSeq & {
Tcl_Obj *error_list = Tcl_NewListObj(0, nullptr);
CheckErrorSeq *check_errors = $1;
@ -1649,13 +1649,6 @@ private:
~TimingArcSet();
};
class LibertyCellTimingArcSetIterator
{
private:
LibertyCellTimingArcSetIterator();
~LibertyCellTimingArcSetIterator();
};
class TimingArcSetArcIterator
{
private:
@ -5714,8 +5707,11 @@ find_liberty_ports_matching(const char *pattern,
LibertyCellPortIterator *
liberty_port_iterator() { return new LibertyCellPortIterator(self); }
LibertyCellTimingArcSetIterator *
timing_arc_set_iterator() { return new LibertyCellTimingArcSetIterator(self); }
const TimingArcSetSeq &
timing_arc_sets()
{
return self->timingArcSets();
}
} // LibertyCell methods
@ -5816,12 +5812,6 @@ full_name()
} // TimingArcSet methods
%extend LibertyCellTimingArcSetIterator {
bool has_next() { return self->hasNext(); }
TimingArcSet *next() { return self->next(); }
void finish() { delete self; }
}
%extend TimingArc {
LibertyPort *from() { return self->from(); }
LibertyPort *to() { return self->to(); }