1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2020, 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 #pragma once
18 
19 #include "MinMax.hh"
20 #include "Error.hh"
21 
22 namespace sta {
23 
24 template <class TYPE>
25 class MinMaxValues
26 {
27 public:
MinMaxValues()28   MinMaxValues()
29   {
30     clear();
31   }
32 
MinMaxValues(TYPE init_value)33   MinMaxValues(TYPE init_value)
34   {
35     int mm_index;
36 
37     mm_index = MinMax::minIndex();
38     values_[mm_index] = init_value;
39     exists_[mm_index] = true;
40 
41     mm_index = MinMax::maxIndex();
42     values_[mm_index] = init_value;
43     exists_[mm_index] = true;
44   }
45 
46   void
clear()47   clear()
48   {
49     exists_[MinMax::minIndex()] = false;
50     exists_[MinMax::maxIndex()] = false;
51   }
52 
53   void
clear(const MinMaxAll * min_max)54   clear(const MinMaxAll *min_max)
55   {
56     exists_[min_max->index()] = false;
57   }
58 
59   bool
empty()60   empty()
61   {
62     return !exists_[MinMax::minIndex()]
63       && !exists_[MinMax::maxIndex()];
64   }
65 
66   void
setValue(TYPE value)67   setValue(TYPE value)
68   {
69     for (auto mm_index : MinMax::rangeIndex()) {
70       values_[mm_index] = value;
71       exists_[mm_index] = true;
72     }
73   }
74 
75   void
setValue(const MinMaxAll * min_max,TYPE value)76   setValue(const MinMaxAll *min_max,
77 	   TYPE value)
78   {
79     for (auto mm_index : min_max->rangeIndex()) {
80       values_[mm_index] = value;
81       exists_[mm_index] = true;
82     }
83   }
84 
85   void
setValue(const MinMax * min_max,TYPE value)86   setValue(const MinMax *min_max,
87 	   TYPE value)
88   {
89     int mm_index = min_max->index();
90     values_[mm_index] = value;
91     exists_[mm_index] = true;
92   }
93 
94   void
mergeValue(const MinMax * min_max,TYPE value)95   mergeValue(const MinMax *min_max,
96 	     TYPE value)
97   {
98     int mm_index = min_max->index();
99     if (!exists_[mm_index]
100 	|| min_max->compare(value, values_[mm_index])) {
101       values_[mm_index] = value;
102       exists_[mm_index] = true;
103     }
104   }
105 
106   TYPE
value(const MinMax * min_max) const107   value(const MinMax *min_max) const
108   {
109     int mm_index = min_max->index();
110     bool exists = exists_[mm_index];
111     if (exists)
112       return values_[mm_index];
113     else
114       criticalError(226, "uninitialized value reference");
115   }
116 
117   void
value(const MinMax * min_max,TYPE & value,bool & exists) const118   value(const MinMax *min_max,
119 	// Return values.
120 	TYPE &value,
121 	bool &exists) const
122   {
123     int mm_index = min_max->index();
124     exists = exists_[mm_index];
125     value = values_[mm_index];
126   }
127 
128   bool
hasValue(const MinMax * min_max) const129   hasValue(const MinMax *min_max) const
130   {
131     int mm_index = min_max->index();
132     return exists_[mm_index];
133   }
134 
135   void
removeValue(const MinMaxAll * min_max)136   removeValue(const MinMaxAll *min_max)
137   {
138     for (auto mm_index : min_max->rangeIndex())
139       exists_[mm_index] = false;
140   }
141 
equal(MinMaxValues * values1,MinMaxValues * values2)142   static bool equal(MinMaxValues *values1,
143 		    MinMaxValues *values2)
144   {
145     return ((!values1->exists_[MinMax::minIndex()]
146 	     && !values2->exists_[MinMax::minIndex()])
147 	    || (values1->exists_[MinMax::minIndex()]
148 		&& values2->exists_[MinMax::minIndex()]
149 		&& values1->values_[MinMax::minIndex()]
150 		== values2->values_[MinMax::minIndex()]))
151       && ((!values1->exists_[MinMax::maxIndex()]
152 	   && !values2->exists_[MinMax::maxIndex()])
153 	 || (values1->exists_[MinMax::maxIndex()]
154 	     && values2->exists_[MinMax::maxIndex()]
155 	     && values1->values_[MinMax::maxIndex()]
156 	     == values2->values_[MinMax::maxIndex()]));
157   }
158 
159 private:
160   TYPE values_[MinMax::index_count];
161   bool exists_[MinMax::index_count];
162 };
163 
164 typedef MinMaxValues<float> MinMaxFloatValues;
165 typedef MinMaxValues<int> MinMaxIntValues;
166 
167 } // namespace
168