1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2021, Parallax Software, Inc.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 
17 #include "MinMax.hh"
18 
19 #include <algorithm>
20 
21 #include "StringUtil.hh"
22 
23 namespace sta {
24 
25 const float INF = 1E+30F;
26 
27 static bool
compareMin(float value1,float value2)28 compareMin(float value1,
29 	   float value2)
30 {
31   return value1 < value2;
32 }
33 
34 static bool
compareMax(float value1,float value2)35 compareMax(float value1,
36 	   float value2)
37 {
38   return value1 > value2;
39 }
40 
41 ////////////////////////////////////////////////////////////////
42 
43 MinMax MinMax::min_("min", 0,  INF, compareMin);
44 MinMax MinMax::max_("max", 1, -INF, compareMax);
45 const std::array<MinMax*, 2> MinMax::range_{&min_, &max_};
46 const std::array<int, 2> MinMax::range_index_{min_.index(), max_.index()};
47 
MinMax(const char * name,int index,float init_value,bool (* compare)(float value1,float value2))48 MinMax::MinMax(const char *name,
49 	       int index,
50 	       float init_value,
51 	       bool (*compare)(float value1, float value2)) :
52   name_(name),
53   index_(index),
54   init_value_(init_value),
55   compare_(compare)
56 {
57 }
58 
59 MinMaxAll *
asMinMaxAll() const60 MinMax::asMinMaxAll() const
61 {
62   if (this == &min_)
63     return MinMaxAll::min();
64   else
65     return MinMaxAll::max();
66 }
67 
68 MinMax *
opposite() const69 MinMax::opposite() const
70 {
71   if (this == &max_)
72     return &min_;
73   else
74     return &max_;
75 }
76 
77 MinMax *
find(const char * min_max)78 MinMax::find(const char *min_max)
79 {
80   if (stringEq(min_max, "min")
81       || stringEq(min_max, "early"))
82     return &min_;
83   else if (stringEq(min_max, "max")
84 	   || stringEq(min_max, "late"))
85     return &max_;
86   else
87     return nullptr;
88 }
89 
90 MinMax *
find(int index)91 MinMax::find(int index)
92 {
93   if (index == min_.index())
94     return &min_;
95   else if (index == max_.index())
96     return &max_;
97   else
98     return nullptr;
99 }
100 
101 bool
compare(float value1,float value2) const102 MinMax::compare(float value1,
103 		float value2) const
104 {
105   return compare_(value1, value2);
106 }
107 
108 float
minMax(float value1,float value2) const109 MinMax::minMax(float value1,
110 	       float value2) const
111 {
112   if (compare_(value1, value2))
113     return value1;
114   else
115     return value2;
116 }
117 
118 ////////////////////////////////////////////////////////////////
119 
120 MinMaxAll MinMaxAll::min_("min", 0, {MinMax::min()}, {MinMax::min()->index()});
121 MinMaxAll MinMaxAll::max_("max", 1, {MinMax::max()}, {MinMax::max()->index()});
122 MinMaxAll MinMaxAll::all_("all", 2, {MinMax::min(), MinMax::max()},
123 			  {MinMax::min()->index(), MinMax::max()->index()});
124 
MinMaxAll(const char * name,int index,std::vector<MinMax * > range,std::vector<int> range_index)125 MinMaxAll::MinMaxAll(const char *name,
126 		     int index,
127 		     std::vector<MinMax*> range,
128 		     std::vector<int> range_index) :
129   name_(name),
130   index_(index),
131   range_(range),
132   range_index_(range_index)
133 {
134 }
135 
136 MinMax *
asMinMax() const137 MinMaxAll::asMinMax() const
138 {
139   if (this == &min_)
140     return MinMax::min();
141   else
142     return MinMax::max();
143 }
144 
145 bool
matches(const MinMax * min_max) const146 MinMaxAll::matches(const MinMax *min_max) const
147 {
148   return this == &all_ || asMinMax() == min_max;
149 }
150 
151 bool
matches(const MinMaxAll * min_max) const152 MinMaxAll::matches(const MinMaxAll *min_max) const
153 {
154   return this == &all_ || this == min_max;
155 }
156 
157 MinMaxAll *
find(const char * min_max)158 MinMaxAll::find(const char *min_max)
159 {
160   if (stringEq(min_max, "min")
161       || stringEq(min_max, "early"))
162     return &min_;
163   else if (stringEq(min_max, "max")
164 	   || stringEq(min_max, "late"))
165     return &max_;
166   else if (stringEq(min_max, "all")
167 	   || stringEq(min_max, "min_max")
168 	   || stringEq(min_max, "minmax"))
169     return &all_;
170   else
171     return nullptr;
172 }
173 
174 ////////////////////////////////////////////////////////////////
175 
MinMaxIterator(const MinMaxAll * min_max)176 MinMaxIterator::MinMaxIterator(const MinMaxAll *min_max)
177 {
178   if (min_max == MinMaxAll::all()) {
179     index_ = 0;
180     index_max_ = MinMax::index_max;
181   }
182   else {
183     index_ = min_max->asMinMax()->index();
184     index_max_ = index_;
185   }
186 }
187 
188 } // namespace
189