issue44 liberty pos/neg latches
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
2c4b81d0f4
commit
3ba6f0e527
|
|
@ -74,6 +74,7 @@ typedef Map<const OperatingConditions*, LibertyPort*> ScaledPortMap;
|
||||||
typedef Map<const char *, ModeDef*, CharPtrLess> ModeDefMap;
|
typedef Map<const char *, ModeDef*, CharPtrLess> ModeDefMap;
|
||||||
typedef Map<const char *, ModeValueDef*, CharPtrLess> ModeValueMap;
|
typedef Map<const char *, ModeValueDef*, CharPtrLess> ModeValueMap;
|
||||||
typedef Map<TimingArcSet*, LatchEnable*> LatchEnableMap;
|
typedef Map<TimingArcSet*, LatchEnable*> LatchEnableMap;
|
||||||
|
typedef Vector<LatchEnable*> LatchEnableSeq;
|
||||||
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
|
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
|
||||||
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
|
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
|
||||||
typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap;
|
typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap;
|
||||||
|
|
@ -476,8 +477,8 @@ public:
|
||||||
// Return values.
|
// Return values.
|
||||||
LibertyPort *&enable_port,
|
LibertyPort *&enable_port,
|
||||||
FuncExpr *&enable_func,
|
FuncExpr *&enable_func,
|
||||||
RiseFall *&enable_rf) const;
|
const RiseFall *&enable_rf) const;
|
||||||
RiseFall *latchCheckEnableEdge(TimingArcSet *check_set);
|
const RiseFall *latchCheckEnableEdge(TimingArcSet *check_set);
|
||||||
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
||||||
LibertyCell *cornerCell(const Corner *corner,
|
LibertyCell *cornerCell(const Corner *corner,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
|
|
@ -539,18 +540,26 @@ protected:
|
||||||
void setLibertyLibrary(LibertyLibrary *library);
|
void setLibertyLibrary(LibertyLibrary *library);
|
||||||
void makeLatchEnables(Report *report,
|
void makeLatchEnables(Report *report,
|
||||||
Debug *debug);
|
Debug *debug);
|
||||||
FuncExpr *findLatchEnableFunc(LibertyPort *data,
|
FuncExpr *findLatchEnableFunc(const LibertyPort *d,
|
||||||
LibertyPort *enable) const;
|
const LibertyPort *en,
|
||||||
|
const RiseFall *en_rf) const;
|
||||||
LatchEnable *makeLatchEnable(LibertyPort *d,
|
LatchEnable *makeLatchEnable(LibertyPort *d,
|
||||||
LibertyPort *en,
|
LibertyPort *en,
|
||||||
|
const RiseFall *en_rf,
|
||||||
LibertyPort *q,
|
LibertyPort *q,
|
||||||
TimingArcSet *d_to_q,
|
TimingArcSet *d_to_q,
|
||||||
TimingArcSet *en_to_q,
|
TimingArcSet *en_to_q,
|
||||||
TimingArcSet *setup_check,
|
TimingArcSet *setup_check,
|
||||||
Debug *debug);
|
Debug *debug);
|
||||||
|
TimingArcSet *findLatchSetup(const LibertyPort *d,
|
||||||
|
const LibertyPort *en,
|
||||||
|
const RiseFall *en_rf,
|
||||||
|
const LibertyPort *q,
|
||||||
|
Report *report);
|
||||||
void findDefaultCondArcs();
|
void findDefaultCondArcs();
|
||||||
void translatePresetClrCheckRoles();
|
void translatePresetClrCheckRoles();
|
||||||
void inferLatchRoles(Debug *debug);
|
void inferLatchRoles(Report *report,
|
||||||
|
Debug *debug);
|
||||||
void deleteInternalPowerAttrs();
|
void deleteInternalPowerAttrs();
|
||||||
void makeTimingArcMap(Report *report);
|
void makeTimingArcMap(Report *report);
|
||||||
void makeTimingArcPortMaps();
|
void makeTimingArcPortMaps();
|
||||||
|
|
@ -596,6 +605,7 @@ protected:
|
||||||
LatchEnableMap latch_d_to_q_map_;
|
LatchEnableMap latch_d_to_q_map_;
|
||||||
// Latch EN->D setup to LatchEnable.
|
// Latch EN->D setup to LatchEnable.
|
||||||
LatchEnableMap latch_check_map_;
|
LatchEnableMap latch_check_map_;
|
||||||
|
LatchEnableSeq latch_enables_;
|
||||||
// Ports that have latch D->Q timing arc sets from them.
|
// Ports that have latch D->Q timing arc sets from them.
|
||||||
LibertyPortSet latch_data_ports_;
|
LibertyPortSet latch_data_ports_;
|
||||||
float ocv_arc_depth_;
|
float ocv_arc_depth_;
|
||||||
|
|
|
||||||
|
|
@ -950,7 +950,7 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
|
||||||
LibertyCell::~LibertyCell()
|
LibertyCell::~LibertyCell()
|
||||||
{
|
{
|
||||||
mode_defs_.deleteContents();
|
mode_defs_.deleteContents();
|
||||||
latch_d_to_q_map_.deleteContents();
|
latch_enables_.deleteContents();
|
||||||
|
|
||||||
timing_arc_sets_.deleteContents();
|
timing_arc_sets_.deleteContents();
|
||||||
port_timing_arc_set_map_.deleteContents();
|
port_timing_arc_set_map_.deleteContents();
|
||||||
|
|
@ -1306,7 +1306,7 @@ LibertyCell::finish(bool infer_latches,
|
||||||
findDefaultCondArcs();
|
findDefaultCondArcs();
|
||||||
makeLatchEnables(report, debug);
|
makeLatchEnables(report, debug);
|
||||||
if (infer_latches)
|
if (infer_latches)
|
||||||
inferLatchRoles(debug);
|
inferLatchRoles(report, debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1675,7 +1675,7 @@ class LatchEnable
|
||||||
public:
|
public:
|
||||||
LatchEnable(LibertyPort *data,
|
LatchEnable(LibertyPort *data,
|
||||||
LibertyPort *enable,
|
LibertyPort *enable,
|
||||||
RiseFall *enable_edge,
|
const RiseFall *enable_edge,
|
||||||
FuncExpr *enable_func,
|
FuncExpr *enable_func,
|
||||||
LibertyPort *output,
|
LibertyPort *output,
|
||||||
TimingArcSet *d_to_q,
|
TimingArcSet *d_to_q,
|
||||||
|
|
@ -1685,7 +1685,7 @@ public:
|
||||||
LibertyPort *output() const { return output_; }
|
LibertyPort *output() const { return output_; }
|
||||||
LibertyPort *enable() const { return enable_; }
|
LibertyPort *enable() const { return enable_; }
|
||||||
FuncExpr *enableFunc() const { return enable_func_; }
|
FuncExpr *enableFunc() const { return enable_func_; }
|
||||||
RiseFall *enableEdge() const { return enable_edge_; }
|
const RiseFall *enableEdge() const { return enable_edge_; }
|
||||||
TimingArcSet *dToQ() const { return d_to_q_; }
|
TimingArcSet *dToQ() const { return d_to_q_; }
|
||||||
TimingArcSet *enToQ() const { return en_to_q_; }
|
TimingArcSet *enToQ() const { return en_to_q_; }
|
||||||
TimingArcSet *setupCheck() const { return setup_check_; }
|
TimingArcSet *setupCheck() const { return setup_check_; }
|
||||||
|
|
@ -1693,7 +1693,7 @@ public:
|
||||||
private:
|
private:
|
||||||
LibertyPort *data_;
|
LibertyPort *data_;
|
||||||
LibertyPort *enable_;
|
LibertyPort *enable_;
|
||||||
RiseFall *enable_edge_;
|
const RiseFall *enable_edge_;
|
||||||
FuncExpr *enable_func_;
|
FuncExpr *enable_func_;
|
||||||
LibertyPort *output_;
|
LibertyPort *output_;
|
||||||
TimingArcSet *d_to_q_;
|
TimingArcSet *d_to_q_;
|
||||||
|
|
@ -1703,7 +1703,7 @@ private:
|
||||||
|
|
||||||
LatchEnable::LatchEnable(LibertyPort *data,
|
LatchEnable::LatchEnable(LibertyPort *data,
|
||||||
LibertyPort *enable,
|
LibertyPort *enable,
|
||||||
RiseFall *enable_edge,
|
const RiseFall *enable_edge,
|
||||||
FuncExpr *enable_func,
|
FuncExpr *enable_func,
|
||||||
LibertyPort *output,
|
LibertyPort *output,
|
||||||
TimingArcSet *d_to_q,
|
TimingArcSet *d_to_q,
|
||||||
|
|
@ -1736,25 +1736,13 @@ LibertyCell::makeLatchEnables(Report *report,
|
||||||
for (TimingArcSet *d_to_q : timingArcSets(nullptr, q)) {
|
for (TimingArcSet *d_to_q : timingArcSets(nullptr, q)) {
|
||||||
if (d_to_q->role() == TimingRole::latchDtoQ()) {
|
if (d_to_q->role() == TimingRole::latchDtoQ()) {
|
||||||
LibertyPort *d = d_to_q->from();
|
LibertyPort *d = d_to_q->from();
|
||||||
for (TimingArcSet *setup_check : timingArcSets(en, d)) {
|
const RiseFall *en_rf = en_to_q->isRisingFallingEdge();
|
||||||
if (setup_check->role() == TimingRole::setup()) {
|
if (en_rf) {
|
||||||
LatchEnable *latch_enable = makeLatchEnable(d, en, q, d_to_q,
|
TimingArcSet *setup_check = findLatchSetup(d, en, en_rf, q, report);
|
||||||
|
LatchEnable *latch_enable = makeLatchEnable(d, en, en_rf, q, d_to_q,
|
||||||
en_to_q,
|
en_to_q,
|
||||||
setup_check,
|
setup_check,
|
||||||
debug);
|
debug);
|
||||||
for (TimingArc *check_arc : setup_check->arcs()) {
|
|
||||||
RiseFall *en_rf = latch_enable->enableEdge();
|
|
||||||
RiseFall *check_rf = check_arc->fromEdge()->asRiseFall();
|
|
||||||
if (check_rf == en_rf)
|
|
||||||
report->warn(1113, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check.",
|
|
||||||
library_->name(),
|
|
||||||
name_,
|
|
||||||
en->name(),
|
|
||||||
q->name(),
|
|
||||||
en_rf == RiseFall::rise()?"rising":"falling",
|
|
||||||
en->name(),
|
|
||||||
d->name(),
|
|
||||||
check_rf==RiseFall::rise()?"rising":"falling");
|
|
||||||
FuncExpr *en_func = latch_enable->enableFunc();
|
FuncExpr *en_func = latch_enable->enableFunc();
|
||||||
if (en_func) {
|
if (en_func) {
|
||||||
TimingSense en_sense = en_func->portTimingSense(en);
|
TimingSense en_sense = en_func->portTimingSense(en);
|
||||||
|
|
@ -1782,50 +1770,99 @@ LibertyCell::makeLatchEnables(Report *report,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimingArcSet *
|
||||||
|
LibertyCell::findLatchSetup(const LibertyPort *d,
|
||||||
|
const LibertyPort *en,
|
||||||
|
const RiseFall *en_rf,
|
||||||
|
const LibertyPort *q,
|
||||||
|
Report *report)
|
||||||
|
{
|
||||||
|
TimingArcSetSeq en_d_arcs = timingArcSets(en, d);
|
||||||
|
// First search for setup checks with the correct clock edge.
|
||||||
|
for (TimingArcSet *arc_set : en_d_arcs) {
|
||||||
|
if (arc_set->role() == TimingRole::setup()) {
|
||||||
|
for (TimingArc *arc : arc_set->arcs()) {
|
||||||
|
const RiseFall *from_rf = arc->fromEdge()->asRiseFall();
|
||||||
|
if (from_rf == en_rf->opposite())
|
||||||
|
return arc_set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// Then search for setup checks with the opposite clock edge.
|
||||||
|
for (TimingArcSet *arc_set : en_d_arcs) {
|
||||||
|
if (arc_set->role() == TimingRole::setup()) {
|
||||||
|
for (TimingArc *arc : arc_set->arcs()) {
|
||||||
|
const RiseFall *from_rf = arc->fromEdge()->asRiseFall();
|
||||||
|
if (from_rf == en_rf) {
|
||||||
|
report->warn(1113, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check.",
|
||||||
|
library_->name(),
|
||||||
|
name_,
|
||||||
|
en->name(),
|
||||||
|
q->name(),
|
||||||
|
en_rf == RiseFall::rise() ? "rising" : "falling",
|
||||||
|
en->name(),
|
||||||
|
d->name(),
|
||||||
|
from_rf == RiseFall::rise() ? "rising" : "falling");
|
||||||
|
return arc_set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
FuncExpr *
|
FuncExpr *
|
||||||
LibertyCell::findLatchEnableFunc(LibertyPort *data,
|
LibertyCell::findLatchEnableFunc(const LibertyPort *d,
|
||||||
LibertyPort *enable) const
|
const LibertyPort *en,
|
||||||
|
const RiseFall *en_rf) const
|
||||||
{
|
{
|
||||||
for (auto seq : sequentials_) {
|
for (auto seq : sequentials_) {
|
||||||
if (seq->isLatch()
|
if (seq->isLatch()
|
||||||
&& seq->data()
|
&& seq->data()
|
||||||
&& seq->data()->hasPort(data)
|
&& seq->data()->hasPort(d)
|
||||||
&& seq->clock()
|
&& seq->clock()
|
||||||
&& seq->clock()->hasPort(enable))
|
&& seq->clock()->hasPort(en)) {
|
||||||
|
FuncExpr *en_func = seq->clock();
|
||||||
|
TimingSense en_sense = en_func->portTimingSense(en);
|
||||||
|
if ((en_sense == TimingSense::positive_unate
|
||||||
|
&& en_rf == RiseFall::rise())
|
||||||
|
|| (en_sense == TimingSense::negative_unate
|
||||||
|
&& en_rf == RiseFall::fall()))
|
||||||
return seq->clock();
|
return seq->clock();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LatchEnable *
|
LatchEnable *
|
||||||
LibertyCell::makeLatchEnable(LibertyPort *d,
|
LibertyCell::makeLatchEnable(LibertyPort *d,
|
||||||
LibertyPort *en,
|
LibertyPort *en,
|
||||||
|
const RiseFall *en_rf,
|
||||||
LibertyPort *q,
|
LibertyPort *q,
|
||||||
TimingArcSet *d_to_q,
|
TimingArcSet *d_to_q,
|
||||||
TimingArcSet *en_to_q,
|
TimingArcSet *en_to_q,
|
||||||
TimingArcSet *setup_check,
|
TimingArcSet *setup_check,
|
||||||
Debug *debug)
|
Debug *debug)
|
||||||
{
|
{
|
||||||
RiseFall *en_rf = en_to_q->isRisingFallingEdge();
|
FuncExpr *en_func = findLatchEnableFunc(d, en, en_rf);
|
||||||
FuncExpr *en_func = findLatchEnableFunc(d, en);
|
|
||||||
LatchEnable *latch_enable = new LatchEnable(d, en, en_rf, en_func, q,
|
LatchEnable *latch_enable = new LatchEnable(d, en, en_rf, en_func, q,
|
||||||
d_to_q, en_to_q, setup_check);
|
d_to_q, en_to_q, setup_check);
|
||||||
// Multiple enables for D->Q pairs are not supported.
|
latch_enables_.push_back(latch_enable);
|
||||||
if (latch_d_to_q_map_[d_to_q])
|
|
||||||
delete latch_d_to_q_map_[d_to_q];
|
|
||||||
latch_d_to_q_map_[d_to_q] = latch_enable;
|
latch_d_to_q_map_[d_to_q] = latch_enable;
|
||||||
latch_check_map_[setup_check] = latch_enable;
|
latch_check_map_[setup_check] = latch_enable;
|
||||||
latch_data_ports_.insert(d);
|
latch_data_ports_.insert(d);
|
||||||
debugPrint(debug, "liberty", 2, "latch d=%s en=%s q=%s",
|
debugPrint(debug, "liberty", 2, "latch d=%s en=%s %s q=%s",
|
||||||
d->name(), en->name(), q->name());
|
d->name(),
|
||||||
|
en->name(),
|
||||||
|
en_rf->name(),
|
||||||
|
q->name());
|
||||||
return latch_enable;
|
return latch_enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyCell::inferLatchRoles(Debug *debug)
|
LibertyCell::inferLatchRoles(Report *report,
|
||||||
|
Debug *debug)
|
||||||
{
|
{
|
||||||
if (hasInferedRegTimingArcs()) {
|
if (hasInferedRegTimingArcs()) {
|
||||||
// Hunt down potential latch D/EN/Q triples.
|
// Hunt down potential latch D/EN/Q triples.
|
||||||
|
|
@ -1845,10 +1882,10 @@ LibertyCell::inferLatchRoles(Debug *debug)
|
||||||
// Previously identified as D->Q arc.
|
// Previously identified as D->Q arc.
|
||||||
|| d_to_q_role == TimingRole::latchDtoQ()) {
|
|| d_to_q_role == TimingRole::latchDtoQ()) {
|
||||||
LibertyPort *d = d_to_q->from();
|
LibertyPort *d = d_to_q->from();
|
||||||
// Check for setup check from en -> d.
|
const RiseFall *en_rf = en_to_q->isRisingFallingEdge();
|
||||||
for (TimingArcSet *setup_check : timingArcSets(en, d)) {
|
if (en_rf) {
|
||||||
if (setup_check->role() == TimingRole::setup()) {
|
TimingArcSet *setup_check = findLatchSetup(d, en, en_rf, q, report);
|
||||||
makeLatchEnable(d, en, q, d_to_q, en_to_q, setup_check, debug);
|
makeLatchEnable(d, en, en_rf, q, d_to_q, en_to_q, setup_check, debug);
|
||||||
d_to_q->setRole(TimingRole::latchDtoQ());
|
d_to_q->setRole(TimingRole::latchDtoQ());
|
||||||
en_to_q->setRole(TimingRole::latchEnToQ());
|
en_to_q->setRole(TimingRole::latchEnToQ());
|
||||||
}
|
}
|
||||||
|
|
@ -1858,7 +1895,6 @@ LibertyCell::inferLatchRoles(Debug *debug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LibertyCell::isLatchData(LibertyPort *port)
|
LibertyCell::isLatchData(LibertyPort *port)
|
||||||
|
|
@ -1871,7 +1907,7 @@ LibertyCell::latchEnable(TimingArcSet *d_to_q_set,
|
||||||
// Return values.
|
// Return values.
|
||||||
LibertyPort *&enable_port,
|
LibertyPort *&enable_port,
|
||||||
FuncExpr *&enable_func,
|
FuncExpr *&enable_func,
|
||||||
RiseFall *&enable_edge) const
|
const RiseFall *&enable_edge) const
|
||||||
{
|
{
|
||||||
enable_port = nullptr;
|
enable_port = nullptr;
|
||||||
LatchEnable *latch_enable = latch_d_to_q_map_.findKey(d_to_q_set);
|
LatchEnable *latch_enable = latch_d_to_q_map_.findKey(d_to_q_set);
|
||||||
|
|
@ -1882,7 +1918,7 @@ LibertyCell::latchEnable(TimingArcSet *d_to_q_set,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RiseFall *
|
const RiseFall *
|
||||||
LibertyCell::latchCheckEnableEdge(TimingArcSet *check_set)
|
LibertyCell::latchCheckEnableEdge(TimingArcSet *check_set)
|
||||||
{
|
{
|
||||||
LatchEnable *latch_enable = latch_check_map_.findKey(check_set);
|
LatchEnable *latch_enable = latch_check_map_.findKey(check_set);
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ Latches::latchEnablePath(Path *q_path,
|
||||||
const PathAnalysisPt *tgt_clk_path_ap = path_ap->tgtClkAnalysisPt();
|
const PathAnalysisPt *tgt_clk_path_ap = path_ap->tgtClkAnalysisPt();
|
||||||
const Instance *latch = network_->instance(q_path->pin(this));
|
const Instance *latch = network_->instance(q_path->pin(this));
|
||||||
Vertex *en_vertex;
|
Vertex *en_vertex;
|
||||||
RiseFall *en_rf;
|
const RiseFall *en_rf;
|
||||||
LatchEnableState state;
|
LatchEnableState state;
|
||||||
latchDtoQEnable(d_q_edge, latch, en_vertex, en_rf, state);
|
latchDtoQEnable(d_q_edge, latch, en_vertex, en_rf, state);
|
||||||
if (state == LatchEnableState::enabled) {
|
if (state == LatchEnableState::enabled) {
|
||||||
|
|
@ -303,7 +303,7 @@ Latches::latchOutArrival(Path *data_path,
|
||||||
Vertex *data_vertex = d_q_edge->from(graph_);
|
Vertex *data_vertex = d_q_edge->from(graph_);
|
||||||
const Instance *inst = network_->instance(data_vertex->pin());
|
const Instance *inst = network_->instance(data_vertex->pin());
|
||||||
Vertex *enable_vertex;
|
Vertex *enable_vertex;
|
||||||
RiseFall *enable_rf;
|
const RiseFall *enable_rf;
|
||||||
LatchEnableState state;
|
LatchEnableState state;
|
||||||
latchDtoQEnable(d_q_edge, inst, enable_vertex, enable_rf, state);
|
latchDtoQEnable(d_q_edge, inst, enable_vertex, enable_rf, state);
|
||||||
// Latch enable may be missing if library is malformed.
|
// Latch enable may be missing if library is malformed.
|
||||||
|
|
@ -466,7 +466,7 @@ Latches::latchDtoQEnable(Edge *d_q_edge,
|
||||||
const Instance *inst,
|
const Instance *inst,
|
||||||
// Return values.
|
// Return values.
|
||||||
Vertex *&enable_vertex,
|
Vertex *&enable_vertex,
|
||||||
RiseFall *&enable_rf,
|
const RiseFall *&enable_rf,
|
||||||
LatchEnableState &state) const
|
LatchEnableState &state) const
|
||||||
{
|
{
|
||||||
enable_vertex = nullptr;
|
enable_vertex = nullptr;
|
||||||
|
|
@ -515,7 +515,7 @@ Latches::latchDtoQState(Edge *edge) const
|
||||||
const Pin *from_pin = from_vertex->pin();
|
const Pin *from_pin = from_vertex->pin();
|
||||||
const Instance *inst = network_->instance(from_pin);
|
const Instance *inst = network_->instance(from_pin);
|
||||||
Vertex *enable_vertex;
|
Vertex *enable_vertex;
|
||||||
RiseFall *enable_rf;
|
const RiseFall *enable_rf;
|
||||||
LatchEnableState state;
|
LatchEnableState state;
|
||||||
latchDtoQEnable(edge, inst, enable_vertex, enable_rf, state);
|
latchDtoQEnable(edge, inst, enable_vertex, enable_rf, state);
|
||||||
return state;
|
return state;
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ public:
|
||||||
const Instance *inst,
|
const Instance *inst,
|
||||||
// Return values.
|
// Return values.
|
||||||
Vertex *&enable_vertex,
|
Vertex *&enable_vertex,
|
||||||
RiseFall *&enable_rf,
|
const RiseFall *&enable_rf,
|
||||||
LatchEnableState &state) const;
|
LatchEnableState &state) const;
|
||||||
LatchEnableState latchDtoQState(Edge *d_q_edge) const;
|
LatchEnableState latchDtoQState(Edge *d_q_edge) const;
|
||||||
void latchEnableOtherPath(Path *path,
|
void latchEnableOtherPath(Path *path,
|
||||||
|
|
|
||||||
|
|
@ -580,14 +580,9 @@ ReportPath::reportEndpoint(const PathEndLatchCheck *end)
|
||||||
const char *
|
const char *
|
||||||
ReportPath::latchDesc(const PathEndLatchCheck *end)
|
ReportPath::latchDesc(const PathEndLatchCheck *end)
|
||||||
{
|
{
|
||||||
// Liberty latch descriptions can have timing checks to the
|
|
||||||
// wrong edge of the enable, so look up the EN->Q arcs and use
|
|
||||||
// them to characterize the latch as positive/negative.
|
|
||||||
TimingArc *check_arc = end->checkArc();
|
TimingArc *check_arc = end->checkArc();
|
||||||
TimingArcSet *check_set = check_arc->set();
|
const RiseFall *en_rf = check_arc->fromEdge()->asRiseFall()->opposite();
|
||||||
LibertyCell *cell = check_set->from()->libertyCell();
|
return latchDesc(en_rf);
|
||||||
RiseFall *enable_rf = cell->latchCheckEnableEdge(check_set);
|
|
||||||
return latchDesc(enable_rf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3257,7 +3252,7 @@ ReportPath::edgeRegLatchDesc(Edge *first_edge,
|
||||||
if (cell) {
|
if (cell) {
|
||||||
LibertyPort *enable_port;
|
LibertyPort *enable_port;
|
||||||
FuncExpr *enable_func;
|
FuncExpr *enable_func;
|
||||||
RiseFall *enable_rf;
|
const RiseFall *enable_rf;
|
||||||
cell->latchEnable(first_edge->timingArcSet(),
|
cell->latchEnable(first_edge->timingArcSet(),
|
||||||
enable_port, enable_func, enable_rf);
|
enable_port, enable_func, enable_rf);
|
||||||
return latchDesc(enable_rf);
|
return latchDesc(enable_rf);
|
||||||
|
|
|
||||||
|
|
@ -4883,7 +4883,7 @@ latch_d_to_q_en()
|
||||||
TimingArcSet *d_q_set = self->timingArcSet();
|
TimingArcSet *d_q_set = self->timingArcSet();
|
||||||
LibertyPort *enable_port;
|
LibertyPort *enable_port;
|
||||||
FuncExpr *enable_func;
|
FuncExpr *enable_func;
|
||||||
RiseFall *enable_rf;
|
const RiseFall *enable_rf;
|
||||||
lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf);
|
lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf);
|
||||||
const char *en_name = enable_port->name();
|
const char *en_name = enable_port->name();
|
||||||
return stringPrintTmp("%s %s", en_name, enable_rf->asString());
|
return stringPrintTmp("%s %s", en_name, enable_rf->asString());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue