4444#include " sta/StaMain.hh"
4545#include " sta/Units.hh"
4646#include " utl/Logger.h"
47+ #include " utl/histogram.h"
4748
4849// //////////////////////////////////////////////////////////////
4950
@@ -151,36 +152,6 @@ class dbStaReport : public sta::ReportTcl
151152 Logger* logger_ = nullptr ;
152153};
153154
154- // Helper class for histogram reporting.
155- class dbStaHistogram
156- {
157- public:
158- dbStaHistogram (Sta* sta, dbNetwork* network, Logger* logger);
159-
160- // Loads data_ with the slack value for each constrained endpoint.
161- void loadSlackData (const MinMax* min_max);
162- // Loads data_ with the logic depth for each constrained endpoint.
163- void loadLogicDepthData (bool exclude_buffers, bool exclude_inverters);
164- // Populates bins_ using the current data_, which must be loaded first.
165- void populateHistogramBins (int num_bins);
166- // Prints the histogram to the log. Width and precision are used to control
167- // the number of digits when displaying each bin's range.
168- void reportHistogram (int width, int precision) const ;
169-
170- private:
171- std::vector<float > data_;
172- // Bins are defined in bins_ as equally sized windows of width bin_width_
173- // starting with smallest value min_val_ at the start of bin 0.
174- std::vector<int > bins_;
175- float min_val_ = 0.0 ;
176- float bin_width_ = 0.0 ;
177- bool integer_bins_ = false ; // Enforce int bin width (for discrete metrics).
178-
179- Sta* sta_;
180- dbNetwork* network_;
181- Logger* logger_;
182- };
183-
184155class dbStaCbk : public dbBlockCallBackObj
185156{
186157 public:
@@ -680,28 +651,28 @@ void dbSta::reportCellUsage(odb::dbModule* module,
680651 }
681652}
682653
683- dbStaHistogram::dbStaHistogram (Sta* sta, dbNetwork* network, Logger* logger)
684- : sta_(sta), network_(network), logger_(logger)
654+ void dbSta::reportTimingHistogram (int num_bins, const MinMax* min_max) const
685655{
686- }
656+ utl::Histogram< float > histogram (logger_);
687657
688- void dbStaHistogram::loadSlackData (const MinMax* min_max)
689- {
690- data_.clear ();
691658 sta::Unit* time_unit = sta_->units ()->timeUnit ();
692659 for (sta::Vertex* vertex : *sta_->endpoints ()) {
693660 float slack = sta_->vertexSlack (vertex, min_max);
694661 if (slack != sta::INF ) { // Ignore unconstrained paths.
695- data_. push_back (time_unit->staToUser (slack));
662+ histogram. addData (time_unit->staToUser (slack));
696663 }
697664 }
698- integer_bins_ = false ;
665+
666+ histogram.generateBins (num_bins);
667+ histogram.report (/* precision=*/ 3 );
699668}
700669
701- void dbStaHistogram::loadLogicDepthData (bool exclude_buffers,
702- bool exclude_inverters)
670+ void dbSta::reportLogicDepthHistogram (int num_bins,
671+ bool exclude_buffers,
672+ bool exclude_inverters) const
703673{
704- data_.clear ();
674+ utl::Histogram<int > histogram (logger_);
675+
705676 sta_->worstSlack (MinMax::max ()); // Update timing.
706677 for (sta::Vertex* vertex : *sta_->endpoints ()) {
707678 int path_length = 0 ;
@@ -710,103 +681,22 @@ void dbStaHistogram::loadLogicDepthData(bool exclude_buffers,
710681 while (path) {
711682 Pin* pin = path->vertex (sta_)->pin ();
712683 Instance* sta_inst = sta_->cmdNetwork ()->instance (pin);
713- dbInst* inst = network_ ->staToDb (sta_inst);
684+ dbInst* inst = db_network_ ->staToDb (sta_inst);
714685 if (!network_->isTopLevelPort (pin) && inst != prev_inst) {
715686 prev_inst = inst;
716- LibertyCell* lib_cell = network_ ->libertyCell (inst);
687+ LibertyCell* lib_cell = db_network_ ->libertyCell (inst);
717688 if (lib_cell && (!exclude_buffers || !lib_cell->isBuffer ())
718689 && (!exclude_inverters || !lib_cell->isInverter ())) {
719690 path_length++;
720691 }
721692 }
722693 path = path->prevPath ();
723694 }
724- data_. push_back (path_length);
695+ histogram. addData (path_length);
725696 }
726- integer_bins_ = true ;
727- }
728697
729- void dbStaHistogram::populateHistogramBins (int num_bins)
730- {
731- if (num_bins <= 0 ) {
732- logger_->error (STA , 70 , " The number of bins must be positive." );
733- return ;
734- }
735- if (data_.empty ()) {
736- logger_->error (STA , 71 , " No data for the histogram has been loaded." );
737- return ;
738- }
739- std::sort (data_.begin (), data_.end ());
740-
741- // Populate each bin with count.
742- bins_.resize (num_bins, 0 );
743- min_val_ = data_.front ();
744- bin_width_ = (data_.back () - min_val_) / num_bins;
745- if (bin_width_ == 0 ) { // Special case for no variation in the data.
746- bins_[0 ] = data_.size ();
747- return ;
748- }
749- if (integer_bins_) {
750- bin_width_ = std::ceil (bin_width_);
751- }
752- for (const float & val : data_) {
753- int bin = static_cast <int >((val - min_val_) / bin_width_);
754- if (bin >= num_bins) { // Special case for val with the maximum value.
755- bin = num_bins - 1 ;
756- }
757- bins_[bin]++;
758- }
759- }
760-
761- void dbStaHistogram::reportHistogram (int width, int precision) const
762- {
763- constexpr int max_bin_width = 50 ; // Max number of chars to print for a bin.
764- if (data_.empty ()) {
765- logger_->error (STA , 72 , " No data for the histogram has been loaded." );
766- return ;
767- }
768- const int num_bins = bins_.size ();
769- const int largest_bin = *std::max_element (bins_.begin (), bins_.end ());
770-
771- // Print the histogram.
772- for (int bin = 0 ; bin < num_bins; ++bin) {
773- const float bin_start = min_val_ + bin * bin_width_;
774- const float bin_end = min_val_ + (bin + 1 ) * bin_width_;
775- int bar_length // Round the bar length to its closest value.
776- = (max_bin_width * bins_[bin] + largest_bin / 2 ) / largest_bin;
777- if (bar_length == 0 && bins_[bin] > 0 ) {
778- bar_length = 1 ; // Better readability when non-zero bins have a bar.
779- }
780- logger_->report (" [{:>{}.{}f}, {:>{}.{}f}{}: {} ({})" ,
781- bin_start,
782- width,
783- precision,
784- bin_end,
785- width,
786- precision,
787- // The final bin is also closed from the right.
788- bin == num_bins - 1 ? " ]" : " )" ,
789- std::string (bar_length, ' *' ),
790- bins_[bin]);
791- }
792- }
793-
794- void dbSta::reportTimingHistogram (int num_bins, const MinMax* min_max) const
795- {
796- dbStaHistogram histogram (sta_, db_network_, logger_);
797- histogram.loadSlackData (min_max);
798- histogram.populateHistogramBins (num_bins);
799- histogram.reportHistogram (/* width=*/ 6 , /* precision=*/ 3 );
800- }
801-
802- void dbSta::reportLogicDepthHistogram (int num_bins,
803- bool exclude_buffers,
804- bool exclude_inverters) const
805- {
806- dbStaHistogram histogram (sta_, db_network_, logger_);
807- histogram.loadLogicDepthData (exclude_buffers, exclude_inverters);
808- histogram.populateHistogramBins (num_bins);
809- histogram.reportHistogram (/* width=*/ 3 , /* precision=*/ 0 );
698+ histogram.generateBins (num_bins);
699+ histogram.report ();
810700}
811701
812702BufferUse dbSta::getBufferUse (sta::LibertyCell* buffer)
0 commit comments