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