latch dcalc with threads
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
b3b092a782
commit
65cb291233
|
|
@ -294,14 +294,14 @@ GraphDelayCalc1::delaysInvalid()
|
|||
iter_->clear();
|
||||
// No need to keep track of incremental updates any more.
|
||||
invalid_delays_.clear();
|
||||
invalid_checks_.clear();
|
||||
invalid_check_edges_.clear();
|
||||
invalid_latch_edges_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc1::delayInvalid(const Pin *pin)
|
||||
{
|
||||
if (graph_
|
||||
&& incremental_) {
|
||||
if (graph_ && incremental_) {
|
||||
if (network_->isHierarchical(pin)) {
|
||||
EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
|
|
@ -421,9 +421,13 @@ GraphDelayCalc1::findDelays(Level level)
|
|||
|
||||
// Timing checks require slews at both ends of the arc,
|
||||
// so find their delays after all slews are known.
|
||||
for (Vertex *check_vertex : invalid_checks_)
|
||||
findCheckDelays(check_vertex, arc_delay_calc_);
|
||||
invalid_checks_.clear();
|
||||
for (Edge *check_edge : invalid_check_edges_)
|
||||
findCheckEdgeDelays(check_edge, arc_delay_calc_);
|
||||
invalid_check_edges_.clear();
|
||||
|
||||
for (Edge *latch_edge : invalid_latch_edges_)
|
||||
findLatchEdgeDelays(latch_edge);
|
||||
invalid_latch_edges_.clear();
|
||||
|
||||
delays_exist_ = true;
|
||||
incremental_ = true;
|
||||
|
|
@ -880,10 +884,34 @@ GraphDelayCalc1::findVertexDelay(Vertex *vertex,
|
|||
void
|
||||
GraphDelayCalc1::enqueueTimingChecksEdges(Vertex *vertex)
|
||||
{
|
||||
if (vertex->hasChecks()
|
||||
|| vertex->isCheckClk()) {
|
||||
UniqueLock lock(check_vertices_lock_);
|
||||
invalid_checks_.insert(vertex);
|
||||
if (vertex->hasChecks()) {
|
||||
VertexInEdgeIterator edge_iter(vertex, graph_);
|
||||
UniqueLock lock(invalid_edge_lock_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
if (edge->role()->isTimingCheck())
|
||||
invalid_check_edges_.insert(edge);
|
||||
}
|
||||
}
|
||||
if (vertex->isCheckClk()) {
|
||||
VertexOutEdgeIterator edge_iter(vertex, graph_);
|
||||
UniqueLock lock(invalid_edge_lock_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
if (edge->role()->isTimingCheck())
|
||||
invalid_check_edges_.insert(edge);
|
||||
}
|
||||
}
|
||||
if (network_->isLatchData(vertex->pin())) {
|
||||
// Latch D->Q arcs have to be re-evaled if level(D) > level(E)
|
||||
// because levelization does not traverse D->Q arcs to break loops.
|
||||
VertexOutEdgeIterator edge_iter(vertex, graph_);
|
||||
UniqueLock lock(invalid_edge_lock_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
if (edge->role() == TimingRole::latchDtoQ())
|
||||
invalid_latch_edges_.insert(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -926,17 +954,23 @@ GraphDelayCalc1::findDriverDelays1(Vertex *drvr_vertex,
|
|||
initSlew(drvr_vertex);
|
||||
initWireDelays(drvr_vertex, init_load_slews);
|
||||
bool delay_changed = false;
|
||||
bool has_delays = false;
|
||||
VertexInEdgeIterator edge_iter(drvr_vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
Vertex *from_vertex = edge->from(graph_);
|
||||
// Don't let disabled edges set slews that influence downstream delays.
|
||||
if (search_pred_->searchFrom(from_vertex)
|
||||
&& search_pred_->searchThru(edge))
|
||||
&& search_pred_->searchThru(edge)
|
||||
&& !edge->role()->isLatchDtoQ()) {
|
||||
delay_changed |= findDriverEdgeDelays(drvr_cell, drvr_inst, drvr_pin,
|
||||
drvr_vertex, multi_drvr, edge,
|
||||
arc_delay_calc);
|
||||
has_delays = true;
|
||||
}
|
||||
}
|
||||
if (!has_delays)
|
||||
zeroSlewAndWireDelays(drvr_vertex);
|
||||
if (delay_changed && observer_)
|
||||
observer_->delayChangedTo(drvr_vertex);
|
||||
return delay_changed;
|
||||
|
|
@ -957,6 +991,21 @@ GraphDelayCalc1::initRootSlews(Vertex *vertex)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc1::findLatchEdgeDelays(Edge *edge)
|
||||
{
|
||||
Vertex *drvr_vertex = edge->to(graph_);
|
||||
const Pin *drvr_pin = drvr_vertex->pin();
|
||||
Instance *drvr_inst = network_->instance(drvr_pin);
|
||||
LibertyCell *drvr_cell = network_->libertyCell(drvr_inst);
|
||||
debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s",
|
||||
sdc_network_->pathName(drvr_inst));
|
||||
bool delay_changed = findDriverEdgeDelays(drvr_cell, drvr_inst, drvr_pin,
|
||||
drvr_vertex, nullptr, edge, arc_delay_calc_);
|
||||
if (delay_changed && observer_)
|
||||
observer_->delayChangedTo(drvr_vertex);
|
||||
}
|
||||
|
||||
bool
|
||||
GraphDelayCalc1::findDriverEdgeDelays(LibertyCell *drvr_cell,
|
||||
Instance *drvr_inst,
|
||||
|
|
@ -1146,6 +1195,36 @@ GraphDelayCalc1::initSlew(Vertex *vertex)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc1::zeroSlewAndWireDelays(Vertex *drvr_vertex)
|
||||
{
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
|
||||
for (auto tr : RiseFall::range()) {
|
||||
// Init drvr slew.
|
||||
if (!drvr_vertex->slewAnnotated(tr, slew_min_max)) {
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
graph_->setSlew(drvr_vertex, tr, ap_index, slew_min_max->initValue());
|
||||
}
|
||||
|
||||
// Init wire delays and slews.
|
||||
VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *wire_edge = edge_iter.next();
|
||||
if (wire_edge->isWire()) {
|
||||
Vertex *load_vertex = wire_edge->to(graph_);
|
||||
if (!graph_->wireDelayAnnotated(wire_edge, tr, ap_index))
|
||||
graph_->setWireArcDelay(wire_edge, tr, ap_index, 0.0);
|
||||
// Init load vertex slew.
|
||||
if (!load_vertex->slewAnnotated(tr, slew_min_max))
|
||||
graph_->setSlew(load_vertex, tr, ap_index, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init wire delays and load slews.
|
||||
void
|
||||
GraphDelayCalc1::initWireDelays(Vertex *drvr_vertex,
|
||||
|
|
@ -1162,13 +1241,13 @@ GraphDelayCalc1::initWireDelays(Vertex *drvr_vertex,
|
|||
Delay delay_init_value(delay_min_max->initValue());
|
||||
Slew slew_init_value(slew_min_max->initValue());
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
for (auto tr : RiseFall::range()) {
|
||||
if (!graph_->wireDelayAnnotated(wire_edge, tr, ap_index))
|
||||
graph_->setWireArcDelay(wire_edge, tr, ap_index, delay_init_value);
|
||||
for (auto rf : RiseFall::range()) {
|
||||
if (!graph_->wireDelayAnnotated(wire_edge, rf, ap_index))
|
||||
graph_->setWireArcDelay(wire_edge, rf, ap_index, delay_init_value);
|
||||
// Init load vertex slew.
|
||||
if (init_load_slews
|
||||
&& !load_vertex->slewAnnotated(tr, slew_min_max))
|
||||
graph_->setSlew(load_vertex, tr, ap_index, slew_init_value);
|
||||
&& !load_vertex->slewAnnotated(rf, slew_min_max))
|
||||
graph_->setSlew(load_vertex, rf, ap_index, slew_init_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1235,7 +1314,8 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell,
|
|||
const Slew &drvr_slew = graph_->slew(drvr_vertex, drvr_rf, ap_index);
|
||||
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
|
||||
if (delayGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax(), this)
|
||||
&& !drvr_vertex->slewAnnotated(drvr_rf, slew_min_max))
|
||||
&& !drvr_vertex->slewAnnotated(drvr_rf, slew_min_max)
|
||||
&& !edge->role()->isLatchDtoQ())
|
||||
graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
|
||||
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
|
||||
const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index);
|
||||
|
|
@ -1247,8 +1327,9 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell,
|
|||
delay_changed = true;
|
||||
graph_->setArcDelay(edge, arc, ap_index, gate_delay);
|
||||
}
|
||||
annotateLoadDelays(drvr_vertex, drvr_rf, delay_zero, true, dcalc_ap,
|
||||
arc_delay_calc);
|
||||
if (!edge->role()->isLatchDtoQ())
|
||||
annotateLoadDelays(drvr_vertex, drvr_rf, delay_zero, true, dcalc_ap,
|
||||
arc_delay_calc);
|
||||
}
|
||||
return delay_changed;
|
||||
}
|
||||
|
|
@ -1445,42 +1526,6 @@ GraphDelayCalc1::annotateLoadDelays(Vertex *drvr_vertex,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc1::findCheckDelays(Vertex *vertex,
|
||||
ArcDelayCalc *arc_delay_calc)
|
||||
{
|
||||
debugPrint(debug_, "delay_calc", 2, "find checks %s (%s)",
|
||||
vertex->name(sdc_network_),
|
||||
network_->cellName(network_->instance(vertex->pin())));
|
||||
if (vertex->hasChecks()) {
|
||||
VertexInEdgeIterator edge_iter(vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
if (edge->role()->isTimingCheck())
|
||||
findCheckEdgeDelays(edge, arc_delay_calc);
|
||||
}
|
||||
if (network_->isLatchData(vertex->pin())) {
|
||||
// Latch D->Q arcs have to be re-evaled if level(D) > level(E)
|
||||
// because levelization does not traverse D->Q arcs to break loops.
|
||||
VertexOutEdgeIterator edge_iter(vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
Vertex *to_vertex = edge->to(graph_);
|
||||
if (edge->role() == TimingRole::latchDtoQ())
|
||||
findVertexDelay(to_vertex, arc_delay_calc_, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vertex->isCheckClk()) {
|
||||
VertexOutEdgeIterator edge_iter(vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
if (edge->role()->isTimingCheck())
|
||||
findCheckEdgeDelays(edge, arc_delay_calc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
|
||||
ArcDelayCalc *arc_delay_calc)
|
||||
|
|
@ -1491,6 +1536,10 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
|
|||
const Pin *to_pin = to_vertex->pin();
|
||||
Instance *inst = network_->instance(to_pin);
|
||||
const LibertyCell *cell = network_->libertyCell(inst);
|
||||
debugPrint(debug_, "delay_calc", 2, "find check %s %s -> %s",
|
||||
sdc_network_->pathName(inst),
|
||||
network_->portName(from_vertex->pin()),
|
||||
network_->portName(to_pin));
|
||||
bool delay_changed = false;
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ protected:
|
|||
void initWireDelays(Vertex *drvr_vertex,
|
||||
bool init_load_slews);
|
||||
void initRootSlews(Vertex *vertex);
|
||||
void zeroSlewAndWireDelays(Vertex *drvr_vertex);
|
||||
void findVertexDelay(Vertex *vertex,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
bool propagate);
|
||||
|
|
@ -160,8 +161,7 @@ protected:
|
|||
bool merge,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void findCheckDelays(Vertex *vertex,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void findLatchEdgeDelays(Edge *edge);
|
||||
void findCheckEdgeDelays(Edge *edge,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void findMultiDrvrGateDelay(MultiDrvrNet *multi_drvr,
|
||||
|
|
@ -213,9 +213,12 @@ protected:
|
|||
bool delays_exist_;
|
||||
// Vertices with invalid -to delays.
|
||||
VertexSet invalid_delays_;
|
||||
// Vertices with invalid -from/-to timing checks.
|
||||
VertexSet invalid_checks_;
|
||||
std::mutex check_vertices_lock_;
|
||||
// Timing check edges with invalid delays.
|
||||
EdgeSet invalid_check_edges_;
|
||||
// Latch D->Q edges with invalid delays.
|
||||
EdgeSet invalid_latch_edges_;
|
||||
// shared by invalid_check_edges_ and invalid_latch_edges_
|
||||
std::mutex invalid_edge_lock_;
|
||||
SearchPred *search_pred_;
|
||||
SearchPred *search_non_latch_pred_;
|
||||
SearchPred *clk_pred_;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ public:
|
|||
bool isAsyncTimingCheck() const;
|
||||
bool isNonSeqTimingCheck() const { return is_non_seq_check_; }
|
||||
bool isDataCheck() const;
|
||||
bool isLatchDtoQ() const;
|
||||
const TimingRole *genericRole() const;
|
||||
const TimingRole *sdfRole() const;
|
||||
// Timing check data path min/max.
|
||||
|
|
|
|||
|
|
@ -241,6 +241,12 @@ TimingRole::isDataCheck() const
|
|||
|| this == data_check_hold_;
|
||||
}
|
||||
|
||||
bool
|
||||
TimingRole::isLatchDtoQ() const
|
||||
{
|
||||
return this == latch_d_q_;
|
||||
}
|
||||
|
||||
bool
|
||||
TimingRole::less(const TimingRole *role1,
|
||||
const TimingRole *role2)
|
||||
|
|
|
|||
Loading…
Reference in New Issue