Merge remote-tracking branch 'parallax/master'
This commit is contained in:
commit
2debe54ede
|
|
@ -1322,7 +1322,7 @@ Edge::arcDelayAnnotated(const TimingArc *arc,
|
||||||
{
|
{
|
||||||
size_t index = arc->index() * ap_count + ap_index;
|
size_t index = arc->index() * ap_count + ap_index;
|
||||||
if (arc_delay_annotated_is_bits_)
|
if (arc_delay_annotated_is_bits_)
|
||||||
return arc_delay_annotated_.bits_ & (1 << index);
|
return arc_delay_annotated_.bits_ & arcDelayAnnotateBit(index);
|
||||||
else
|
else
|
||||||
return (*arc_delay_annotated_.seq_)[index];
|
return (*arc_delay_annotated_.seq_)[index];
|
||||||
}
|
}
|
||||||
|
|
@ -1334,7 +1334,7 @@ Edge::setArcDelayAnnotated(const TimingArc *arc,
|
||||||
bool annotated)
|
bool annotated)
|
||||||
{
|
{
|
||||||
size_t index = arc->index() * ap_count + ap_index;
|
size_t index = arc->index() * ap_count + ap_index;
|
||||||
if (index > sizeof(intptr_t) * 8
|
if (index > sizeof(uintptr_t) * 8
|
||||||
&& arc_delay_annotated_is_bits_) {
|
&& arc_delay_annotated_is_bits_) {
|
||||||
arc_delay_annotated_is_bits_ = false;
|
arc_delay_annotated_is_bits_ = false;
|
||||||
size_t bit_count = ap_count * RiseFall::index_count * 2;
|
size_t bit_count = ap_count * RiseFall::index_count * 2;
|
||||||
|
|
@ -1342,9 +1342,9 @@ Edge::setArcDelayAnnotated(const TimingArc *arc,
|
||||||
}
|
}
|
||||||
if (arc_delay_annotated_is_bits_) {
|
if (arc_delay_annotated_is_bits_) {
|
||||||
if (annotated)
|
if (annotated)
|
||||||
arc_delay_annotated_.bits_ |= (1 << index);
|
arc_delay_annotated_.bits_ |= arcDelayAnnotateBit(index);
|
||||||
else
|
else
|
||||||
arc_delay_annotated_.bits_ &= ~(1 << index);
|
arc_delay_annotated_.bits_ &= ~arcDelayAnnotateBit(index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(*arc_delay_annotated_.seq_)[index] = annotated;
|
(*arc_delay_annotated_.seq_)[index] = annotated;
|
||||||
|
|
@ -1368,6 +1368,12 @@ Edge::setDelayAnnotationIsIncremental(bool is_incr)
|
||||||
delay_annotation_is_incremental_ = is_incr;
|
delay_annotation_is_incremental_ = is_incr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t
|
||||||
|
Edge::arcDelayAnnotateBit(size_t index)
|
||||||
|
{
|
||||||
|
return static_cast<uintptr_t>(1) << index;
|
||||||
|
}
|
||||||
|
|
||||||
const TimingRole *
|
const TimingRole *
|
||||||
Edge::role() const
|
Edge::role() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -667,6 +667,10 @@ private:
|
||||||
int index_;
|
int index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
exceptionStateLess(const ExceptionState *state1,
|
||||||
|
const ExceptionState *state2);
|
||||||
|
|
||||||
// Exception thrown by check.
|
// Exception thrown by check.
|
||||||
class EmptyExpceptionPt : public Exception
|
class EmptyExpceptionPt : public Exception
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -421,6 +421,7 @@ protected:
|
||||||
DcalcAPIndex ap_index,
|
DcalcAPIndex ap_index,
|
||||||
DcalcAPIndex ap_count,
|
DcalcAPIndex ap_count,
|
||||||
bool annotated);
|
bool annotated);
|
||||||
|
static uintptr_t arcDelayAnnotateBit(size_t index);
|
||||||
|
|
||||||
TimingArcSet *arc_set_;
|
TimingArcSet *arc_set_;
|
||||||
VertexId from_;
|
VertexId from_;
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,8 @@ public:
|
||||||
exists_[mm_index] = false;
|
exists_[mm_index] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool equal(MinMaxValues *values1,
|
static bool equal(const MinMaxValues *values1,
|
||||||
MinMaxValues *values2)
|
const MinMaxValues *values2)
|
||||||
{
|
{
|
||||||
return ((!values1->exists_[MinMax::minIndex()]
|
return ((!values1->exists_[MinMax::minIndex()]
|
||||||
&& !values2->exists_[MinMax::minIndex()])
|
&& !values2->exists_[MinMax::minIndex()])
|
||||||
|
|
@ -166,6 +166,32 @@ public:
|
||||||
== values2->values_[MinMax::maxIndex()]));
|
== values2->values_[MinMax::maxIndex()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cmp(const MinMaxValues *values1,
|
||||||
|
const MinMaxValues *values2)
|
||||||
|
{
|
||||||
|
if (!values1->exists_[MinMax::minIndex()]
|
||||||
|
&& values2->exists_[MinMax::minIndex()])
|
||||||
|
return -1;
|
||||||
|
if (values1->exists_[MinMax::minIndex()]
|
||||||
|
&& !values2->exists_[MinMax::minIndex()])
|
||||||
|
return 1;
|
||||||
|
if (!values1->exists_[MinMax::maxIndex()]
|
||||||
|
&& values2->exists_[MinMax::maxIndex()])
|
||||||
|
return -1;
|
||||||
|
if (values1->exists_[MinMax::maxIndex()]
|
||||||
|
&& !values2->exists_[MinMax::maxIndex()])
|
||||||
|
return 1;
|
||||||
|
if (values1->values_[MinMax::minIndex()] < values2->values_[MinMax::minIndex()])
|
||||||
|
return -1;
|
||||||
|
if (values1->values_[MinMax::minIndex()] > values2->values_[MinMax::minIndex()])
|
||||||
|
return 1;
|
||||||
|
if (values1->values_[MinMax::maxIndex()] < values2->values_[MinMax::maxIndex()])
|
||||||
|
return -1;
|
||||||
|
if (values1->values_[MinMax::maxIndex()] > values2->values_[MinMax::maxIndex()])
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TYPE values_[MinMax::index_count];
|
TYPE values_[MinMax::index_count];
|
||||||
bool exists_[MinMax::index_count];
|
bool exists_[MinMax::index_count];
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class Path
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Path();
|
Path();
|
||||||
Path(Path *path);
|
Path(const Path *path);
|
||||||
Path(Vertex *vertex,
|
Path(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
|
|
@ -89,7 +89,7 @@ public:
|
||||||
TagIndex tagIndex(const StaState *sta) const;
|
TagIndex tagIndex(const StaState *sta) const;
|
||||||
void setTag(Tag *tag);
|
void setTag(Tag *tag);
|
||||||
size_t pathIndex(const StaState *sta) const;
|
size_t pathIndex(const StaState *sta) const;
|
||||||
ClkInfo *clkInfo(const StaState *sta) const;
|
const ClkInfo *clkInfo(const StaState *sta) const;
|
||||||
const ClockEdge *clkEdge(const StaState *sta) const;
|
const ClockEdge *clkEdge(const StaState *sta) const;
|
||||||
const Clock *clock(const StaState *sta) const;
|
const Clock *clock(const StaState *sta) const;
|
||||||
bool isClock(const StaState *sta) const;
|
bool isClock(const StaState *sta) const;
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,10 @@ public:
|
||||||
const std::string property);
|
const std::string property);
|
||||||
|
|
||||||
// Define handler for external property.
|
// Define handler for external property.
|
||||||
// proerties->defineProperty("foo",
|
// properties->defineProperty("foo",
|
||||||
// [] (const Instance *, Sta *) -> PropertyValue {
|
// [] (const Instance *, Sta *) -> PropertyValue {
|
||||||
// return PropertyValue("bar");
|
// return PropertyValue("bar");
|
||||||
// });
|
// });
|
||||||
void defineProperty(std::string &property,
|
void defineProperty(std::string &property,
|
||||||
PropertyRegistry<const Library *>::PropertyHandler handler);
|
PropertyRegistry<const Library *>::PropertyHandler handler);
|
||||||
void defineProperty(std::string &property,
|
void defineProperty(std::string &property,
|
||||||
|
|
@ -116,6 +116,8 @@ public:
|
||||||
PropertyRegistry<const Pin *>::PropertyHandler handler);
|
PropertyRegistry<const Pin *>::PropertyHandler handler);
|
||||||
void defineProperty(std::string &property,
|
void defineProperty(std::string &property,
|
||||||
PropertyRegistry<const Net *>::PropertyHandler handler);
|
PropertyRegistry<const Net *>::PropertyHandler handler);
|
||||||
|
void defineProperty(std::string &property,
|
||||||
|
PropertyRegistry<const Clock *>::PropertyHandler handler);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PropertyValue portSlew(const Port *port,
|
PropertyValue portSlew(const Port *port,
|
||||||
|
|
@ -159,6 +161,7 @@ protected:
|
||||||
PropertyRegistry<const Instance*> registry_instance_;
|
PropertyRegistry<const Instance*> registry_instance_;
|
||||||
PropertyRegistry<const Pin*> registry_pin_;
|
PropertyRegistry<const Pin*> registry_pin_;
|
||||||
PropertyRegistry<const Net*> registry_net_;
|
PropertyRegistry<const Net*> registry_net_;
|
||||||
|
PropertyRegistry<const Clock*> registry_clock_;
|
||||||
|
|
||||||
Sta *sta_;
|
Sta *sta_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class CheckCrpr;
|
||||||
class Genclks;
|
class Genclks;
|
||||||
class Corner;
|
class Corner;
|
||||||
|
|
||||||
typedef Set<ClkInfo*, ClkInfoLess> ClkInfoSet;
|
typedef Set<const ClkInfo*, ClkInfoLess> ClkInfoSet;
|
||||||
typedef UnorderedSet<Tag*, TagHash, TagEqual> TagSet;
|
typedef UnorderedSet<Tag*, TagHash, TagEqual> TagSet;
|
||||||
typedef UnorderedSet<TagGroup*, TagGroupHash, TagGroupEqual> TagGroupSet;
|
typedef UnorderedSet<TagGroup*, TagGroupHash, TagGroupEqual> TagGroupSet;
|
||||||
typedef Map<Vertex*, Slack> VertexSlackMap;
|
typedef Map<Vertex*, Slack> VertexSlackMap;
|
||||||
|
|
@ -158,7 +158,7 @@ public:
|
||||||
// Clock arrival respecting ideal clock insertion delay and latency.
|
// Clock arrival respecting ideal clock insertion delay and latency.
|
||||||
Arrival clkPathArrival(const Path *clk_path) const;
|
Arrival clkPathArrival(const Path *clk_path) const;
|
||||||
Arrival clkPathArrival(const Path *clk_path,
|
Arrival clkPathArrival(const Path *clk_path,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
const ClockEdge *clk_edge,
|
const ClockEdge *clk_edge,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap) const;
|
const PathAnalysisPt *path_ap) const;
|
||||||
|
|
@ -244,7 +244,7 @@ public:
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
const Clock *clk,
|
const Clock *clk,
|
||||||
const RiseFall *clk_rf,
|
const RiseFall *clk_rf,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
const Pin *to_pin,
|
const Pin *to_pin,
|
||||||
const RiseFall *to_rf,
|
const RiseFall *to_rf,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
|
|
@ -263,20 +263,20 @@ public:
|
||||||
bool arc_delay_min_max_eq,
|
bool arc_delay_min_max_eq,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap);
|
const PathAnalysisPt *path_ap);
|
||||||
ClkInfo *thruClkInfo(Path *from_path,
|
const ClkInfo *thruClkInfo(Path *from_path,
|
||||||
Vertex *from_vertex,
|
Vertex *from_vertex,
|
||||||
ClkInfo *from_clk_info,
|
const ClkInfo *from_clk_info,
|
||||||
bool from_is_clk,
|
bool from_is_clk,
|
||||||
Edge *edge,
|
Edge *edge,
|
||||||
Vertex *to_vertex,
|
Vertex *to_vertex,
|
||||||
const Pin *to_pin,
|
const Pin *to_pin,
|
||||||
bool to_is_clk,
|
bool to_is_clk,
|
||||||
bool arc_delay_min_max_eq,
|
bool arc_delay_min_max_eq,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap);
|
const PathAnalysisPt *path_ap);
|
||||||
ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
|
const ClkInfo *clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
|
||||||
Path *from_path,
|
Path *from_path,
|
||||||
const PathAnalysisPt *path_ap);
|
const PathAnalysisPt *path_ap);
|
||||||
void seedClkArrivals(const Pin *pin,
|
void seedClkArrivals(const Pin *pin,
|
||||||
Vertex *vertex,
|
Vertex *vertex,
|
||||||
TagGroupBldr *tag_bldr);
|
TagGroupBldr *tag_bldr);
|
||||||
|
|
@ -323,7 +323,7 @@ public:
|
||||||
|
|
||||||
Tag *findTag(const RiseFall *rf,
|
Tag *findTag(const RiseFall *rf,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap,
|
||||||
ClkInfo *tag_clk,
|
const ClkInfo *tag_clk,
|
||||||
bool is_clk,
|
bool is_clk,
|
||||||
InputDelay *input_delay,
|
InputDelay *input_delay,
|
||||||
bool is_segment_start,
|
bool is_segment_start,
|
||||||
|
|
@ -331,22 +331,22 @@ public:
|
||||||
bool own_states);
|
bool own_states);
|
||||||
void reportTags() const;
|
void reportTags() const;
|
||||||
void reportClkInfos() const;
|
void reportClkInfos() const;
|
||||||
virtual ClkInfo *findClkInfo(const ClockEdge *clk_edge,
|
const ClkInfo *findClkInfo(const ClockEdge *clk_edge,
|
||||||
const Pin *clk_src,
|
const Pin *clk_src,
|
||||||
bool is_propagated,
|
bool is_propagated,
|
||||||
const Pin *gen_clk_src,
|
const Pin *gen_clk_src,
|
||||||
bool gen_clk_src_path,
|
bool gen_clk_src_path,
|
||||||
const RiseFall *pulse_clk_sense,
|
const RiseFall *pulse_clk_sense,
|
||||||
Arrival insertion,
|
Arrival insertion,
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap,
|
||||||
Path *crpr_clk_path);
|
Path *crpr_clk_path);
|
||||||
ClkInfo *findClkInfo(const ClockEdge *clk_edge,
|
const ClkInfo *findClkInfo(const ClockEdge *clk_edge,
|
||||||
const Pin *clk_src,
|
const Pin *clk_src,
|
||||||
bool is_propagated,
|
bool is_propagated,
|
||||||
Arrival insertion,
|
Arrival insertion,
|
||||||
const PathAnalysisPt *path_ap);
|
const PathAnalysisPt *path_ap);
|
||||||
// Timing derated arc delay for a path analysis point.
|
// Timing derated arc delay for a path analysis point.
|
||||||
ArcDelay deratedDelay(const Vertex *from_vertex,
|
ArcDelay deratedDelay(const Vertex *from_vertex,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
|
|
@ -515,13 +515,13 @@ protected:
|
||||||
const Pin *from_pin,
|
const Pin *from_pin,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
bool from_is_clk,
|
bool from_is_clk,
|
||||||
ClkInfo *from_clk_info,
|
const ClkInfo *from_clk_info,
|
||||||
const Pin *to_pin,
|
const Pin *to_pin,
|
||||||
const RiseFall *to_rf,
|
const RiseFall *to_rf,
|
||||||
bool to_is_clk,
|
bool to_is_clk,
|
||||||
bool to_is_reg_clk,
|
bool to_is_reg_clk,
|
||||||
bool to_is_segment_start,
|
bool to_is_segment_start,
|
||||||
ClkInfo *to_clk_info,
|
const ClkInfo *to_clk_info,
|
||||||
InputDelay *to_input_delay,
|
InputDelay *to_input_delay,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap);
|
const PathAnalysisPt *path_ap);
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,9 @@ PropActivityVisitor::visit(Vertex *vertex)
|
||||||
}
|
}
|
||||||
if (network_->isDriver(pin)) {
|
if (network_->isDriver(pin)) {
|
||||||
LibertyPort *port = network_->libertyPort(pin);
|
LibertyPort *port = network_->libertyPort(pin);
|
||||||
|
LibertyCell *test_cell = port->libertyCell()->testCell();
|
||||||
|
if (test_cell)
|
||||||
|
port = test_cell->findLibertyPort(port->name());
|
||||||
if (port) {
|
if (port) {
|
||||||
FuncExpr *func = port->function();
|
FuncExpr *func = port->function();
|
||||||
if (func) {
|
if (func) {
|
||||||
|
|
@ -519,23 +522,28 @@ PropActivityVisitor::visit(Vertex *vertex)
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
LibertyCell *cell = network_->libertyCell(inst);
|
LibertyCell *cell = network_->libertyCell(inst);
|
||||||
if (network_->isLoad(pin) && cell) {
|
if (cell) {
|
||||||
if (cell->hasSequentials()) {
|
LibertyCell *test_cell = cell->libertyCell()->testCell();
|
||||||
debugPrint(debug_, "power_activity", 3, "pending seq %s",
|
if (network_->isLoad(pin)) {
|
||||||
network_->pathName(inst));
|
if (cell->hasSequentials()
|
||||||
visited_regs_.insert(inst);
|
|| (test_cell
|
||||||
}
|
&& test_cell->hasSequentials())) {
|
||||||
// Gated clock cells latch the enable so there is no EN->GCLK timing arc.
|
debugPrint(debug_, "power_activity", 3, "pending seq %s",
|
||||||
if (cell->isClockGate()) {
|
network_->pathName(inst));
|
||||||
const Pin *enable, *clk, *gclk;
|
visited_regs_.insert(inst);
|
||||||
power_->clockGatePins(inst, enable, clk, gclk);
|
}
|
||||||
if (gclk) {
|
// Gated clock cells latch the enable so there is no EN->GCLK timing arc.
|
||||||
Vertex *gclk_vertex = graph_->pinDrvrVertex(gclk);
|
if (cell->isClockGate()) {
|
||||||
bfs_->enqueue(gclk_vertex);
|
const Pin *enable, *clk, *gclk;
|
||||||
}
|
power_->clockGatePins(inst, enable, clk, gclk);
|
||||||
|
if (gclk) {
|
||||||
|
Vertex *gclk_vertex = graph_->pinDrvrVertex(gclk);
|
||||||
|
bfs_->enqueue(gclk_vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
bfs_->enqueueAdjacentVertices(vertex);
|
||||||
}
|
}
|
||||||
bfs_->enqueueAdjacentVertices(vertex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,12 +733,9 @@ Power::ensureActivities()
|
||||||
int pass = 1;
|
int pass = 1;
|
||||||
while (!regs.empty() && pass < max_activity_passes_) {
|
while (!regs.empty() && pass < max_activity_passes_) {
|
||||||
visitor.init();
|
visitor.init();
|
||||||
InstanceSet::Iterator reg_iter(regs);
|
for (const Instance *reg : regs)
|
||||||
while (reg_iter.hasNext()) {
|
|
||||||
const Instance *reg = reg_iter.next();
|
|
||||||
// Propagate activiities across register D->Q.
|
// Propagate activiities across register D->Q.
|
||||||
seedRegOutputActivities(reg, bfs);
|
seedRegOutputActivities(reg, bfs);
|
||||||
}
|
|
||||||
// Propagate register output activities through
|
// Propagate register output activities through
|
||||||
// combinational logic.
|
// combinational logic.
|
||||||
bfs.visit(levelize_->maxLevel(), &visitor);
|
bfs.visit(levelize_->maxLevel(), &visitor);
|
||||||
|
|
@ -771,7 +776,11 @@ Power::seedRegOutputActivities(const Instance *inst,
|
||||||
BfsFwdIterator &bfs)
|
BfsFwdIterator &bfs)
|
||||||
{
|
{
|
||||||
LibertyCell *cell = network_->libertyCell(inst);
|
LibertyCell *cell = network_->libertyCell(inst);
|
||||||
for (Sequential *seq : cell->sequentials()) {
|
LibertyCell *test_cell = cell->testCell();
|
||||||
|
const SequentialSeq &seqs = test_cell
|
||||||
|
? test_cell->sequentials()
|
||||||
|
: cell->sequentials();
|
||||||
|
for (Sequential *seq : seqs) {
|
||||||
seedRegOutputActivities(inst, seq, seq->output(), false);
|
seedRegOutputActivities(inst, seq, seq->output(), false);
|
||||||
seedRegOutputActivities(inst, seq, seq->outputInv(), true);
|
seedRegOutputActivities(inst, seq, seq->outputInv(), true);
|
||||||
// Enqueue register output pins with functions that reference
|
// Enqueue register output pins with functions that reference
|
||||||
|
|
@ -780,6 +789,8 @@ Power::seedRegOutputActivities(const Instance *inst,
|
||||||
while (pin_iter->hasNext()) {
|
while (pin_iter->hasNext()) {
|
||||||
Pin *pin = pin_iter->next();
|
Pin *pin = pin_iter->next();
|
||||||
LibertyPort *port = network_->libertyPort(pin);
|
LibertyPort *port = network_->libertyPort(pin);
|
||||||
|
if (test_cell)
|
||||||
|
port = test_cell->findLibertyPort(port->name());
|
||||||
if (port) {
|
if (port) {
|
||||||
FuncExpr *func = port->function();
|
FuncExpr *func = port->function();
|
||||||
Vertex *vertex = graph_->pinDrvrVertex(pin);
|
Vertex *vertex = graph_->pinDrvrVertex(pin);
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ VcdParse::read(const char *filename,
|
||||||
Stats stats(debug_, report_);
|
Stats stats(debug_, report_);
|
||||||
filename_ = filename;
|
filename_ = filename;
|
||||||
reader_ = reader;
|
reader_ = reader;
|
||||||
file_line_ = 1;
|
file_line_ = 0;
|
||||||
stmt_line_ = 1;
|
stmt_line_ = 0;
|
||||||
std::string token = getToken();
|
std::string token = getToken();
|
||||||
while (!token.empty()) {
|
while (!token.empty()) {
|
||||||
if (token == "$date")
|
if (token == "$date")
|
||||||
|
|
@ -205,11 +205,19 @@ void
|
||||||
VcdParse::parseVarValues()
|
VcdParse::parseVarValues()
|
||||||
{
|
{
|
||||||
string token = getToken();
|
string token = getToken();
|
||||||
|
bool first_time = true;
|
||||||
while (!token.empty()) {
|
while (!token.empty()) {
|
||||||
char char0 = toupper(token[0]);
|
char char0 = toupper(token[0]);
|
||||||
if (char0 == '#' && token.size() > 1) {
|
if (char0 == '#' && token.size() > 1) {
|
||||||
prev_time_ = time_;
|
VcdTime time = stoll(token.substr(1));
|
||||||
time_ = stoll(token.substr(1));
|
if (first_time) {
|
||||||
|
prev_time_ = time;
|
||||||
|
first_time = false;
|
||||||
|
reader_->setTimeMin(time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev_time_ = time_;
|
||||||
|
time_ = time;
|
||||||
if (time_ > prev_time_)
|
if (time_ > prev_time_)
|
||||||
reader_->varMinDeltaTime(time_ - prev_time_);
|
reader_->varMinDeltaTime(time_ - prev_time_);
|
||||||
}
|
}
|
||||||
|
|
@ -286,20 +294,18 @@ VcdParse::getToken()
|
||||||
{
|
{
|
||||||
string token;
|
string token;
|
||||||
int ch = gzgetc(stream_);
|
int ch = gzgetc(stream_);
|
||||||
if (ch == '\n')
|
|
||||||
file_line_++;
|
|
||||||
// skip whitespace
|
// skip whitespace
|
||||||
while (ch != EOF && isspace(ch)) {
|
while (ch != EOF && isspace(ch)) {
|
||||||
ch = gzgetc(stream_);
|
|
||||||
if (ch == '\n')
|
if (ch == '\n')
|
||||||
file_line_++;
|
file_line_++;
|
||||||
|
ch = gzgetc(stream_);
|
||||||
}
|
}
|
||||||
while (ch != EOF && !isspace(ch)) {
|
while (ch != EOF && !isspace(ch)) {
|
||||||
token.push_back(ch);
|
token.push_back(ch);
|
||||||
ch = gzgetc(stream_);
|
ch = gzgetc(stream_);
|
||||||
if (ch == '\n')
|
|
||||||
file_line_++;
|
|
||||||
}
|
}
|
||||||
|
if (ch == '\n')
|
||||||
|
file_line_++;
|
||||||
if (ch == EOF)
|
if (ch == EOF)
|
||||||
return "";
|
return "";
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,8 @@ public:
|
||||||
virtual void setTimeUnit(const std::string &time_unit,
|
virtual void setTimeUnit(const std::string &time_unit,
|
||||||
double time_unit_scale,
|
double time_unit_scale,
|
||||||
double time_scale) = 0;
|
double time_scale) = 0;
|
||||||
virtual void setTimeMax(VcdTime time_max) = 0;
|
virtual void setTimeMin(VcdTime time) = 0;
|
||||||
|
virtual void setTimeMax(VcdTime time) = 0;
|
||||||
virtual void varMinDeltaTime(VcdTime min_delta_time) = 0;
|
virtual void varMinDeltaTime(VcdTime min_delta_time) = 0;
|
||||||
virtual bool varIdValid(const std::string &id) = 0;
|
virtual bool varIdValid(const std::string &id) = 0;
|
||||||
virtual void makeVar(const VcdScope &scope,
|
virtual void makeVar(const VcdScope &scope,
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ public:
|
||||||
Report *report,
|
Report *report,
|
||||||
Debug *debug);
|
Debug *debug);
|
||||||
VcdTime timeMax() const { return time_max_; }
|
VcdTime timeMax() const { return time_max_; }
|
||||||
|
VcdTime timeMin() const { return time_min_; }
|
||||||
const VcdIdCountsMap &countMap() const { return vcd_count_map_; }
|
const VcdIdCountsMap &countMap() const { return vcd_count_map_; }
|
||||||
double timeScale() const { return time_scale_; }
|
double timeScale() const { return time_scale_; }
|
||||||
|
|
||||||
|
|
@ -137,7 +138,8 @@ public:
|
||||||
void setTimeUnit(const string &time_unit,
|
void setTimeUnit(const string &time_unit,
|
||||||
double time_unit_scale,
|
double time_unit_scale,
|
||||||
double time_scale) override;
|
double time_scale) override;
|
||||||
void setTimeMax(VcdTime time_max) override;
|
void setTimeMin(VcdTime time) override;
|
||||||
|
void setTimeMax(VcdTime time) override;
|
||||||
void varMinDeltaTime(VcdTime) override {}
|
void varMinDeltaTime(VcdTime) override {}
|
||||||
bool varIdValid(const string &id) override;
|
bool varIdValid(const string &id) override;
|
||||||
void makeVar(const VcdScope &scope,
|
void makeVar(const VcdScope &scope,
|
||||||
|
|
@ -164,6 +166,7 @@ private:
|
||||||
Debug *debug_;
|
Debug *debug_;
|
||||||
|
|
||||||
double time_scale_;
|
double time_scale_;
|
||||||
|
VcdTime time_min_;
|
||||||
VcdTime time_max_;
|
VcdTime time_max_;
|
||||||
VcdIdCountsMap vcd_count_map_;
|
VcdIdCountsMap vcd_count_map_;
|
||||||
};
|
};
|
||||||
|
|
@ -177,7 +180,8 @@ VcdCountReader::VcdCountReader(const char *scope,
|
||||||
report_(report),
|
report_(report),
|
||||||
debug_(debug),
|
debug_(debug),
|
||||||
time_scale_(1.0),
|
time_scale_(1.0),
|
||||||
time_max_(0.0)
|
time_min_(0),
|
||||||
|
time_max_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,9 +194,15 @@ VcdCountReader::setTimeUnit(const string &,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VcdCountReader::setTimeMax(VcdTime time_max)
|
VcdCountReader::setTimeMin(VcdTime time)
|
||||||
{
|
{
|
||||||
time_max_ = time_max;
|
time_min_ = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdCountReader::setTimeMax(VcdTime time)
|
||||||
|
{
|
||||||
|
time_max_ = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -400,14 +410,16 @@ ReadVcdActivities::readActivities()
|
||||||
void
|
void
|
||||||
ReadVcdActivities::setActivities()
|
ReadVcdActivities::setActivities()
|
||||||
{
|
{
|
||||||
|
VcdTime time_min = vcd_reader_.timeMin();
|
||||||
VcdTime time_max = vcd_reader_.timeMax();
|
VcdTime time_max = vcd_reader_.timeMax();
|
||||||
|
VcdTime time_delta = time_max - time_min;
|
||||||
double time_scale = vcd_reader_.timeScale();
|
double time_scale = vcd_reader_.timeScale();
|
||||||
for (auto& [id, vcd_counts] : vcd_reader_.countMap()) {
|
for (auto& [id, vcd_counts] : vcd_reader_.countMap()) {
|
||||||
for (const VcdCount &vcd_count : vcd_counts) {
|
for (const VcdCount &vcd_count : vcd_counts) {
|
||||||
double transition_count = vcd_count.transitionCount();
|
double transition_count = vcd_count.transitionCount();
|
||||||
VcdTime high_time = vcd_count.highTime(time_max);
|
VcdTime high_time = vcd_count.highTime(time_max);
|
||||||
float duty = static_cast<double>(high_time) / time_max;
|
float duty = static_cast<double>(high_time) / time_delta;
|
||||||
float density = transition_count / (time_max * time_scale);
|
float density = transition_count / (time_delta * time_scale);
|
||||||
if (debug_->check("read_vcd_activities", 1)) {
|
if (debug_->check("read_vcd_activities", 1)) {
|
||||||
for (const Pin *pin : vcd_count.pins()) {
|
for (const Pin *pin : vcd_count.pins()) {
|
||||||
debugPrint(debug_, "read_vcd_activities", 1,
|
debugPrint(debug_, "read_vcd_activities", 1,
|
||||||
|
|
@ -433,8 +445,9 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin,
|
||||||
double transition_count)
|
double transition_count)
|
||||||
{
|
{
|
||||||
VcdTime time_max = vcd_reader_.timeMax();
|
VcdTime time_max = vcd_reader_.timeMax();
|
||||||
|
VcdTime time_min = vcd_reader_.timeMin();
|
||||||
double time_scale = vcd_reader_.timeScale();
|
double time_scale = vcd_reader_.timeScale();
|
||||||
double sim_period = time_max * time_scale / (transition_count / 2.0);
|
double sim_period = (time_max - time_min) * time_scale / (transition_count / 2.0);
|
||||||
ClockSet *clks = sdc_->findLeafPinClocks(pin);
|
ClockSet *clks = sdc_->findLeafPinClocks(pin);
|
||||||
if (clks) {
|
if (clks) {
|
||||||
for (Clock *clk : *clks) {
|
for (Clock *clk : *clks) {
|
||||||
|
|
@ -449,4 +462,4 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -2280,17 +2280,23 @@ ExceptionState::hash() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExceptionStateLess::operator()(const ExceptionState *state1,
|
exceptionStateLess(const ExceptionState *state1,
|
||||||
const ExceptionState *state2) const
|
const ExceptionState *state2)
|
||||||
{
|
{
|
||||||
const ExceptionPath *except1 = state1->exception();
|
const ExceptionPath *except1 = state1->exception();
|
||||||
const ExceptionPath *except2 = state2->exception();
|
const ExceptionPath *except2 = state2->exception();
|
||||||
return except1->id() < except2->id()
|
return except1->id() < except2->id()
|
||||||
//return except1 < except2
|
|
||||||
|| (except1 == except2
|
|| (except1 == except2
|
||||||
&& state1->index() < state2->index());
|
&& state1->index() < state2->index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ExceptionStateLess::operator()(const ExceptionState *state1,
|
||||||
|
const ExceptionState *state2) const
|
||||||
|
{
|
||||||
|
return exceptionStateLess(state1, state2);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExceptionPathLess::ExceptionPathLess(const Network *network) :
|
ExceptionPathLess::ExceptionPathLess(const Network *network) :
|
||||||
|
|
|
||||||
|
|
@ -322,17 +322,17 @@ MinPulseWidthCheck::closePath(const StaState *sta) const
|
||||||
const RiseFall *open_rf = open_path_->transition(sta);
|
const RiseFall *open_rf = open_path_->transition(sta);
|
||||||
const RiseFall *close_rf = open_rf->opposite();
|
const RiseFall *close_rf = open_rf->opposite();
|
||||||
Tag *open_tag = open_path_->tag(sta);
|
Tag *open_tag = open_path_->tag(sta);
|
||||||
ClkInfo *open_clk_info = open_tag->clkInfo();
|
const ClkInfo *open_clk_info = open_tag->clkInfo();
|
||||||
ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(),
|
const ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(),
|
||||||
open_clk_info->clkSrc(),
|
open_clk_info->clkSrc(),
|
||||||
open_clk_info->isPropagated(),
|
open_clk_info->isPropagated(),
|
||||||
open_clk_info->genClkSrc(),
|
open_clk_info->genClkSrc(),
|
||||||
open_clk_info->isGenClkSrcPath(),
|
open_clk_info->isGenClkSrcPath(),
|
||||||
open_clk_info->pulseClkSense(),
|
open_clk_info->pulseClkSense(),
|
||||||
delay_zero, 0.0, nullptr,
|
delay_zero, 0.0, nullptr,
|
||||||
open_clk_info->pathAPIndex(),
|
open_clk_info->pathAPIndex(),
|
||||||
open_clk_info->crprClkPath(sta),
|
open_clk_info->crprClkPath(sta),
|
||||||
sta);
|
sta);
|
||||||
Tag close_tag(0,
|
Tag close_tag(0,
|
||||||
close_rf->index(),
|
close_rf->index(),
|
||||||
close_ap->index(),
|
close_ap->index(),
|
||||||
|
|
@ -350,7 +350,7 @@ MinPulseWidthCheck::closePath(const StaState *sta) const
|
||||||
close_ap, sta);
|
close_ap, sta);
|
||||||
while (close_iter.hasNext()) {
|
while (close_iter.hasNext()) {
|
||||||
Path *close_path = close_iter.next();
|
Path *close_path = close_iter.next();
|
||||||
if (tagMatchNoPathAp(close_path->tag(sta), &close_tag)) {
|
if (Tag::matchNoPathAp(close_path->tag(sta), &close_tag)) {
|
||||||
debugPrint(sta->debug(), "mpw", 3, " match %s",
|
debugPrint(sta->debug(), "mpw", 3, " match %s",
|
||||||
close_path->tag(sta)->to_string(sta).c_str());
|
close_path->tag(sta)->to_string(sta).c_str());
|
||||||
return close_path;
|
return close_path;
|
||||||
|
|
@ -394,7 +394,7 @@ const ClockEdge *
|
||||||
MinPulseWidthCheck::closeClkEdge(const StaState *sta) const
|
MinPulseWidthCheck::closeClkEdge(const StaState *sta) const
|
||||||
{
|
{
|
||||||
Tag *open_tag = open_path_->tag(sta);
|
Tag *open_tag = open_path_->tag(sta);
|
||||||
ClkInfo *open_clk_info = open_tag->clkInfo();
|
const ClkInfo *open_clk_info = open_tag->clkInfo();
|
||||||
return open_clk_info->clkEdge()->opposite();
|
return open_clk_info->clkEdge()->opposite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@
|
||||||
|
|
||||||
#include "ClkInfo.hh"
|
#include "ClkInfo.hh"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "Units.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
|
|
@ -44,7 +47,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
Path *crpr_clk_path,
|
const Path *crpr_clk_path,
|
||||||
const StaState *sta) :
|
const StaState *sta) :
|
||||||
clk_edge_(clk_edge),
|
clk_edge_(clk_edge),
|
||||||
clk_src_(clk_src),
|
clk_src_(clk_src),
|
||||||
|
|
@ -55,6 +58,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
|
||||||
latency_(latency),
|
latency_(latency),
|
||||||
is_propagated_(is_propagated),
|
is_propagated_(is_propagated),
|
||||||
is_gen_clk_src_path_(is_gen_clk_src_path),
|
is_gen_clk_src_path_(is_gen_clk_src_path),
|
||||||
|
crpr_path_refs_filter_(crpr_clk_path ? crpr_clk_path->tag(sta)->isFilter() : false),
|
||||||
is_pulse_clk_(pulse_clk_sense != nullptr),
|
is_pulse_clk_(pulse_clk_sense != nullptr),
|
||||||
pulse_clk_sense_(pulse_clk_sense ? pulse_clk_sense->index() : 0),
|
pulse_clk_sense_(pulse_clk_sense ? pulse_clk_sense->index() : 0),
|
||||||
path_ap_index_(path_ap_index)
|
path_ap_index_(path_ap_index)
|
||||||
|
|
@ -78,19 +82,26 @@ ClkInfo::findHash(const StaState *sta)
|
||||||
hashIncr(hash_, network->vertexId(clk_src_));
|
hashIncr(hash_, network->vertexId(clk_src_));
|
||||||
if (gen_clk_src_)
|
if (gen_clk_src_)
|
||||||
hashIncr(hash_, network->vertexId(gen_clk_src_));
|
hashIncr(hash_, network->vertexId(gen_clk_src_));
|
||||||
hashIncr(hash_, crprClkVertexId(sta));
|
if (crpr_clk_path_.isNull())
|
||||||
|
hashIncr(hash_, vertex_id_null);
|
||||||
|
else {
|
||||||
|
hashIncr(hash_, crpr_clk_path_.vertexId(sta));
|
||||||
|
hashIncr(hash_, crpr_clk_path_.tag(sta)->hash(false, sta));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::hash<float> hash_float;
|
||||||
if (uncertainties_) {
|
if (uncertainties_) {
|
||||||
float uncertainty;
|
float uncertainty;
|
||||||
bool exists;
|
bool exists;
|
||||||
uncertainties_->value(MinMax::min(), uncertainty, exists);
|
uncertainties_->value(MinMax::min(), uncertainty, exists);
|
||||||
if (exists)
|
if (exists)
|
||||||
hashIncr(hash_, uncertainty * 1E+12F);
|
hashIncr(hash_, hash_float(uncertainty));
|
||||||
uncertainties_->value(MinMax::max(), uncertainty, exists);
|
uncertainties_->value(MinMax::max(), uncertainty, exists);
|
||||||
if (exists)
|
if (exists)
|
||||||
hashIncr(hash_, uncertainty * 1E+12F);
|
hashIncr(hash_, hash_float(uncertainty));
|
||||||
}
|
}
|
||||||
hashIncr(hash_, latency_ * 1E+12F);
|
hashIncr(hash_, hash_float(latency_));
|
||||||
hashIncr(hash_, delayAsFloat(insertion_) * 1E+12F);
|
hashIncr(hash_, hash_float(delayAsFloat(insertion_)));
|
||||||
hashIncr(hash_, is_propagated_);
|
hashIncr(hash_, is_propagated_);
|
||||||
hashIncr(hash_, is_gen_clk_src_path_);
|
hashIncr(hash_, is_gen_clk_src_path_);
|
||||||
hashIncr(hash_, is_pulse_clk_);
|
hashIncr(hash_, is_pulse_clk_);
|
||||||
|
|
@ -101,19 +112,13 @@ ClkInfo::findHash(const StaState *sta)
|
||||||
VertexId
|
VertexId
|
||||||
ClkInfo::crprClkVertexId(const StaState *sta) const
|
ClkInfo::crprClkVertexId(const StaState *sta) const
|
||||||
{
|
{
|
||||||
if (crpr_clk_path_.isNull())
|
return crpr_clk_path_.vertexId(sta);
|
||||||
return vertex_id_null;
|
|
||||||
else
|
|
||||||
return crpr_clk_path_.vertexId(sta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Path *
|
Path *
|
||||||
ClkInfo::crprClkPath(const StaState *sta)
|
ClkInfo::crprClkPath(const StaState *sta)
|
||||||
{
|
{
|
||||||
if (crpr_clk_path_.isNull())
|
return Path::vertexPath(crpr_clk_path_, sta);
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
return Path::vertexPath(crpr_clk_path_, sta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Path *
|
const Path *
|
||||||
|
|
@ -125,6 +130,15 @@ ClkInfo::crprClkPath(const StaState *sta) const
|
||||||
return Path::vertexPath(crpr_clk_path_, sta);
|
return Path::vertexPath(crpr_clk_path_, sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Path *
|
||||||
|
ClkInfo::crprClkPathRaw() const
|
||||||
|
{
|
||||||
|
if (crpr_clk_path_.isNull())
|
||||||
|
return nullptr;
|
||||||
|
else
|
||||||
|
return &crpr_clk_path_;
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ClkInfo::to_string(const StaState *sta) const
|
ClkInfo::to_string(const StaState *sta) const
|
||||||
{
|
{
|
||||||
|
|
@ -150,13 +164,37 @@ ClkInfo::to_string(const StaState *sta) const
|
||||||
|
|
||||||
if (!crpr_clk_path_.isNull()) {
|
if (!crpr_clk_path_.isNull()) {
|
||||||
const Pin *crpr_clk_pin = crpr_clk_path_.vertex(sta)->pin();
|
const Pin *crpr_clk_pin = crpr_clk_path_.vertex(sta)->pin();
|
||||||
result += " crpr_pin ";
|
result += " crpr ";
|
||||||
result += network->pathName(crpr_clk_pin);
|
result += network->pathName(crpr_clk_pin);
|
||||||
|
result += "/";
|
||||||
|
result += std::to_string(crpr_clk_path_.tag(sta)->index());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_gen_clk_src_path_)
|
if (is_gen_clk_src_path_)
|
||||||
result += " genclk";
|
result += " genclk";
|
||||||
|
if (gen_clk_src_) {
|
||||||
|
result += " ";
|
||||||
|
result += network->pathName(gen_clk_src_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insertion_ > 0.0) {
|
||||||
|
result += " insert";
|
||||||
|
result += std::to_string(insertion_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uncertainties_) {
|
||||||
|
result += " uncertain ";
|
||||||
|
float uncertainty;
|
||||||
|
bool exists;
|
||||||
|
uncertainties_->value(MinMax::min(), uncertainty, exists);
|
||||||
|
if (exists)
|
||||||
|
result += sta->units()->timeUnit()->asString(uncertainty);
|
||||||
|
uncertainties_->value(MinMax::max(), uncertainty, exists);
|
||||||
|
if (exists) {
|
||||||
|
result += ":";
|
||||||
|
result += sta->units()->timeUnit()->asString(uncertainty);
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,13 +216,6 @@ ClkInfo::pulseClkSense() const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ClkInfo::refsFilter(const StaState *sta) const
|
|
||||||
{
|
|
||||||
return !crpr_clk_path_.isNull()
|
|
||||||
&& crpr_clk_path_.tag(sta)->isFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
@ -204,36 +235,15 @@ bool
|
||||||
ClkInfoEqual::operator()(const ClkInfo *clk_info1,
|
ClkInfoEqual::operator()(const ClkInfo *clk_info1,
|
||||||
const ClkInfo *clk_info2) const
|
const ClkInfo *clk_info2) const
|
||||||
{
|
{
|
||||||
return clkInfoEqual(clk_info1, clk_info2, sta_);
|
return ClkInfo::equal(clk_info1, clk_info2, sta_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
clkInfoEqual(const ClkInfo *clk_info1,
|
ClkInfo::equal(const ClkInfo *clk_info1,
|
||||||
const ClkInfo *clk_info2,
|
const ClkInfo *clk_info2,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
bool crpr_on = sta->crprActive();
|
return ClkInfo::cmp(clk_info1, clk_info2, sta) == 0;
|
||||||
ClockUncertainties *uncertainties1 = clk_info1->uncertainties();
|
|
||||||
ClockUncertainties *uncertainties2 = clk_info2->uncertainties();
|
|
||||||
return clk_info1->clkEdge() == clk_info2->clkEdge()
|
|
||||||
&& clk_info1->pathAPIndex() == clk_info2->pathAPIndex()
|
|
||||||
&& clk_info1->clkSrc() == clk_info2->clkSrc()
|
|
||||||
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
|
|
||||||
&& (!crpr_on
|
|
||||||
|| Path::equal(clk_info1->crprClkPath(sta),
|
|
||||||
clk_info2->crprClkPath(sta),
|
|
||||||
sta))
|
|
||||||
&& ((uncertainties1 == nullptr
|
|
||||||
&& uncertainties2 == nullptr)
|
|
||||||
|| (uncertainties1 && uncertainties2
|
|
||||||
&& MinMaxValues<float>::equal(uncertainties1,
|
|
||||||
uncertainties2)))
|
|
||||||
&& clk_info1->insertion() == clk_info2->insertion()
|
|
||||||
&& clk_info1->latency() == clk_info2->latency()
|
|
||||||
&& clk_info1->isPropagated() == clk_info2->isPropagated()
|
|
||||||
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
|
||||||
&& clk_info1->isPulseClk() == clk_info2->isPulseClk()
|
|
||||||
&& clk_info1->pulseClkSenseTrIndex() == clk_info2->pulseClkSenseTrIndex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -247,13 +257,13 @@ bool
|
||||||
ClkInfoLess::operator()(const ClkInfo *clk_info1,
|
ClkInfoLess::operator()(const ClkInfo *clk_info1,
|
||||||
const ClkInfo *clk_info2) const
|
const ClkInfo *clk_info2) const
|
||||||
{
|
{
|
||||||
return clkInfoCmp(clk_info1, clk_info2, sta_) < 0;
|
return ClkInfo::cmp(clk_info1, clk_info2, sta_) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
clkInfoCmp(const ClkInfo *clk_info1,
|
ClkInfo::cmp(const ClkInfo *clk_info1,
|
||||||
const ClkInfo *clk_info2,
|
const ClkInfo *clk_info2,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
const ClockEdge *clk_edge1 = clk_info1->clkEdge();
|
const ClockEdge *clk_edge1 = clk_info1->clkEdge();
|
||||||
const ClockEdge *clk_edge2 = clk_info2->clkEdge();
|
const ClockEdge *clk_edge2 = clk_info2->clkEdge();
|
||||||
|
|
@ -271,24 +281,29 @@ clkInfoCmp(const ClkInfo *clk_info1,
|
||||||
if (path_ap_index1 > path_ap_index2)
|
if (path_ap_index1 > path_ap_index2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
const Network *network = sta->network();
|
||||||
const Pin *clk_src1 = clk_info1->clkSrc();
|
const Pin *clk_src1 = clk_info1->clkSrc();
|
||||||
const Pin *clk_src2 = clk_info2->clkSrc();
|
const Pin *clk_src2 = clk_info2->clkSrc();
|
||||||
if (clk_src1 < clk_src2)
|
int clk_src_id1 = clk_src1 ? network->id(clk_src1) : -1;
|
||||||
|
int clk_src_id2 = clk_src2 ? network->id(clk_src2) : -1;
|
||||||
|
if (clk_src_id1 < clk_src_id2)
|
||||||
return -1;
|
return -1;
|
||||||
if (clk_src1 > clk_src2)
|
if (clk_src_id1 > clk_src_id2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const Pin *gen_clk_src1 = clk_info1->genClkSrc();
|
const Pin *gen_clk_src1 = clk_info1->genClkSrc();
|
||||||
const Pin *gen_clk_src2 = clk_info2->genClkSrc();
|
const Pin *gen_clk_src2 = clk_info2->genClkSrc();
|
||||||
if (gen_clk_src1 < gen_clk_src2)
|
int gen_clk_src_id1 = gen_clk_src1 ? network->id(gen_clk_src1) : -1;
|
||||||
|
int gen_clk_src_id2 = gen_clk_src2 ? network->id(gen_clk_src2) : -1;
|
||||||
|
if (gen_clk_src_id1 < gen_clk_src_id2)
|
||||||
return -1;
|
return -1;
|
||||||
if (gen_clk_src1 > gen_clk_src2)
|
if (gen_clk_src_id1 > gen_clk_src_id2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
bool crpr_on = sta->crprActive();
|
bool crpr_on = sta->crprActive();
|
||||||
if (crpr_on) {
|
if (crpr_on) {
|
||||||
const Path *crpr_path1 = clk_info1->crprClkPath(sta);
|
const Path *crpr_path1 = clk_info1->crprClkPathRaw();
|
||||||
const Path *crpr_path2 = clk_info2->crprClkPath(sta);
|
const Path *crpr_path2 = clk_info2->crprClkPathRaw();
|
||||||
int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta);
|
int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta);
|
||||||
if (path_cmp != 0)
|
if (path_cmp != 0)
|
||||||
return path_cmp;
|
return path_cmp;
|
||||||
|
|
@ -296,11 +311,15 @@ clkInfoCmp(const ClkInfo *clk_info1,
|
||||||
|
|
||||||
const ClockUncertainties *uncertainties1 = clk_info1->uncertainties();
|
const ClockUncertainties *uncertainties1 = clk_info1->uncertainties();
|
||||||
const ClockUncertainties *uncertainties2 = clk_info2->uncertainties();
|
const ClockUncertainties *uncertainties2 = clk_info2->uncertainties();
|
||||||
if (uncertainties1 < uncertainties2)
|
if (uncertainties1 == nullptr && uncertainties2)
|
||||||
return -1;
|
return -1;
|
||||||
if (uncertainties1 > uncertainties2)
|
if (uncertainties1 && uncertainties2 == nullptr)
|
||||||
return 1;
|
return 1;
|
||||||
|
if (uncertainties1 && uncertainties2) {
|
||||||
|
int uncertain_cmp = ClockUncertainties::cmp(uncertainties1, uncertainties2);
|
||||||
|
if (uncertain_cmp != 0)
|
||||||
|
return uncertain_cmp;
|
||||||
|
}
|
||||||
const Arrival &insert1 = clk_info1->insertion();
|
const Arrival &insert1 = clk_info1->insertion();
|
||||||
const Arrival &insert2 = clk_info2->insertion();
|
const Arrival &insert2 = clk_info2->insertion();
|
||||||
if (delayLess(insert1, insert2, sta))
|
if (delayLess(insert1, insert2, sta))
|
||||||
|
|
@ -336,8 +355,8 @@ clkInfoCmp(const ClkInfo *clk_info1,
|
||||||
if (is_pulse_clk1 && !is_pulse_clk2)
|
if (is_pulse_clk1 && !is_pulse_clk2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int pulse_clk_sense_index1 = clk_info1->pulseClkSenseTrIndex();
|
int pulse_clk_sense_index1 = clk_info1->pulseClkSenseRfIndex();
|
||||||
int pulse_clk_sense_index2 = clk_info2->pulseClkSenseTrIndex();
|
int pulse_clk_sense_index2 = clk_info2->pulseClkSenseRfIndex();
|
||||||
if (pulse_clk_sense_index1 < pulse_clk_sense_index2)
|
if (pulse_clk_sense_index1 < pulse_clk_sense_index2)
|
||||||
return -1;
|
return -1;
|
||||||
if (pulse_clk_sense_index1 > pulse_clk_sense_index2)
|
if (pulse_clk_sense_index1 > pulse_clk_sense_index2)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public:
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
Path *crpr_clk_path,
|
const Path *crpr_clk_path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
~ClkInfo();
|
~ClkInfo();
|
||||||
std::string to_string(const StaState *sta) const;
|
std::string to_string(const StaState *sta) const;
|
||||||
|
|
@ -57,7 +57,7 @@ public:
|
||||||
const Pin *genClkSrc() const { return gen_clk_src_; }
|
const Pin *genClkSrc() const { return gen_clk_src_; }
|
||||||
bool isPulseClk() const { return is_pulse_clk_; }
|
bool isPulseClk() const { return is_pulse_clk_; }
|
||||||
const RiseFall *pulseClkSense() const;
|
const RiseFall *pulseClkSense() const;
|
||||||
int pulseClkSenseTrIndex() const { return pulse_clk_sense_; }
|
int pulseClkSenseRfIndex() const { return pulse_clk_sense_; }
|
||||||
float latency() const { return latency_; }
|
float latency() const { return latency_; }
|
||||||
Arrival &insertion() { return insertion_; }
|
Arrival &insertion() { return insertion_; }
|
||||||
const Arrival &insertion() const { return insertion_; }
|
const Arrival &insertion() const { return insertion_; }
|
||||||
|
|
@ -69,11 +69,18 @@ public:
|
||||||
const Path *crprClkPath(const StaState *sta) const;
|
const Path *crprClkPath(const StaState *sta) const;
|
||||||
VertexId crprClkVertexId(const StaState *sta) const;
|
VertexId crprClkVertexId(const StaState *sta) const;
|
||||||
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
||||||
bool refsFilter(const StaState *sta) const;
|
|
||||||
// This clk_info/tag is used for a generated clock source path.
|
// This clk_info/tag is used for a generated clock source path.
|
||||||
bool isGenClkSrcPath() const { return is_gen_clk_src_path_; }
|
bool isGenClkSrcPath() const { return is_gen_clk_src_path_; }
|
||||||
size_t hash() const { return hash_; }
|
size_t hash() const { return hash_; }
|
||||||
|
bool crprPathRefsFilter() const { return crpr_path_refs_filter_; }
|
||||||
|
const Path *crprClkPathRaw() const;
|
||||||
|
|
||||||
|
static int cmp(const ClkInfo *clk_info1,
|
||||||
|
const ClkInfo *clk_info2,
|
||||||
|
const StaState *sta);
|
||||||
|
static bool equal(const ClkInfo *clk_info1,
|
||||||
|
const ClkInfo *clk_info2,
|
||||||
|
const StaState *sta);
|
||||||
protected:
|
protected:
|
||||||
void findHash(const StaState *sta);
|
void findHash(const StaState *sta);
|
||||||
|
|
||||||
|
|
@ -88,20 +95,14 @@ private:
|
||||||
size_t hash_;
|
size_t hash_;
|
||||||
bool is_propagated_:1;
|
bool is_propagated_:1;
|
||||||
bool is_gen_clk_src_path_:1;
|
bool is_gen_clk_src_path_:1;
|
||||||
|
// This is used to break a circular dependency in Search::deleteFilteredArrival
|
||||||
|
// between tags and clk infos that reference a filter.
|
||||||
|
bool crpr_path_refs_filter_:1;
|
||||||
bool is_pulse_clk_:1;
|
bool is_pulse_clk_:1;
|
||||||
unsigned int pulse_clk_sense_:RiseFall::index_bit_count;
|
unsigned int pulse_clk_sense_:RiseFall::index_bit_count;
|
||||||
unsigned int path_ap_index_:path_ap_index_bit_count;
|
unsigned int path_ap_index_:path_ap_index_bit_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
|
||||||
clkInfoCmp(const ClkInfo *clk_info1,
|
|
||||||
const ClkInfo *clk_info2,
|
|
||||||
const StaState *sta);
|
|
||||||
bool
|
|
||||||
clkInfoEqual(const ClkInfo *clk_info1,
|
|
||||||
const ClkInfo *clk_info2,
|
|
||||||
const StaState *sta);
|
|
||||||
|
|
||||||
class ClkInfoLess
|
class ClkInfoLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ ClkDelays::insertionDelay(Path *clk_path,
|
||||||
const ClockEdge *clk_edge = clk_path->clkEdge(sta);
|
const ClockEdge *clk_edge = clk_path->clkEdge(sta);
|
||||||
const Clock *clk = clk_edge->clock();
|
const Clock *clk = clk_edge->clock();
|
||||||
const RiseFall *clk_rf = clk_edge->transition();
|
const RiseFall *clk_rf = clk_edge->transition();
|
||||||
ClkInfo *clk_info = clk_path->clkInfo(sta);
|
const ClkInfo *clk_info = clk_path->clkInfo(sta);
|
||||||
const Pin *src_pin = clk_info->clkSrc();
|
const Pin *src_pin = clk_info->clkSrc();
|
||||||
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(sta);
|
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(sta);
|
||||||
const MinMax *min_max = clk_path->minMax(sta);
|
const MinMax *min_max = clk_path->minMax(sta);
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ CheckCrpr::CheckCrpr(StaState *sta) :
|
||||||
// Find the maximum possible crpr (clock min/max delta delay) for a
|
// Find the maximum possible crpr (clock min/max delta delay) for a
|
||||||
// path from it's ClkInfo.
|
// path from it's ClkInfo.
|
||||||
Arrival
|
Arrival
|
||||||
CheckCrpr::maxCrpr(ClkInfo *clk_info)
|
CheckCrpr::maxCrpr(const ClkInfo *clk_info)
|
||||||
{
|
{
|
||||||
const Path *crpr_clk_path = clk_info->crprClkPath(this);
|
const Path *crpr_clk_path = clk_info->crprClkPath(this);
|
||||||
if (crpr_clk_path) {
|
if (crpr_clk_path) {
|
||||||
|
|
@ -81,7 +81,7 @@ CheckCrpr::otherMinMaxArrival(const Path *path)
|
||||||
other_ap, this);
|
other_ap, this);
|
||||||
while (other_iter.hasNext()) {
|
while (other_iter.hasNext()) {
|
||||||
Path *other = other_iter.next();
|
Path *other = other_iter.next();
|
||||||
if (tagMatchCrpr(other->tag(this), tag))
|
if (Tag::matchCrpr(other->tag(this), tag))
|
||||||
return other->arrival();
|
return other->arrival();
|
||||||
}
|
}
|
||||||
// No corresponding path found.
|
// No corresponding path found.
|
||||||
|
|
@ -126,8 +126,8 @@ CheckCrpr::checkCrpr1(const Path *src_path,
|
||||||
crpr = 0.0;
|
crpr = 0.0;
|
||||||
crpr_pin = nullptr;
|
crpr_pin = nullptr;
|
||||||
const Tag *src_tag = src_path->tag(this);
|
const Tag *src_tag = src_path->tag(this);
|
||||||
ClkInfo *src_clk_info = src_tag->clkInfo();
|
const ClkInfo *src_clk_info = src_tag->clkInfo();
|
||||||
ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
|
const ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
|
||||||
const Clock *src_clk = src_clk_info->clock();
|
const Clock *src_clk = src_clk_info->clock();
|
||||||
const Clock *tgt_clk = tgt_clk_info->clock();
|
const Clock *tgt_clk = tgt_clk_info->clock();
|
||||||
const Path *src_clk_path = nullptr;
|
const Path *src_clk_path = nullptr;
|
||||||
|
|
@ -246,7 +246,7 @@ ConstPathSeq
|
||||||
CheckCrpr::genClkSrcPaths(const Path *path)
|
CheckCrpr::genClkSrcPaths(const Path *path)
|
||||||
{
|
{
|
||||||
ConstPathSeq gclk_paths;
|
ConstPathSeq gclk_paths;
|
||||||
ClkInfo *clk_info = path->clkInfo(this);
|
const ClkInfo *clk_info = path->clkInfo(this);
|
||||||
const ClockEdge *clk_edge = clk_info->clkEdge();
|
const ClockEdge *clk_edge = clk_info->clkEdge();
|
||||||
const Pin *clk_src = clk_info->clkSrc();
|
const Pin *clk_src = clk_info->clkSrc();
|
||||||
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
||||||
|
|
@ -350,7 +350,7 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path,
|
||||||
{
|
{
|
||||||
crpr = 0.0;
|
crpr = 0.0;
|
||||||
crpr_pin = nullptr;
|
crpr_pin = nullptr;
|
||||||
ClkInfo *src_clk_info = src_path->tag(this)->clkInfo();
|
const ClkInfo *src_clk_info = src_path->tag(this)->clkInfo();
|
||||||
const Clock *tgt_clk = tgt_clk_edge->clock();
|
const Clock *tgt_clk = tgt_clk_edge->clock();
|
||||||
const Clock *src_clk = src_path->clock(this);
|
const Clock *src_clk = src_path->clock(this);
|
||||||
if (src_clk && tgt_clk
|
if (src_clk && tgt_clk
|
||||||
|
|
@ -361,7 +361,7 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path,
|
||||||
Path *tgt_genclk_path = portClkPath(tgt_clk_edge,
|
Path *tgt_genclk_path = portClkPath(tgt_clk_edge,
|
||||||
tgt_clk_edge->clock()->defaultPin(),
|
tgt_clk_edge->clock()->defaultPin(),
|
||||||
tgt_path_ap);
|
tgt_path_ap);
|
||||||
Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this);
|
const Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this);
|
||||||
if (src_clk_path)
|
if (src_clk_path)
|
||||||
findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin);
|
findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ public:
|
||||||
explicit CheckCrpr(StaState *sta);
|
explicit CheckCrpr(StaState *sta);
|
||||||
|
|
||||||
// Find the maximum possible crpr (clock min/max delta delay) for path.
|
// Find the maximum possible crpr (clock min/max delta delay) for path.
|
||||||
Arrival maxCrpr(ClkInfo *clk_info);
|
Arrival maxCrpr(const ClkInfo *clk_info);
|
||||||
// Timing check CRPR.
|
// Timing check CRPR.
|
||||||
Crpr checkCrpr(const Path *src_clk_path,
|
Crpr checkCrpr(const Path *src_clk_path,
|
||||||
const Path *tgt_clk_path);
|
const Path *tgt_clk_path);
|
||||||
|
|
|
||||||
|
|
@ -711,12 +711,12 @@ Genclks::makeTag(const Clock *gclk,
|
||||||
state = state->nextState();
|
state = state->nextState();
|
||||||
ExceptionStateSet *states = new ExceptionStateSet();
|
ExceptionStateSet *states = new ExceptionStateSet();
|
||||||
states->insert(state);
|
states->insert(state);
|
||||||
ClkInfo *clk_info = search_->findClkInfo(master_clk->edge(master_rf),
|
const ClkInfo *clk_info = search_->findClkInfo(master_clk->edge(master_rf),
|
||||||
master_pin, true, nullptr, true,
|
master_pin, true, nullptr, true,
|
||||||
nullptr, insert, 0.0, nullptr,
|
nullptr, insert, 0.0, nullptr,
|
||||||
path_ap, nullptr);
|
path_ap, nullptr);
|
||||||
return search_->findTag(master_rf, path_ap, clk_info, false, nullptr, false,
|
return search_->findTag(master_rf, path_ap, clk_info, false,
|
||||||
states, true);
|
nullptr, false, states, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenClkArrivalSearchPred : public EvalPred
|
class GenClkArrivalSearchPred : public EvalPred
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ Latches::latchOutArrival(const Path *data_path,
|
||||||
tgt_clk_path_ap, this);
|
tgt_clk_path_ap, this);
|
||||||
while (enable_iter.hasNext()) {
|
while (enable_iter.hasNext()) {
|
||||||
Path *enable_path = enable_iter.next();
|
Path *enable_path = enable_iter.next();
|
||||||
ClkInfo *en_clk_info = enable_path->clkInfo(this);
|
const ClkInfo *en_clk_info = enable_path->clkInfo(this);
|
||||||
const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
|
const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
|
||||||
if (enable_path->isClock(this)) {
|
if (enable_path->isClock(this)) {
|
||||||
ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge);
|
ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge);
|
||||||
|
|
@ -353,7 +353,7 @@ Latches::latchOutArrival(const Path *data_path,
|
||||||
// Tag switcheroo - data passing thru gets latch enable tag.
|
// Tag switcheroo - data passing thru gets latch enable tag.
|
||||||
// States and path ap come from Q, everything else from enable.
|
// States and path ap come from Q, everything else from enable.
|
||||||
Path *crpr_clk_path = crprActive() ? enable_path : nullptr;
|
Path *crpr_clk_path = crprActive() ? enable_path : nullptr;
|
||||||
ClkInfo *q_clk_info =
|
const ClkInfo *q_clk_info =
|
||||||
search_->findClkInfo(en_clk_edge,
|
search_->findClkInfo(en_clk_edge,
|
||||||
en_clk_info->clkSrc(),
|
en_clk_info->clkSrc(),
|
||||||
en_clk_info->isPropagated(),
|
en_clk_info->isPropagated(),
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ Path::Path() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Path::Path(Path *path) :
|
Path::Path(const Path *path) :
|
||||||
prev_path_(path ? path->prev_path_ : nullptr),
|
prev_path_(path ? path->prev_path_ : nullptr),
|
||||||
arrival_(path ? path->arrival_ : 0.0),
|
arrival_(path ? path->arrival_ : 0.0),
|
||||||
required_(path ? path->required_ : 0.0),
|
required_(path ? path->required_ : 0.0),
|
||||||
|
|
@ -279,7 +279,7 @@ Path::pathIndex(const StaState *sta) const
|
||||||
return this - paths;
|
return this - paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClkInfo *
|
const ClkInfo *
|
||||||
Path::clkInfo(const StaState *sta) const
|
Path::clkInfo(const StaState *sta) const
|
||||||
{
|
{
|
||||||
return tag(sta)->clkInfo();
|
return tag(sta)->clkInfo();
|
||||||
|
|
@ -608,10 +608,20 @@ Path::cmp(const Path *path1,
|
||||||
const Path *path2,
|
const Path *path2,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path1 && path2) {
|
if (path1 == path2)
|
||||||
|
return 0;
|
||||||
|
else if (path1 == nullptr && path2)
|
||||||
|
return 1;
|
||||||
|
else if (path1 && path2 == nullptr)
|
||||||
|
return -1;
|
||||||
|
else {
|
||||||
VertexId vertex_id1 = path1->vertexId(sta);
|
VertexId vertex_id1 = path1->vertexId(sta);
|
||||||
VertexId vertex_id2 = path2->vertexId(sta);
|
VertexId vertex_id2 = path2->vertexId(sta);
|
||||||
if (vertex_id1 == vertex_id2) {
|
if (vertex_id1 < vertex_id2)
|
||||||
|
return -1;
|
||||||
|
else if (vertex_id1 > vertex_id2)
|
||||||
|
return 1;
|
||||||
|
else {
|
||||||
TagIndex tag_index1 = path1->tagIndex(sta);
|
TagIndex tag_index1 = path1->tagIndex(sta);
|
||||||
TagIndex tag_index2 = path2->tagIndex(sta);
|
TagIndex tag_index2 = path2->tagIndex(sta);
|
||||||
if (tag_index1 == tag_index2)
|
if (tag_index1 == tag_index2)
|
||||||
|
|
@ -621,18 +631,7 @@ Path::cmp(const Path *path1,
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (vertex_id1 < vertex_id2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
else if (path1 == nullptr
|
|
||||||
&& path2 == nullptr)
|
|
||||||
return 0;
|
|
||||||
else if (path1 == nullptr)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -643,7 +642,7 @@ Path::cmpNoCrpr(const Path *path1,
|
||||||
VertexId vertex_id1 = path1->vertexId(sta);
|
VertexId vertex_id1 = path1->vertexId(sta);
|
||||||
VertexId vertex_id2 = path2->vertexId(sta);
|
VertexId vertex_id2 = path2->vertexId(sta);
|
||||||
if (vertex_id1 == vertex_id2)
|
if (vertex_id1 == vertex_id2)
|
||||||
return tagMatchCmp(path1->tag(sta), path2->tag(sta), false, sta);
|
return Tag::matchCmp(path1->tag(sta), path2->tag(sta), false, sta);
|
||||||
else if (vertex_id1 < vertex_id2)
|
else if (vertex_id1 < vertex_id2)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ PathEnd::checkTgtClkDelay(const Path *tgt_clk_path,
|
||||||
const MinMax *min_max = tgt_clk_path->minMax(sta);
|
const MinMax *min_max = tgt_clk_path->minMax(sta);
|
||||||
const EarlyLate *early_late = check_role->tgtClkEarlyLate();
|
const EarlyLate *early_late = check_role->tgtClkEarlyLate();
|
||||||
const PathAnalysisPt *tgt_path_ap = tgt_clk_path->pathAnalysisPt(sta);
|
const PathAnalysisPt *tgt_path_ap = tgt_clk_path->pathAnalysisPt(sta);
|
||||||
ClkInfo *clk_info = tgt_clk_path->clkInfo(sta);
|
const ClkInfo *clk_info = tgt_clk_path->clkInfo(sta);
|
||||||
const Pin *tgt_src_pin = clk_info->clkSrc();
|
const Pin *tgt_src_pin = clk_info->clkSrc();
|
||||||
const Clock *tgt_clk = tgt_clk_edge->clock();
|
const Clock *tgt_clk = tgt_clk_edge->clock();
|
||||||
const RiseFall *tgt_clk_rf = tgt_clk_edge->transition();
|
const RiseFall *tgt_clk_rf = tgt_clk_edge->transition();
|
||||||
|
|
@ -560,14 +560,14 @@ PathEndClkConstrained::sourceClkOffset(const ClockEdge *src_clk_edge,
|
||||||
Arrival
|
Arrival
|
||||||
PathEndClkConstrained::sourceClkLatency(const StaState *sta) const
|
PathEndClkConstrained::sourceClkLatency(const StaState *sta) const
|
||||||
{
|
{
|
||||||
ClkInfo *clk_info = path_->clkInfo(sta);
|
const ClkInfo *clk_info = path_->clkInfo(sta);
|
||||||
return clk_info->latency();
|
return clk_info->latency();
|
||||||
}
|
}
|
||||||
|
|
||||||
Arrival
|
Arrival
|
||||||
PathEndClkConstrained::sourceClkInsertionDelay(const StaState *sta) const
|
PathEndClkConstrained::sourceClkInsertionDelay(const StaState *sta) const
|
||||||
{
|
{
|
||||||
ClkInfo *clk_info = path_->clkInfo(sta);
|
const ClkInfo *clk_info = path_->clkInfo(sta);
|
||||||
return clk_info->insertion();
|
return clk_info->insertion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1033,7 +1033,7 @@ PathEndCheck::sourceClkDelay(const StaState *sta) const
|
||||||
PathExpanded expanded(path_, sta);
|
PathExpanded expanded(path_, sta);
|
||||||
const Path *src_clk_path = expanded.clkPath();
|
const Path *src_clk_path = expanded.clkPath();
|
||||||
if (src_clk_path) {
|
if (src_clk_path) {
|
||||||
ClkInfo *src_clk_info = path_->tag(sta)->clkInfo();
|
const ClkInfo *src_clk_info = path_->tag(sta)->clkInfo();
|
||||||
if (src_clk_info->isPropagated()) {
|
if (src_clk_info->isPropagated()) {
|
||||||
// Propagated clock. Propagated arrival is seeded with insertion delay.
|
// Propagated clock. Propagated arrival is seeded with insertion delay.
|
||||||
Arrival clk_arrival = src_clk_path->arrival();
|
Arrival clk_arrival = src_clk_path->arrival();
|
||||||
|
|
@ -1280,7 +1280,7 @@ PathEndLatchCheck::targetClkWidth(const StaState *sta) const
|
||||||
const Search *search = sta->search();
|
const Search *search = sta->search();
|
||||||
Arrival disable_arrival = search->clkPathArrival(disable_path_);
|
Arrival disable_arrival = search->clkPathArrival(disable_path_);
|
||||||
Arrival enable_arrival = search->clkPathArrival(clk_path_);
|
Arrival enable_arrival = search->clkPathArrival(clk_path_);
|
||||||
ClkInfo *enable_clk_info = clk_path_->clkInfo(sta);
|
const ClkInfo *enable_clk_info = clk_path_->clkInfo(sta);
|
||||||
if (enable_clk_info->isPulseClk())
|
if (enable_clk_info->isPulseClk())
|
||||||
return disable_arrival - enable_arrival;
|
return disable_arrival - enable_arrival;
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
||||||
// These paths fanin to before_div_ so we know to_vertex matches.
|
// These paths fanin to before_div_ so we know to_vertex matches.
|
||||||
if ((!unique_pins_ || from_vertex != prev_vertex_)
|
if ((!unique_pins_ || from_vertex != prev_vertex_)
|
||||||
&& arc != prev_arc_
|
&& arc != prev_arc_
|
||||||
&& tagMatchNoCrpr(to_tag, before_div_tag_)) {
|
&& Tag::matchNoCrpr(to_tag, before_div_tag_)) {
|
||||||
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
|
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
|
||||||
from_path->to_string(this).c_str(),
|
from_path->to_string(this).c_str(),
|
||||||
to_vertex->to_string(this).c_str(),
|
to_vertex->to_string(this).c_str(),
|
||||||
|
|
@ -644,7 +644,7 @@ PathEnum::updatePathHeadDelays(PathSeq &paths,
|
||||||
Path *after_div)
|
Path *after_div)
|
||||||
{
|
{
|
||||||
Tag *prev_tag = after_div->tag(this);
|
Tag *prev_tag = after_div->tag(this);
|
||||||
ClkInfo *prev_clk_info = prev_tag->clkInfo();
|
const ClkInfo *prev_clk_info = prev_tag->clkInfo();
|
||||||
Arrival prev_arrival = search_->clkPathArrival(after_div);
|
Arrival prev_arrival = search_->clkPathArrival(after_div);
|
||||||
int path_idx_max = paths.size() - 1;
|
int path_idx_max = paths.size() - 1;
|
||||||
// paths[0] is the path endpoint
|
// paths[0] is the path endpoint
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
|
||||||
other_ap, sta_);
|
other_ap, sta_);
|
||||||
while (other_iter.hasNext()) {
|
while (other_iter.hasNext()) {
|
||||||
Path *other = other_iter.next();
|
Path *other = other_iter.next();
|
||||||
if (tagMatchCrpr(other->tag(sta_), tag)) {
|
if (Tag::matchCrpr(other->tag(sta_), tag)) {
|
||||||
PathEnd *end_min = path_end->copy();
|
PathEnd *end_min = path_end->copy();
|
||||||
end_min->setPath(other);
|
end_min->setPath(other);
|
||||||
float slack = delayAsFloat(end_min->slackNoCrpr(sta_));
|
float slack = delayAsFloat(end_min->slackNoCrpr(sta_));
|
||||||
|
|
|
||||||
|
|
@ -1240,8 +1240,14 @@ Properties::getProperty(const Clock *clk,
|
||||||
return PropertyValue(clk->isVirtual());
|
return PropertyValue(clk->isVirtual());
|
||||||
else if (property == "is_propagated")
|
else if (property == "is_propagated")
|
||||||
return PropertyValue(clk->isPropagated());
|
return PropertyValue(clk->isPropagated());
|
||||||
else
|
else {
|
||||||
throw PropertyUnknown("clock", property);
|
PropertyValue value = registry_clock_.getProperty(clk, property,
|
||||||
|
"clock", sta_);
|
||||||
|
if (value.type() != PropertyValue::Type::type_none)
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
throw PropertyUnknown("clock", property);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -1376,6 +1382,13 @@ Properties::defineProperty(std::string &property,
|
||||||
registry_net_.defineProperty(property, handler);
|
registry_net_.defineProperty(property, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Properties::defineProperty(std::string &property,
|
||||||
|
PropertyRegistry<const Clock *>::PropertyHandler handler)
|
||||||
|
{
|
||||||
|
registry_clock_.defineProperty(property, handler);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TYPE>
|
template<class TYPE>
|
||||||
|
|
|
||||||
|
|
@ -2112,7 +2112,7 @@ ReportPath::reportSrcClkAndPath(const Path *path,
|
||||||
else if (clk_used_as_data
|
else if (clk_used_as_data
|
||||||
&& pathFromGenPropClk(path, path->minMax(this))) {
|
&& pathFromGenPropClk(path, path->minMax(this))) {
|
||||||
reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time, min_max);
|
reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time, min_max);
|
||||||
ClkInfo *clk_info = path->tag(search_)->clkInfo();
|
const ClkInfo *clk_info = path->tag(search_)->clkInfo();
|
||||||
if (clk_info->isPropagated())
|
if (clk_info->isPropagated())
|
||||||
reportClkSrcLatency(clk_insertion, clk_time, early_late);
|
reportClkSrcLatency(clk_insertion, clk_time, early_late);
|
||||||
reportPath1(path, expanded, true, time_offset);
|
reportPath1(path, expanded, true, time_offset);
|
||||||
|
|
@ -2259,7 +2259,7 @@ ReportPath::tgtClkInsertionOffet(const Path *clk_path,
|
||||||
const EarlyLate *early_late,
|
const EarlyLate *early_late,
|
||||||
const PathAnalysisPt *path_ap) const
|
const PathAnalysisPt *path_ap) const
|
||||||
{
|
{
|
||||||
ClkInfo *clk_info = clk_path->clkInfo(this);
|
const ClkInfo *clk_info = clk_path->clkInfo(this);
|
||||||
const Pin *src_pin = clk_info->clkSrc();
|
const Pin *src_pin = clk_info->clkSrc();
|
||||||
const ClockEdge *clk_edge = clk_info->clkEdge();
|
const ClockEdge *clk_edge = clk_info->clkEdge();
|
||||||
const Clock *clk = clk_edge->clock();
|
const Clock *clk = clk_edge->clock();
|
||||||
|
|
@ -2278,7 +2278,7 @@ bool
|
||||||
ReportPath::pathFromGenPropClk(const Path *clk_path,
|
ReportPath::pathFromGenPropClk(const Path *clk_path,
|
||||||
const EarlyLate *early_late) const
|
const EarlyLate *early_late) const
|
||||||
{
|
{
|
||||||
ClkInfo *clk_info = clk_path->tag(search_)->clkInfo();
|
const ClkInfo *clk_info = clk_path->tag(search_)->clkInfo();
|
||||||
const ClockEdge *clk_edge = clk_info->clkEdge();
|
const ClockEdge *clk_edge = clk_info->clkEdge();
|
||||||
if (clk_edge) {
|
if (clk_edge) {
|
||||||
const Clock *clk = clk_edge->clock();
|
const Clock *clk = clk_edge->clock();
|
||||||
|
|
@ -2393,7 +2393,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
|
||||||
const Path *src_path = search_->genclks()->srcPath(clk, clk_pin,
|
const Path *src_path = search_->genclks()->srcPath(clk, clk_pin,
|
||||||
clk_rf, insert_ap);
|
clk_rf, insert_ap);
|
||||||
if (src_path) {
|
if (src_path) {
|
||||||
ClkInfo *src_clk_info = src_path->clkInfo(this);
|
const ClkInfo *src_clk_info = src_path->clkInfo(this);
|
||||||
const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
|
const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
|
||||||
const Clock *src_clk = src_clk_info->clock();
|
const Clock *src_clk = src_clk_info->clock();
|
||||||
if (src_clk) {
|
if (src_clk) {
|
||||||
|
|
|
||||||
120
search/Search.cc
120
search/Search.cc
|
|
@ -235,7 +235,7 @@ Search::init(StaState *sta)
|
||||||
arrival_iter_ = new BfsFwdIterator(BfsIndex::arrival, nullptr, sta);
|
arrival_iter_ = new BfsFwdIterator(BfsIndex::arrival, nullptr, sta);
|
||||||
required_iter_ = new BfsBkwdIterator(BfsIndex::required, search_adj_, sta);
|
required_iter_ = new BfsBkwdIterator(BfsIndex::required, search_adj_, sta);
|
||||||
tag_capacity_ = 128;
|
tag_capacity_ = 128;
|
||||||
tag_set_ = new TagSet(tag_capacity_);
|
tag_set_ = new TagSet(tag_capacity_, TagHash(sta), TagEqual(sta));
|
||||||
clk_info_set_ = new ClkInfoSet(ClkInfoLess(sta));
|
clk_info_set_ = new ClkInfoSet(ClkInfoLess(sta));
|
||||||
tag_next_ = 0;
|
tag_next_ = 0;
|
||||||
tags_ = new Tag*[tag_capacity_];
|
tags_ = new Tag*[tag_capacity_];
|
||||||
|
|
@ -543,8 +543,8 @@ Search::deleteFilteredArrivals()
|
||||||
}
|
}
|
||||||
filtered_arrivals_->clear();
|
filtered_arrivals_->clear();
|
||||||
deleteFilterTagGroups();
|
deleteFilterTagGroups();
|
||||||
deleteFilterClkInfos();
|
|
||||||
deleteFilterTags();
|
deleteFilterTags();
|
||||||
|
deleteFilterClkInfos();
|
||||||
}
|
}
|
||||||
deleteFilter();
|
deleteFilter();
|
||||||
}
|
}
|
||||||
|
|
@ -576,7 +576,8 @@ Search::deleteFilterTags()
|
||||||
for (TagIndex i = 0; i < tag_next_; i++) {
|
for (TagIndex i = 0; i < tag_next_; i++) {
|
||||||
Tag *tag = tags_[i];
|
Tag *tag = tags_[i];
|
||||||
if (tag
|
if (tag
|
||||||
&& tag->isFilter()) {
|
&& (tag->isFilter()
|
||||||
|
|| tag->clkInfo()->crprPathRefsFilter())) {
|
||||||
tags_[i] = nullptr;
|
tags_[i] = nullptr;
|
||||||
tag_set_->erase(tag);
|
tag_set_->erase(tag);
|
||||||
delete tag;
|
delete tag;
|
||||||
|
|
@ -589,13 +590,13 @@ void
|
||||||
Search::deleteFilterClkInfos()
|
Search::deleteFilterClkInfos()
|
||||||
{
|
{
|
||||||
for (auto itr = clk_info_set_->cbegin(); itr != clk_info_set_->cend(); ) {
|
for (auto itr = clk_info_set_->cbegin(); itr != clk_info_set_->cend(); ) {
|
||||||
ClkInfo *clk_info = *itr;
|
const ClkInfo *clk_info = *itr;
|
||||||
if (clk_info->refsFilter(this)) {
|
if (clk_info->crprPathRefsFilter()) {
|
||||||
itr = clk_info_set_->erase(itr);
|
itr = clk_info_set_->erase(itr);
|
||||||
delete clk_info;
|
delete clk_info;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
itr++;
|
itr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,8 +615,7 @@ Search::findFilteredArrivals(bool thru_latches)
|
||||||
if (thru_latches)
|
if (thru_latches)
|
||||||
enqueuePendingLatchOutputs();
|
enqueuePendingLatchOutputs();
|
||||||
debugPrint(debug_, "search", 1, "find arrivals pass %d", pass);
|
debugPrint(debug_, "search", 1, "find arrivals pass %d", pass);
|
||||||
int arrival_count = arrival_iter_->visitParallel(max_level,
|
int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_);
|
||||||
arrival_visitor_);
|
|
||||||
deleteTagsPrev();
|
deleteTagsPrev();
|
||||||
debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
|
debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
|
||||||
}
|
}
|
||||||
|
|
@ -1216,11 +1216,10 @@ ArrivalVisitor::visit(Vertex *vertex)
|
||||||
// If vertex is a latch data input arrival that changed from the
|
// If vertex is a latch data input arrival that changed from the
|
||||||
// previous eval pass enqueue the latch outputs to be re-evaled on the
|
// previous eval pass enqueue the latch outputs to be re-evaled on the
|
||||||
// next pass.
|
// next pass.
|
||||||
if (network_->isLatchData(pin)) {
|
if (arrivals_changed
|
||||||
if (arrivals_changed
|
&& network_->isLatchData(pin))
|
||||||
&& network_->isLatchData(pin))
|
search_->enqueueLatchDataOutputs(vertex);
|
||||||
search_->enqueueLatchDataOutputs(vertex);
|
|
||||||
}
|
|
||||||
if (!search_->arrivalsAtEndpointsExist()
|
if (!search_->arrivalsAtEndpointsExist()
|
||||||
|| always_to_endpoints_
|
|| always_to_endpoints_
|
||||||
|| arrivals_changed)
|
|| arrivals_changed)
|
||||||
|
|
@ -1326,7 +1325,7 @@ ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */,
|
||||||
from_tag->to_string(this).c_str());
|
from_tag->to_string(this).c_str());
|
||||||
debugPrint(debug_, "search", 3, " to tag : %s",
|
debugPrint(debug_, "search", 3, " to tag : %s",
|
||||||
to_tag->to_string(this).c_str());
|
to_tag->to_string(this).c_str());
|
||||||
ClkInfo *to_clk_info = to_tag->clkInfo();
|
const ClkInfo *to_clk_info = to_tag->clkInfo();
|
||||||
bool to_is_clk = to_tag->isClock();
|
bool to_is_clk = to_tag->isClock();
|
||||||
Path *match;
|
Path *match;
|
||||||
size_t path_index;
|
size_t path_index;
|
||||||
|
|
@ -1363,7 +1362,7 @@ ArrivalVisitor::pruneCrprArrivals()
|
||||||
for (auto path_itr = path_index_map.cbegin(); path_itr != path_index_map.cend(); ) {
|
for (auto path_itr = path_index_map.cbegin(); path_itr != path_index_map.cend(); ) {
|
||||||
Tag *tag = path_itr->first;
|
Tag *tag = path_itr->first;
|
||||||
size_t path_index = path_itr->second;
|
size_t path_index = path_itr->second;
|
||||||
ClkInfo *clk_info = tag->clkInfo();
|
const ClkInfo *clk_info = tag->clkInfo();
|
||||||
bool deleted_tag = false;
|
bool deleted_tag = false;
|
||||||
if (!tag->isClock()
|
if (!tag->isClock()
|
||||||
&& clk_info->hasCrprClkPin()) {
|
&& clk_info->hasCrprClkPin()) {
|
||||||
|
|
@ -1372,7 +1371,7 @@ ArrivalVisitor::pruneCrprArrivals()
|
||||||
Path *path_no_crpr = tag_bldr_no_crpr_->tagMatchPath(tag);
|
Path *path_no_crpr = tag_bldr_no_crpr_->tagMatchPath(tag);
|
||||||
if (path_no_crpr) {
|
if (path_no_crpr) {
|
||||||
Arrival max_arrival = path_no_crpr->arrival();
|
Arrival max_arrival = path_no_crpr->arrival();
|
||||||
ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this);
|
const ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this);
|
||||||
Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr);
|
Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr);
|
||||||
Arrival max_arrival_max_crpr = (min_max == MinMax::max())
|
Arrival max_arrival_max_crpr = (min_max == MinMax::max())
|
||||||
? max_arrival - max_crpr
|
? max_arrival - max_crpr
|
||||||
|
|
@ -1610,9 +1609,9 @@ Search::seedClkArrival(const Pin *pin,
|
||||||
// Propagate liberty "pulse_clock" transition to transitive fanout.
|
// Propagate liberty "pulse_clock" transition to transitive fanout.
|
||||||
LibertyPort *port = network_->libertyPort(pin);
|
LibertyPort *port = network_->libertyPort(pin);
|
||||||
const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr);
|
const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr);
|
||||||
ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, nullptr, false,
|
const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, nullptr, false,
|
||||||
pulse_clk_sense, insertion, latency,
|
pulse_clk_sense, insertion, latency,
|
||||||
uncertainties, path_ap, nullptr);
|
uncertainties, path_ap, nullptr);
|
||||||
// Only false_paths -from apply to clock tree pins.
|
// Only false_paths -from apply to clock tree pins.
|
||||||
ExceptionStateSet *states = nullptr;
|
ExceptionStateSet *states = nullptr;
|
||||||
sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states);
|
sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states);
|
||||||
|
|
@ -1652,8 +1651,8 @@ Search::clkDataTag(const Pin *pin,
|
||||||
if (sdc_->exceptionFromStates(pin, rf, clk, rf, min_max, states)) {
|
if (sdc_->exceptionFromStates(pin, rf, clk, rf, min_max, states)) {
|
||||||
bool is_propagated = (clk->isPropagated()
|
bool is_propagated = (clk->isPropagated()
|
||||||
|| sdc_->isPropagatedClock(pin));
|
|| sdc_->isPropagatedClock(pin));
|
||||||
ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated,
|
const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated,
|
||||||
insertion, path_ap);
|
insertion, path_ap);
|
||||||
return findTag(rf, path_ap, clk_info, false, nullptr, false, states, true);
|
return findTag(rf, path_ap, clk_info, false, nullptr, false, states, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1888,7 +1887,7 @@ Search::inputDelayRefPinArrival(Path *ref_path,
|
||||||
{
|
{
|
||||||
Clock *clk = clk_edge->clock();
|
Clock *clk = clk_edge->clock();
|
||||||
if (clk->isPropagated()) {
|
if (clk->isPropagated()) {
|
||||||
ClkInfo *clk_info = ref_path->clkInfo(this);
|
const ClkInfo *clk_info = ref_path->clkInfo(this);
|
||||||
ref_arrival = delayAsFloat(ref_path->arrival());
|
ref_arrival = delayAsFloat(ref_path->arrival());
|
||||||
ref_insertion = delayAsFloat(clk_info->insertion());
|
ref_insertion = delayAsFloat(clk_info->insertion());
|
||||||
ref_latency = clk_info->latency();
|
ref_latency = clk_info->latency();
|
||||||
|
|
@ -2011,15 +2010,15 @@ Search::inputDelayTag(const Pin *pin,
|
||||||
ExceptionStateSet *states = nullptr;
|
ExceptionStateSet *states = nullptr;
|
||||||
Tag *tag = nullptr;
|
Tag *tag = nullptr;
|
||||||
if (sdc_->exceptionFromStates(pin,rf,clk,clk_rf,min_max,states)) {
|
if (sdc_->exceptionFromStates(pin,rf,clk,clk_rf,min_max,states)) {
|
||||||
ClkInfo *clk_info = findClkInfo(clk_edge, clk_pin, is_propagated, nullptr,
|
const ClkInfo *clk_info = findClkInfo(clk_edge, clk_pin, is_propagated, nullptr,
|
||||||
false, nullptr, clk_insertion, clk_latency,
|
false, nullptr, clk_insertion, clk_latency,
|
||||||
clk_uncertainties, path_ap, nullptr);
|
clk_uncertainties, path_ap, nullptr);
|
||||||
tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start,
|
tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start,
|
||||||
states, true);
|
states, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag) {
|
if (tag) {
|
||||||
ClkInfo *clk_info = tag->clkInfo();
|
const ClkInfo *clk_info = tag->clkInfo();
|
||||||
// Check for state changes on existing tag exceptions (pending -thru pins).
|
// Check for state changes on existing tag exceptions (pending -thru pins).
|
||||||
tag = mutateTag(tag, pin, rf, false, clk_info,
|
tag = mutateTag(tag, pin, rf, false, clk_info,
|
||||||
pin, rf, false, false, is_segment_start, clk_info,
|
pin, rf, false, false, is_segment_start, clk_info,
|
||||||
|
|
@ -2151,7 +2150,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|
||||||
{
|
{
|
||||||
const TimingRole *role = edge->role();
|
const TimingRole *role = edge->role();
|
||||||
Tag *from_tag = from_path->tag(this);
|
Tag *from_tag = from_path->tag(this);
|
||||||
ClkInfo *from_clk_info = from_tag->clkInfo();
|
const ClkInfo *from_clk_info = from_tag->clkInfo();
|
||||||
Tag *to_tag = nullptr;
|
Tag *to_tag = nullptr;
|
||||||
const ClockEdge *clk_edge = from_clk_info->clkEdge();
|
const ClockEdge *clk_edge = from_clk_info->clkEdge();
|
||||||
const Clock *clk = from_clk_info->clock();
|
const Clock *clk = from_clk_info->clock();
|
||||||
|
|
@ -2221,7 +2220,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|
||||||
// passed thru reg/latch D->Q edges.
|
// passed thru reg/latch D->Q edges.
|
||||||
&& from_tag->isClock())) {
|
&& from_tag->isClock())) {
|
||||||
const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr;
|
const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr;
|
||||||
ClkInfo *to_clk_info = from_clk_info;
|
const ClkInfo *to_clk_info = from_clk_info;
|
||||||
if (from_clk_info->crprClkPath(this) == nullptr
|
if (from_clk_info->crprClkPath(this) == nullptr
|
||||||
|| network_->direction(to_pin)->isInternal())
|
|| network_->direction(to_pin)->isInternal())
|
||||||
to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info,
|
to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info,
|
||||||
|
|
@ -2304,7 +2303,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|
||||||
Arrival
|
Arrival
|
||||||
Search::clkPathArrival(const Path *clk_path) const
|
Search::clkPathArrival(const Path *clk_path) const
|
||||||
{
|
{
|
||||||
ClkInfo *clk_info = clk_path->clkInfo(this);
|
const ClkInfo *clk_info = clk_path->clkInfo(this);
|
||||||
const ClockEdge *clk_edge = clk_info->clkEdge();
|
const ClockEdge *clk_edge = clk_info->clkEdge();
|
||||||
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
|
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
|
||||||
const MinMax *min_max = path_ap->pathMinMax();
|
const MinMax *min_max = path_ap->pathMinMax();
|
||||||
|
|
@ -2313,7 +2312,7 @@ Search::clkPathArrival(const Path *clk_path) const
|
||||||
|
|
||||||
Arrival
|
Arrival
|
||||||
Search::clkPathArrival(const Path *clk_path,
|
Search::clkPathArrival(const Path *clk_path,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
const ClockEdge *clk_edge,
|
const ClockEdge *clk_edge,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap) const
|
const PathAnalysisPt *path_ap) const
|
||||||
|
|
@ -2338,7 +2337,7 @@ Search::clkPathArrival(const Path *clk_path,
|
||||||
Arrival
|
Arrival
|
||||||
Search::pathClkPathArrival(const Path *path) const
|
Search::pathClkPathArrival(const Path *path) const
|
||||||
{
|
{
|
||||||
ClkInfo *clk_info = path->clkInfo(this);
|
const ClkInfo *clk_info = path->clkInfo(this);
|
||||||
if (clk_info->isPropagated()) {
|
if (clk_info->isPropagated()) {
|
||||||
const Path *src_clk_path = pathClkPathArrival1(path);
|
const Path *src_clk_path = pathClkPathArrival1(path);
|
||||||
if (src_clk_path)
|
if (src_clk_path)
|
||||||
|
|
@ -2393,7 +2392,7 @@ Search::fromUnclkedInputTag(const Pin *pin,
|
||||||
ExceptionStateSet *states = nullptr;
|
ExceptionStateSet *states = nullptr;
|
||||||
if (sdc_->exceptionFromStates(pin, rf, nullptr, nullptr, min_max, states)
|
if (sdc_->exceptionFromStates(pin, rf, nullptr, nullptr, min_max, states)
|
||||||
&& (!require_exception || states)) {
|
&& (!require_exception || states)) {
|
||||||
ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap);
|
const ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap);
|
||||||
return findTag(rf, path_ap, clk_info, false, nullptr,
|
return findTag(rf, path_ap, clk_info, false, nullptr,
|
||||||
is_segment_start, states, true);
|
is_segment_start, states, true);
|
||||||
}
|
}
|
||||||
|
|
@ -2405,7 +2404,7 @@ Search::fromRegClkTag(const Pin *from_pin,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
const Clock *clk,
|
const Clock *clk,
|
||||||
const RiseFall *clk_rf,
|
const RiseFall *clk_rf,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
const Pin *to_pin,
|
const Pin *to_pin,
|
||||||
const RiseFall *to_rf,
|
const RiseFall *to_rf,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
|
|
@ -2423,8 +2422,8 @@ Search::fromRegClkTag(const Pin *from_pin,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert from_path as ClkInfo crpr_clk_path.
|
// Insert from_path as ClkInfo crpr_clk_path.
|
||||||
ClkInfo *
|
const ClkInfo *
|
||||||
Search::clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
|
Search::clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
|
||||||
Path *from_path,
|
Path *from_path,
|
||||||
const PathAnalysisPt *path_ap)
|
const PathAnalysisPt *path_ap)
|
||||||
{
|
{
|
||||||
|
|
@ -2456,7 +2455,7 @@ Search::thruTag(Tag *from_tag,
|
||||||
Vertex *to_vertex = edge->to(graph_);
|
Vertex *to_vertex = edge->to(graph_);
|
||||||
const Pin *to_pin = to_vertex->pin();
|
const Pin *to_pin = to_vertex->pin();
|
||||||
const RiseFall *from_rf = from_tag->transition();
|
const RiseFall *from_rf = from_tag->transition();
|
||||||
ClkInfo *from_clk_info = from_tag->clkInfo();
|
const ClkInfo *from_clk_info = from_tag->clkInfo();
|
||||||
bool to_is_reg_clk = to_vertex->isRegClk();
|
bool to_is_reg_clk = to_vertex->isRegClk();
|
||||||
Tag *to_tag = mutateTag(from_tag, from_pin, from_rf, false, from_clk_info,
|
Tag *to_tag = mutateTag(from_tag, from_pin, from_rf, false, from_clk_info,
|
||||||
to_pin, to_rf, false, to_is_reg_clk, false,
|
to_pin, to_rf, false, to_is_reg_clk, false,
|
||||||
|
|
@ -2481,7 +2480,7 @@ Search::thruClkTag(Path *from_path,
|
||||||
Vertex *to_vertex = edge->to(graph_);
|
Vertex *to_vertex = edge->to(graph_);
|
||||||
const Pin *to_pin = to_vertex->pin();
|
const Pin *to_pin = to_vertex->pin();
|
||||||
const RiseFall *from_rf = from_tag->transition();
|
const RiseFall *from_rf = from_tag->transition();
|
||||||
ClkInfo *from_clk_info = from_tag->clkInfo();
|
const ClkInfo *from_clk_info = from_tag->clkInfo();
|
||||||
bool from_is_clk = from_tag->isClock();
|
bool from_is_clk = from_tag->isClock();
|
||||||
bool to_is_reg_clk = to_vertex->isRegClk();
|
bool to_is_reg_clk = to_vertex->isRegClk();
|
||||||
const TimingRole *role = edge->role();
|
const TimingRole *role = edge->role();
|
||||||
|
|
@ -2489,19 +2488,20 @@ Search::thruClkTag(Path *from_path,
|
||||||
&& to_propagates_clk
|
&& to_propagates_clk
|
||||||
&& (role->isWire()
|
&& (role->isWire()
|
||||||
|| role == TimingRole::combinational()));
|
|| role == TimingRole::combinational()));
|
||||||
ClkInfo *to_clk_info = thruClkInfo(from_path, from_vertex, from_clk_info, from_is_clk,
|
const ClkInfo *to_clk_info = thruClkInfo(from_path, from_vertex,
|
||||||
edge, to_vertex, to_pin, to_is_clk,
|
from_clk_info, from_is_clk,
|
||||||
arc_delay_min_max_eq, min_max, path_ap);
|
edge, to_vertex, to_pin, to_is_clk,
|
||||||
|
arc_delay_min_max_eq, min_max, path_ap);
|
||||||
Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info,
|
Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info,
|
||||||
to_pin, to_rf, to_is_clk, to_is_reg_clk, false,
|
to_pin, to_rf, to_is_clk, to_is_reg_clk, false,
|
||||||
to_clk_info, nullptr, min_max, path_ap);
|
to_clk_info, nullptr, min_max, path_ap);
|
||||||
return to_tag;
|
return to_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClkInfo *
|
const ClkInfo *
|
||||||
Search::thruClkInfo(Path *from_path,
|
Search::thruClkInfo(Path *from_path,
|
||||||
Vertex *from_vertex,
|
Vertex *from_vertex,
|
||||||
ClkInfo *from_clk_info,
|
const ClkInfo *from_clk_info,
|
||||||
bool from_is_clk,
|
bool from_is_clk,
|
||||||
Edge *edge,
|
Edge *edge,
|
||||||
Vertex *to_vertex,
|
Vertex *to_vertex,
|
||||||
|
|
@ -2598,11 +2598,13 @@ Search::thruClkInfo(Path *from_path,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
ClkInfo *to_clk_info = findClkInfo(from_clk_edge, from_clk_info->clkSrc(),
|
const ClkInfo *to_clk_info = findClkInfo(from_clk_edge,
|
||||||
to_clk_prop, gen_clk_src,
|
from_clk_info->clkSrc(),
|
||||||
from_clk_info->isGenClkSrcPath(),
|
to_clk_prop, gen_clk_src,
|
||||||
to_pulse_sense, to_insertion, to_latency,
|
from_clk_info->isGenClkSrcPath(),
|
||||||
to_uncertainties, path_ap, to_crpr_clk_path);
|
to_pulse_sense, to_insertion, to_latency,
|
||||||
|
to_uncertainties, path_ap,
|
||||||
|
to_crpr_clk_path);
|
||||||
return to_clk_info;
|
return to_clk_info;
|
||||||
}
|
}
|
||||||
return from_clk_info;
|
return from_clk_info;
|
||||||
|
|
@ -2614,13 +2616,13 @@ Search::mutateTag(Tag *from_tag,
|
||||||
const Pin *from_pin,
|
const Pin *from_pin,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
bool from_is_clk,
|
bool from_is_clk,
|
||||||
ClkInfo *from_clk_info,
|
const ClkInfo *from_clk_info,
|
||||||
const Pin *to_pin,
|
const Pin *to_pin,
|
||||||
const RiseFall *to_rf,
|
const RiseFall *to_rf,
|
||||||
bool to_is_clk,
|
bool to_is_clk,
|
||||||
bool to_is_reg_clk,
|
bool to_is_reg_clk,
|
||||||
bool to_is_segment_start,
|
bool to_is_segment_start,
|
||||||
ClkInfo *to_clk_info,
|
const ClkInfo *to_clk_info,
|
||||||
InputDelay *to_input_delay,
|
InputDelay *to_input_delay,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap)
|
const PathAnalysisPt *path_ap)
|
||||||
|
|
@ -2727,7 +2729,7 @@ Search::mutateTag(Tag *from_tag,
|
||||||
TagGroup *
|
TagGroup *
|
||||||
Search::findTagGroup(TagGroupBldr *tag_bldr)
|
Search::findTagGroup(TagGroupBldr *tag_bldr)
|
||||||
{
|
{
|
||||||
TagGroup probe(tag_bldr);
|
TagGroup probe(tag_bldr, this);
|
||||||
LockGuard lock(tag_group_lock_);
|
LockGuard lock(tag_group_lock_);
|
||||||
TagGroup *tag_group = tag_group_set_->findKey(&probe);
|
TagGroup *tag_group = tag_group_set_->findKey(&probe);
|
||||||
if (tag_group == nullptr) {
|
if (tag_group == nullptr) {
|
||||||
|
|
@ -2828,7 +2830,7 @@ bool
|
||||||
ReportPathLess::operator()(const Path *path1,
|
ReportPathLess::operator()(const Path *path1,
|
||||||
const Path *path2) const
|
const Path *path2) const
|
||||||
{
|
{
|
||||||
return tagCmp(path1->tag(sta_), path2->tag(sta_), sta_) < 0;
|
return Tag::cmp(path1->tag(sta_), path2->tag(sta_), sta_) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2967,7 +2969,7 @@ Search::tagCount() const
|
||||||
Tag *
|
Tag *
|
||||||
Search::findTag(const RiseFall *rf,
|
Search::findTag(const RiseFall *rf,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
bool is_clk,
|
bool is_clk,
|
||||||
InputDelay *input_delay,
|
InputDelay *input_delay,
|
||||||
bool is_segment_start,
|
bool is_segment_start,
|
||||||
|
|
@ -3037,17 +3039,17 @@ Search::reportTags() const
|
||||||
void
|
void
|
||||||
Search::reportClkInfos() const
|
Search::reportClkInfos() const
|
||||||
{
|
{
|
||||||
Vector<ClkInfo*> clk_infos;
|
Vector<const ClkInfo*> clk_infos;
|
||||||
// set -> vector for sorting.
|
// set -> vector for sorting.
|
||||||
for (ClkInfo *clk_info : *clk_info_set_)
|
for (const ClkInfo *clk_info : *clk_info_set_)
|
||||||
clk_infos.push_back(clk_info);
|
clk_infos.push_back(clk_info);
|
||||||
sort(clk_infos, ClkInfoLess(this));
|
sort(clk_infos, ClkInfoLess(this));
|
||||||
for (ClkInfo *clk_info : clk_infos)
|
for (const ClkInfo *clk_info : clk_infos)
|
||||||
report_->reportLine("%s", clk_info->to_string(this).c_str());
|
report_->reportLine("%s", clk_info->to_string(this).c_str());
|
||||||
report_->reportLine("%zu clk infos", clk_info_set_->size());
|
report_->reportLine("%zu clk infos", clk_info_set_->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
ClkInfo *
|
const ClkInfo *
|
||||||
Search::findClkInfo(const ClockEdge *clk_edge,
|
Search::findClkInfo(const ClockEdge *clk_edge,
|
||||||
const Pin *clk_src,
|
const Pin *clk_src,
|
||||||
bool is_propagated,
|
bool is_propagated,
|
||||||
|
|
@ -3064,7 +3066,7 @@ Search::findClkInfo(const ClockEdge *clk_edge,
|
||||||
pulse_clk_sense, insertion, latency, uncertainties,
|
pulse_clk_sense, insertion, latency, uncertainties,
|
||||||
path_ap->index(), crpr_clk_path, this);
|
path_ap->index(), crpr_clk_path, this);
|
||||||
LockGuard lock(clk_info_lock_);
|
LockGuard lock(clk_info_lock_);
|
||||||
ClkInfo *clk_info = clk_info_set_->findKey(&probe);
|
const ClkInfo *clk_info = clk_info_set_->findKey(&probe);
|
||||||
if (clk_info == nullptr) {
|
if (clk_info == nullptr) {
|
||||||
clk_info = new ClkInfo(clk_edge, clk_src,
|
clk_info = new ClkInfo(clk_edge, clk_src,
|
||||||
is_propagated, gen_clk_src, gen_clk_src_path,
|
is_propagated, gen_clk_src, gen_clk_src_path,
|
||||||
|
|
@ -3075,7 +3077,7 @@ Search::findClkInfo(const ClockEdge *clk_edge,
|
||||||
return clk_info;
|
return clk_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClkInfo *
|
const ClkInfo *
|
||||||
Search::findClkInfo(const ClockEdge *clk_edge,
|
Search::findClkInfo(const ClockEdge *clk_edge,
|
||||||
const Pin *clk_src,
|
const Pin *clk_src,
|
||||||
bool is_propagated,
|
bool is_propagated,
|
||||||
|
|
@ -3612,7 +3614,7 @@ RequiredVisitor::visitFromToPath(const Pin *,
|
||||||
while (to_iter.hasNext()) {
|
while (to_iter.hasNext()) {
|
||||||
Path *to_path = to_iter.next();
|
Path *to_path = to_iter.next();
|
||||||
Tag *to_path_tag = to_path->tag(this);
|
Tag *to_path_tag = to_path->tag(this);
|
||||||
if (tagMatchNoCrpr(to_path_tag, to_tag)) {
|
if (Tag::matchNoCrpr(to_path_tag, to_tag)) {
|
||||||
Required to_required = to_path->required();
|
Required to_required = to_path->required();
|
||||||
Required from_required = to_required - arc_delay;
|
Required from_required = to_required - arc_delay;
|
||||||
debugPrint(debug_, "search", 3, " to tag %2u: %s",
|
debugPrint(debug_, "search", 3, " to tag %2u: %s",
|
||||||
|
|
|
||||||
|
|
@ -2881,7 +2881,7 @@ Sta::vertexArrival(Vertex *vertex,
|
||||||
while (path_iter.hasNext()) {
|
while (path_iter.hasNext()) {
|
||||||
Path *path = path_iter.next();
|
Path *path = path_iter.next();
|
||||||
const Arrival &path_arrival = path->arrival();
|
const Arrival &path_arrival = path->arrival();
|
||||||
ClkInfo *clk_info = path->clkInfo(search_);
|
const ClkInfo *clk_info = path->clkInfo(search_);
|
||||||
if ((clk_edge == clk_edge_wildcard
|
if ((clk_edge == clk_edge_wildcard
|
||||||
|| clk_info->clkEdge() == clk_edge)
|
|| clk_info->clkEdge() == clk_edge)
|
||||||
&& !clk_info->isGenClkSrcPath()
|
&& !clk_info->isGenClkSrcPath()
|
||||||
|
|
|
||||||
190
search/Tag.cc
190
search/Tag.cc
|
|
@ -38,20 +38,10 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
static int
|
|
||||||
tagStateCmp(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
static bool
|
|
||||||
tagStateEqual(ExceptionStateSet *states1,
|
|
||||||
ExceptionStateSet *states2);
|
|
||||||
static bool
|
|
||||||
tagStateEqualCrpr(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
|
|
||||||
Tag::Tag(TagIndex index,
|
Tag::Tag(TagIndex index,
|
||||||
int rf_index,
|
int rf_index,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
bool is_clk,
|
bool is_clk,
|
||||||
InputDelay *input_delay,
|
InputDelay *input_delay,
|
||||||
bool is_segment_start,
|
bool is_segment_start,
|
||||||
|
|
@ -262,26 +252,32 @@ Tag::findHash()
|
||||||
for (ExceptionState *state : *states_)
|
for (ExceptionState *state : *states_)
|
||||||
hashIncr(hash_, state->hash());
|
hashIncr(hash_, state->hash());
|
||||||
}
|
}
|
||||||
|
hashIncr(hash_, clk_info_->hash());
|
||||||
match_hash_ = hash_;
|
match_hash_ = hash_;
|
||||||
|
|
||||||
// Finish hash_.
|
// Finish hash_.
|
||||||
hashIncr(hash_, clk_info_->hash());
|
|
||||||
if (input_delay_)
|
if (input_delay_)
|
||||||
hashIncr(hash_, input_delay_->index());
|
hashIncr(hash_, input_delay_->index());
|
||||||
|
|
||||||
// Finish match_hash_.
|
// Finish match_hash_.
|
||||||
const ClockEdge *clk_edge = clk_info_->clkEdge();
|
|
||||||
if (clk_edge)
|
|
||||||
hashIncr(match_hash_, clk_edge->index());
|
|
||||||
hashIncr(match_hash_, clk_info_->isGenClkSrcPath());
|
hashIncr(match_hash_, clk_info_->isGenClkSrcPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Tag::hash(bool match_crpr_clk_pin,
|
||||||
|
const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (match_crpr_clk_pin)
|
||||||
|
return hashSum(hash_, clk_info_->crprClkVertexId(sta));
|
||||||
|
else
|
||||||
|
return hash_;
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Tag::matchHash(bool match_crpr_clk_pin,
|
Tag::matchHash(bool match_crpr_clk_pin,
|
||||||
const StaState *sta) const
|
const StaState *sta) const
|
||||||
{
|
{
|
||||||
if (match_crpr_clk_pin)
|
if (match_crpr_clk_pin)
|
||||||
// match_hash_ with crpr clk pin thrown in.
|
|
||||||
return hashSum(match_hash_, clk_info_->crprClkVertexId(sta));
|
return hashSum(match_hash_, clk_info_->crprClkVertexId(sta));
|
||||||
else
|
else
|
||||||
return match_hash_;
|
return match_hash_;
|
||||||
|
|
@ -298,20 +294,20 @@ bool
|
||||||
TagLess::operator()(const Tag *tag1,
|
TagLess::operator()(const Tag *tag1,
|
||||||
const Tag *tag2) const
|
const Tag *tag2) const
|
||||||
{
|
{
|
||||||
return tagCmp(tag1, tag2, sta_) < 0;
|
return Tag::cmp(tag1, tag2, sta_) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tagCmp(const Tag *tag1,
|
Tag::cmp(const Tag *tag1,
|
||||||
const Tag *tag2,
|
const Tag *tag2,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (tag1 == tag2)
|
if (tag1 == tag2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ClkInfo *clk_info1 = tag1->clkInfo();
|
const ClkInfo *clk_info1 = tag1->clkInfo();
|
||||||
ClkInfo *clk_info2 = tag2->clkInfo();
|
const ClkInfo *clk_info2 = tag2->clkInfo();
|
||||||
int clk_cmp = clkInfoCmp(clk_info1, clk_info2, sta);
|
int clk_cmp = ClkInfo::cmp(clk_info1, clk_info2, sta);
|
||||||
if (clk_cmp != 0)
|
if (clk_cmp != 0)
|
||||||
return clk_cmp;
|
return clk_cmp;
|
||||||
|
|
||||||
|
|
@ -338,8 +334,8 @@ tagCmp(const Tag *tag1,
|
||||||
|
|
||||||
InputDelay *input_delay1 = tag1->inputDelay();
|
InputDelay *input_delay1 = tag1->inputDelay();
|
||||||
InputDelay *input_delay2 = tag2->inputDelay();
|
InputDelay *input_delay2 = tag2->inputDelay();
|
||||||
int input_delay_index1 = input_delay1 ? input_delay1->index() : 0;
|
int input_delay_index1 = input_delay1 ? input_delay1->index() : -1;
|
||||||
int input_delay_index2 = input_delay2 ? input_delay2->index() : 0;
|
int input_delay_index2 = input_delay2 ? input_delay2->index() : -1;
|
||||||
if (input_delay_index1 < input_delay_index2)
|
if (input_delay_index1 < input_delay_index2)
|
||||||
return -1;
|
return -1;
|
||||||
if (input_delay_index1 > input_delay_index2)
|
if (input_delay_index1 > input_delay_index2)
|
||||||
|
|
@ -352,21 +348,15 @@ tagCmp(const Tag *tag1,
|
||||||
if (is_segment_start1 && !is_segment_start2)
|
if (is_segment_start1 && !is_segment_start2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return tagStateCmp(tag1, tag2);
|
return stateCmp(tag1, tag2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagEqual(const Tag *tag1,
|
Tag::equal(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2,
|
||||||
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
return tag1 == tag2
|
return cmp(tag1, tag2, sta) == 0;
|
||||||
|| (tag1->rfIndex() == tag2->rfIndex()
|
|
||||||
&& tag1->pathAPIndex() == tag2->pathAPIndex()
|
|
||||||
&& tag1->clkInfo() == tag2->clkInfo()
|
|
||||||
&& tag1->isClock() == tag2->isClock()
|
|
||||||
&& tag1->inputDelay() == tag2->inputDelay()
|
|
||||||
&& tag1->isSegmentStart() == tag2->isSegmentStart()
|
|
||||||
&& tagStateEqual(tag1, tag2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -391,45 +381,33 @@ bool
|
||||||
TagMatchLess::operator()(const Tag *tag1,
|
TagMatchLess::operator()(const Tag *tag1,
|
||||||
const Tag *tag2) const
|
const Tag *tag2) const
|
||||||
{
|
{
|
||||||
return tagMatchCmp(tag1, tag2, match_crpr_clk_pin_, sta_) < 0;
|
return Tag::matchCmp(tag1, tag2, match_crpr_clk_pin_, sta_) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagMatch(const Tag *tag1,
|
Tag::match(const Tag *tag1,
|
||||||
const Tag *tag2,
|
const Tag *tag2,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
return tagMatch(tag1, tag2, true, sta);
|
return Tag::matchCmp(tag1, tag2, true, sta) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagMatch(const Tag *tag1,
|
Tag::match(const Tag *tag1,
|
||||||
const Tag *tag2,
|
const Tag *tag2,
|
||||||
bool match_crpr_clk_pin,
|
bool match_crpr_clk_pin,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
const ClkInfo *clk_info1 = tag1->clkInfo();
|
return Tag::matchCmp(tag1, tag2, match_crpr_clk_pin, sta) == 0;
|
||||||
const ClkInfo *clk_info2 = tag2->clkInfo();
|
|
||||||
return tag1 == tag2
|
|
||||||
|| (clk_info1->clkEdge() == clk_info2->clkEdge()
|
|
||||||
&& tag1->rfIndex() == tag2->rfIndex()
|
|
||||||
&& tag1->pathAPIndex() == tag2->pathAPIndex()
|
|
||||||
&& tag1->isClock() == tag2->isClock()
|
|
||||||
&& tag1->isSegmentStart() == tag2->isSegmentStart()
|
|
||||||
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
|
||||||
&& (!match_crpr_clk_pin
|
|
||||||
|| !sta->crprActive()
|
|
||||||
|| clk_info1->crprClkVertexId(sta) == clk_info2->crprClkVertexId(sta))
|
|
||||||
&& tagStateEqual(tag1, tag2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tagMatchCmp(const Tag *tag1,
|
Tag::matchCmp(const Tag *tag1,
|
||||||
const Tag *tag2,
|
const Tag *tag2,
|
||||||
bool match_crpr_clk_pin,
|
bool match_crpr_clk_pin,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (tag1 == tag2)
|
if (tag1 == tag2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -490,12 +468,12 @@ tagMatchCmp(const Tag *tag1,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tagStateCmp(tag1, tag2);
|
return stateCmp(tag1, tag2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagMatchNoCrpr(const Tag *tag1,
|
Tag::matchNoCrpr(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2)
|
||||||
{
|
{
|
||||||
const ClkInfo *clk_info1 = tag1->clkInfo();
|
const ClkInfo *clk_info1 = tag1->clkInfo();
|
||||||
const ClkInfo *clk_info2 = tag2->clkInfo();
|
const ClkInfo *clk_info2 = tag2->clkInfo();
|
||||||
|
|
@ -505,12 +483,12 @@ tagMatchNoCrpr(const Tag *tag1,
|
||||||
&& tag1->pathAPIndex() == tag2->pathAPIndex()
|
&& tag1->pathAPIndex() == tag2->pathAPIndex()
|
||||||
&& tag1->isClock() == tag2->isClock()
|
&& tag1->isClock() == tag2->isClock()
|
||||||
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
||||||
&& tagStateEqual(tag1, tag2));
|
&& Tag::stateEqual(tag1, tag2));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagMatchNoPathAp(const Tag *tag1,
|
Tag::matchNoPathAp(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2)
|
||||||
{
|
{
|
||||||
const ClkInfo *clk_info1 = tag1->clkInfo();
|
const ClkInfo *clk_info1 = tag1->clkInfo();
|
||||||
const ClkInfo *clk_info2 = tag2->clkInfo();
|
const ClkInfo *clk_info2 = tag2->clkInfo();
|
||||||
|
|
@ -520,12 +498,12 @@ tagMatchNoPathAp(const Tag *tag1,
|
||||||
&& tag1->isClock() == tag2->isClock()
|
&& tag1->isClock() == tag2->isClock()
|
||||||
&& tag1->isSegmentStart() == tag2->isSegmentStart()
|
&& tag1->isSegmentStart() == tag2->isSegmentStart()
|
||||||
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
||||||
&& tagStateEqual(tag1, tag2));
|
&& Tag::stateEqual(tag1, tag2));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagMatchCrpr(const Tag *tag1,
|
Tag::matchCrpr(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2)
|
||||||
{
|
{
|
||||||
const ClkInfo *clk_info1 = tag1->clkInfo();
|
const ClkInfo *clk_info1 = tag1->clkInfo();
|
||||||
const ClkInfo *clk_info2 = tag2->clkInfo();
|
const ClkInfo *clk_info2 = tag2->clkInfo();
|
||||||
|
|
@ -535,14 +513,14 @@ tagMatchCrpr(const Tag *tag1,
|
||||||
&& tag1->isClock() == tag2->isClock()
|
&& tag1->isClock() == tag2->isClock()
|
||||||
&& tag1->isSegmentStart() == tag2->isSegmentStart()
|
&& tag1->isSegmentStart() == tag2->isSegmentStart()
|
||||||
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
|
||||||
&& tagStateEqualCrpr(tag1, tag2));
|
&& stateEqualCrpr(tag1, tag2));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static int
|
int
|
||||||
tagStateCmp(const Tag *tag1,
|
Tag::stateCmp(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2)
|
||||||
{
|
{
|
||||||
ExceptionStateSet *states1 = tag1->states();
|
ExceptionStateSet *states1 = tag1->states();
|
||||||
ExceptionStateSet *states2 = tag2->states();
|
ExceptionStateSet *states2 = tag2->states();
|
||||||
|
|
@ -571,54 +549,25 @@ tagStateCmp(const Tag *tag1,
|
||||||
&& state_iter2.hasNext()) {
|
&& state_iter2.hasNext()) {
|
||||||
ExceptionState *state1 = state_iter1.next();
|
ExceptionState *state1 = state_iter1.next();
|
||||||
ExceptionState *state2 = state_iter2.next();
|
ExceptionState *state2 = state_iter2.next();
|
||||||
if (state1 < state2)
|
if (exceptionStateLess(state1, state2))
|
||||||
return -1;
|
return -1;
|
||||||
if (state1 > state2)
|
if (exceptionStateLess(state2, state1))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tagStateEqual(const Tag *tag1,
|
Tag::stateEqual(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2)
|
||||||
{
|
{
|
||||||
return tagStateEqual(tag1->states(), tag2->states());
|
return stateCmp(tag1, tag2) == 0;
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
tagStateEqual(ExceptionStateSet *states1,
|
|
||||||
ExceptionStateSet *states2)
|
|
||||||
{
|
|
||||||
bool states_null1 = (states1 == nullptr || states1->empty());
|
|
||||||
bool states_null2 = (states2 == nullptr || states2->empty());
|
|
||||||
if (states_null1 && states_null2)
|
|
||||||
return true;
|
|
||||||
else if (states_null1 != states_null2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
size_t state_size1 = states1->size();
|
|
||||||
size_t state_size2 = states2->size();
|
|
||||||
if (state_size1 == state_size2) {
|
|
||||||
ExceptionStateSet::Iterator state_iter1(states1);
|
|
||||||
ExceptionStateSet::Iterator state_iter2(states2);
|
|
||||||
while (state_iter1.hasNext()
|
|
||||||
&& state_iter2.hasNext()) {
|
|
||||||
ExceptionState *state1 = state_iter1.next();
|
|
||||||
ExceptionState *state2 = state_iter2.next();
|
|
||||||
if (state1 != state2)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match loop exception states only for crpr min/max paths.
|
// Match loop exception states only for crpr min/max paths.
|
||||||
static bool
|
bool
|
||||||
tagStateEqualCrpr(const Tag *tag1,
|
Tag::stateEqualCrpr(const Tag *tag1,
|
||||||
const Tag *tag2)
|
const Tag *tag2)
|
||||||
{
|
{
|
||||||
ExceptionStateSet *states1 = tag1->states();
|
ExceptionStateSet *states1 = tag1->states();
|
||||||
ExceptionStateSet *states2 = tag2->states();
|
ExceptionStateSet *states2 = tag2->states();
|
||||||
|
|
@ -653,17 +602,28 @@ tagStateEqualCrpr(const Tag *tag1,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TagHash::TagHash(const StaState *sta) :
|
||||||
|
sta_(sta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
TagHash::operator()(const Tag *tag) const
|
TagHash::operator()(const Tag *tag) const
|
||||||
{
|
{
|
||||||
return tag->hash();
|
bool crpr_on = sta_->crprActive();
|
||||||
|
return tag->matchHash(crpr_on, sta_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TagEqual::TagEqual(const StaState *sta) :
|
||||||
|
sta_(sta)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TagEqual::operator()(const Tag *tag1,
|
TagEqual::operator()(const Tag *tag1,
|
||||||
const Tag *tag2) const
|
const Tag *tag2) const
|
||||||
{
|
{
|
||||||
return tagEqual(tag1, tag2);
|
return Tag::equal(tag1, tag2, sta_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TagMatchHash::TagMatchHash(bool match_crpr_clk_pin,
|
TagMatchHash::TagMatchHash(bool match_crpr_clk_pin,
|
||||||
|
|
@ -690,7 +650,7 @@ bool
|
||||||
TagMatchEqual::operator()(const Tag *tag1,
|
TagMatchEqual::operator()(const Tag *tag1,
|
||||||
const Tag *tag2) const
|
const Tag *tag2) const
|
||||||
{
|
{
|
||||||
return tagMatch(tag1, tag2, match_crpr_clk_pin_, sta_);
|
return Tag::match(tag1, tag2, match_crpr_clk_pin_, sta_);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public:
|
||||||
Tag(TagIndex index,
|
Tag(TagIndex index,
|
||||||
int rf_index,
|
int rf_index,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
ClkInfo *clk_info,
|
const ClkInfo *clk_info,
|
||||||
bool is_clk,
|
bool is_clk,
|
||||||
InputDelay *input_delay,
|
InputDelay *input_delay,
|
||||||
bool is_segment_start,
|
bool is_segment_start,
|
||||||
|
|
@ -66,7 +66,7 @@ public:
|
||||||
std::string to_string(bool report_index,
|
std::string to_string(bool report_index,
|
||||||
bool report_rf_min_max,
|
bool report_rf_min_max,
|
||||||
const StaState *sta) const;
|
const StaState *sta) const;
|
||||||
ClkInfo *clkInfo() const { return clk_info_; }
|
const ClkInfo *clkInfo() const { return clk_info_; }
|
||||||
bool isClock() const { return is_clk_; }
|
bool isClock() const { return is_clk_; }
|
||||||
const ClockEdge *clkEdge() const;
|
const ClockEdge *clkEdge() const;
|
||||||
const Clock *clock() const;
|
const Clock *clock() const;
|
||||||
|
|
@ -85,15 +85,48 @@ public:
|
||||||
bool isLoop() const { return is_loop_; }
|
bool isLoop() const { return is_loop_; }
|
||||||
bool isFilter() const { return is_filter_; }
|
bool isFilter() const { return is_filter_; }
|
||||||
bool isSegmentStart() const { return is_segment_start_; }
|
bool isSegmentStart() const { return is_segment_start_; }
|
||||||
size_t hash() const { return hash_; }
|
size_t hash(bool match_crpr_clk_pin,
|
||||||
|
const StaState *sta) const;
|
||||||
size_t matchHash(bool match_crpr_clk_pin,
|
size_t matchHash(bool match_crpr_clk_pin,
|
||||||
const StaState *sta) const;
|
const StaState *sta) const;
|
||||||
|
|
||||||
|
static int cmp(const Tag *tag1,
|
||||||
|
const Tag *tag2,
|
||||||
|
const StaState *sta);
|
||||||
|
static int matchCmp(const Tag *tag1,
|
||||||
|
const Tag *tag2,
|
||||||
|
bool match_clk_clk_pin,
|
||||||
|
const StaState *sta);
|
||||||
|
static bool match(const Tag *tag1,
|
||||||
|
const Tag *tag2,
|
||||||
|
bool match_crpr_clk_pin,
|
||||||
|
const StaState *sta);
|
||||||
|
static bool equal(const Tag *tag1,
|
||||||
|
const Tag *tag2,
|
||||||
|
const StaState *sta);
|
||||||
|
static bool matchNoPathAp(const Tag *tag1,
|
||||||
|
const Tag *tag2);
|
||||||
|
static bool matchCrpr(const Tag *tag1,
|
||||||
|
const Tag *tag2);
|
||||||
|
static bool matchNoCrpr(const Tag *tag1,
|
||||||
|
const Tag *tag2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void findHash();
|
void findHash();
|
||||||
|
|
||||||
|
// Match tag clock edge, clock driver and exception states but not clk info.
|
||||||
|
static bool match(const Tag *tag1,
|
||||||
|
const Tag *tag2,
|
||||||
|
const StaState *sta);
|
||||||
|
static bool stateEqual(const Tag *tag1,
|
||||||
|
const Tag *tag2);
|
||||||
|
static int stateCmp(const Tag *tag1,
|
||||||
|
const Tag *tag2);
|
||||||
|
static bool stateEqualCrpr(const Tag *tag1,
|
||||||
|
const Tag *tag2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClkInfo *clk_info_;
|
const ClkInfo *clk_info_;
|
||||||
InputDelay *input_delay_;
|
InputDelay *input_delay_;
|
||||||
ExceptionStateSet *states_;
|
ExceptionStateSet *states_;
|
||||||
size_t hash_;
|
size_t hash_;
|
||||||
|
|
@ -130,51 +163,22 @@ public:
|
||||||
class TagHash
|
class TagHash
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TagHash(const StaState *sta);
|
||||||
size_t operator()(const Tag *tag) const;
|
size_t operator()(const Tag *tag) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const StaState *sta_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TagEqual
|
class TagEqual
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TagEqual(const StaState *sta);
|
||||||
bool operator()(const Tag *tag1,
|
bool operator()(const Tag *tag1,
|
||||||
const Tag *tag2) const;
|
const Tag *tag2) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const StaState *sta_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
|
||||||
tagEqual(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
int
|
|
||||||
tagCmp(const Tag *tag1,
|
|
||||||
const Tag *tag2,
|
|
||||||
const StaState *sta);
|
|
||||||
|
|
||||||
// Match tag clock edge, clock driver and exception states but not clk info.
|
|
||||||
bool
|
|
||||||
tagMatch(const Tag *tag1,
|
|
||||||
const Tag *tag2,
|
|
||||||
const StaState *sta);
|
|
||||||
bool
|
|
||||||
tagMatch(const Tag *tag1,
|
|
||||||
const Tag *tag2,
|
|
||||||
bool match_crpr_clk_pin,
|
|
||||||
const StaState *sta);
|
|
||||||
bool
|
|
||||||
tagStateEqual(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
bool
|
|
||||||
tagMatchNoCrpr(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
int
|
|
||||||
tagMatchCmp(const Tag *tag1,
|
|
||||||
const Tag *tag2,
|
|
||||||
bool match_clk_clk_pin,
|
|
||||||
const StaState *sta);
|
|
||||||
|
|
||||||
bool
|
|
||||||
tagMatchNoPathAp(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
bool
|
|
||||||
tagMatchCrpr(const Tag *tag1,
|
|
||||||
const Tag *tag2);
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,10 @@ TagGroup::TagGroup(TagGroupIndex index,
|
||||||
bool has_clk_tag,
|
bool has_clk_tag,
|
||||||
bool has_genclk_src_tag,
|
bool has_genclk_src_tag,
|
||||||
bool has_filter_tag,
|
bool has_filter_tag,
|
||||||
bool has_loop_tag) :
|
bool has_loop_tag,
|
||||||
|
const StaState *sta) :
|
||||||
path_index_map_(path_index_map),
|
path_index_map_(path_index_map),
|
||||||
hash_(pathIndexMapHash(path_index_map)),
|
hash_(hash(path_index_map, sta)),
|
||||||
ref_count_(0),
|
ref_count_(0),
|
||||||
index_(index),
|
index_(index),
|
||||||
has_clk_tag_(has_clk_tag),
|
has_clk_tag_(has_clk_tag),
|
||||||
|
|
@ -54,9 +55,10 @@ TagGroup::TagGroup(TagGroupIndex index,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TagGroup::TagGroup(TagGroupBldr *tag_bldr) :
|
TagGroup::TagGroup(TagGroupBldr *tag_bldr,
|
||||||
|
const StaState *sta) :
|
||||||
path_index_map_(&tag_bldr->pathIndexMap()),
|
path_index_map_(&tag_bldr->pathIndexMap()),
|
||||||
hash_(pathIndexMapHash(path_index_map_)),
|
hash_(hash(path_index_map_, sta)),
|
||||||
ref_count_(0),
|
ref_count_(0),
|
||||||
own_path_map_(false)
|
own_path_map_(false)
|
||||||
{
|
{
|
||||||
|
|
@ -81,11 +83,13 @@ TagGroup::decrRefCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
TagGroup::pathIndexMapHash(PathIndexMap *path_index_map)
|
TagGroup::hash(PathIndexMap *path_index_map,
|
||||||
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
|
bool crpr_on = sta->crprActive();
|
||||||
size_t hash = 0;
|
size_t hash = 0;
|
||||||
for (auto const [tag, path_index] : *path_index_map)
|
for (auto const [tag, path_index] : *path_index_map)
|
||||||
hash += tag->hash();
|
hash += tag->hash(crpr_on, sta);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,7 +272,7 @@ TagGroupBldr::insertPath(Tag *tag,
|
||||||
if (tag->isGenClkSrcPath())
|
if (tag->isGenClkSrcPath())
|
||||||
has_genclk_src_tag_ = true;
|
has_genclk_src_tag_ = true;
|
||||||
if (tag->isFilter()
|
if (tag->isFilter()
|
||||||
|| tag->clkInfo()->refsFilter(sta_))
|
|| tag->clkInfo()->crprPathRefsFilter())
|
||||||
has_filter_tag_ = true;
|
has_filter_tag_ = true;
|
||||||
if (tag->isLoop())
|
if (tag->isLoop())
|
||||||
has_loop_tag_ = true;
|
has_loop_tag_ = true;
|
||||||
|
|
@ -289,7 +293,7 @@ TagGroupBldr::makeTagGroup(TagGroupIndex index,
|
||||||
{
|
{
|
||||||
return new TagGroup(index, makePathIndexMap(sta),
|
return new TagGroup(index, makePathIndexMap(sta),
|
||||||
has_clk_tag_, has_genclk_src_tag_, has_filter_tag_,
|
has_clk_tag_, has_genclk_src_tag_, has_filter_tag_,
|
||||||
has_loop_tag_);
|
has_loop_tag_, sta);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,10 +343,7 @@ pathIndexMapEqual(const PathIndexMap *path_index_map1,
|
||||||
size_t path_index2;
|
size_t path_index2;
|
||||||
bool exists2;
|
bool exists2;
|
||||||
path_index_map2->findKey(tag1, tag2, path_index2, exists2);
|
path_index_map2->findKey(tag1, tag2, path_index2, exists2);
|
||||||
if (!exists2
|
if (!exists2)
|
||||||
// ArrivalMap equal function is TagMatchEqual, so make sure
|
|
||||||
// the tag is an exact match.
|
|
||||||
|| tag2 != tag1)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,11 @@ public:
|
||||||
bool has_clk_tag,
|
bool has_clk_tag,
|
||||||
bool has_genclk_src_tag,
|
bool has_genclk_src_tag,
|
||||||
bool has_filter_tag,
|
bool has_filter_tag,
|
||||||
bool has_loop_tag);
|
bool has_loop_tag,
|
||||||
|
const StaState *sta);
|
||||||
// For Search::findTagGroup to probe.
|
// For Search::findTagGroup to probe.
|
||||||
TagGroup(TagGroupBldr *tag_bldr);
|
TagGroup(TagGroupBldr *tag_bldr,
|
||||||
|
const StaState *sta);
|
||||||
~TagGroup();
|
~TagGroup();
|
||||||
TagGroupIndex index() const { return index_; }
|
TagGroupIndex index() const { return index_; }
|
||||||
size_t hash() const { return hash_; }
|
size_t hash() const { return hash_; }
|
||||||
|
|
@ -72,7 +74,8 @@ public:
|
||||||
int refCount() const { return ref_count_; }
|
int refCount() const { return ref_count_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static size_t pathIndexMapHash(PathIndexMap *path_index_map);
|
static size_t hash(PathIndexMap *path_index_map,
|
||||||
|
const StaState *sta);
|
||||||
|
|
||||||
// tag -> path index
|
// tag -> path index
|
||||||
PathIndexMap *path_index_map_;
|
PathIndexMap *path_index_map_;
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ VisitPathEnds::visitCheckEnd(const Pin *pin,
|
||||||
tgt_clk_path_ap, this);
|
tgt_clk_path_ap, this);
|
||||||
while (tgt_clk_path_iter.hasNext()) {
|
while (tgt_clk_path_iter.hasNext()) {
|
||||||
Path *tgt_clk_path = tgt_clk_path_iter.next();
|
Path *tgt_clk_path = tgt_clk_path_iter.next();
|
||||||
ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this);
|
const ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this);
|
||||||
const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this);
|
const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this);
|
||||||
const Clock *tgt_clk = tgt_clk_path->clock(this);
|
const Clock *tgt_clk = tgt_clk_path->clock(this);
|
||||||
const Pin *tgt_pin = tgt_clk_vertex->pin();
|
const Pin *tgt_pin = tgt_clk_vertex->pin();
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
|
||||||
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
|
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
|
||||||
while (to_iter.hasNext()) {
|
while (to_iter.hasNext()) {
|
||||||
Path *to_path = to_iter.next();
|
Path *to_path = to_iter.next();
|
||||||
if (tagMatchNoCrpr(to_path->tag(this), to_tag)
|
if (Tag::matchNoCrpr(to_path->tag(this), to_tag)
|
||||||
&& matching_paths->hasKey(to_path)) {
|
&& matching_paths->hasKey(to_path)) {
|
||||||
debugPrint(debug_, "visit_path_group", 2,
|
debugPrint(debug_, "visit_path_group", 2,
|
||||||
"match crpr %s %s -> %s %s",
|
"match crpr %s %s -> %s %s",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue