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 "Delay.hh"
18
19 #include <cmath> // sqrt
20
21 #include "StaConfig.hh"
22 #include "Error.hh"
23 #include "StringUtil.hh"
24 #include "Fuzzy.hh"
25 #include "Units.hh"
26 #include "StaState.hh"
27
28 // SSTA compilation.
29 #if (SSTA == 1)
30
31 namespace sta {
32
33 inline float
square(float x)34 square(float x)
35 {
36 return x * x;
37 }
38
39 static Delay delay_init_values[MinMax::index_count];
40
41 void
initDelayConstants()42 initDelayConstants()
43 {
44 delay_init_values[MinMax::minIndex()] = MinMax::min()->initValue();
45 delay_init_values[MinMax::maxIndex()] = MinMax::max()->initValue();
46 }
47
48 const Delay &
delayInitValue(const MinMax * min_max)49 delayInitValue(const MinMax *min_max)
50 {
51 return delay_init_values[min_max->index()];
52 }
53
Delay()54 Delay::Delay() :
55 mean_(0.0),
56 sigma2_(0.0)
57 {
58 }
59
Delay(const Delay & delay)60 Delay::Delay(const Delay &delay) :
61 mean_(delay.mean_),
62 sigma2_(delay.sigma2_)
63 {
64 }
65
Delay(float mean)66 Delay::Delay(float mean) :
67 mean_(mean),
68 sigma2_(0.0)
69 {
70 }
71
Delay(float mean,float sigma2)72 Delay::Delay(float mean,
73 float sigma2) :
74 mean_(mean),
75 sigma2_(sigma2)
76 {
77 }
78
79 float
sigma() const80 Delay::sigma() const
81 {
82 if (sigma2_ < 0.0)
83 // Sigma is negative for crpr to offset sigmas in the common
84 // clock path.
85 return -sqrt(-sigma2_);
86 else
87 return sqrt(sigma2_);
88 }
89
90 float
sigma2() const91 Delay::sigma2() const
92 {
93 return sigma2_;
94 }
95
96 void
operator =(const Delay & delay)97 Delay::operator=(const Delay &delay)
98 {
99 mean_ = delay.mean_;
100 sigma2_ = delay.sigma2_;
101 }
102
103 void
operator =(float delay)104 Delay::operator=(float delay)
105 {
106 mean_ = delay;
107 sigma2_ = 0.0;
108 }
109
110 void
operator +=(const Delay & delay)111 Delay::operator+=(const Delay &delay)
112 {
113 mean_ += delay.mean_;
114 sigma2_ += delay.sigma2_;
115 }
116
117 void
operator +=(float delay)118 Delay::operator+=(float delay)
119 {
120 mean_ += delay;
121 }
122
123 Delay
operator +(const Delay & delay) const124 Delay::operator+(const Delay &delay) const
125 {
126 return Delay(mean_ + delay.mean_,
127 sigma2_ + delay.sigma2_);
128 }
129
130 Delay
operator +(float delay) const131 Delay::operator+(float delay) const
132 {
133 return Delay(mean_ + delay, sigma2_);
134 }
135
136 Delay
operator -(const Delay & delay) const137 Delay::operator-(const Delay &delay) const
138 {
139 return Delay(mean_ - delay.mean_,
140 sigma2_ + delay.sigma2_);
141 }
142
143 Delay
operator -(float delay) const144 Delay::operator-(float delay) const
145 {
146 return Delay(mean_ - delay, sigma2_);
147 }
148
149 Delay
operator -() const150 Delay::operator-() const
151 {
152 return Delay(-mean_, sigma2_);
153 }
154
155 void
operator -=(float delay)156 Delay::operator-=(float delay)
157 {
158 mean_ -= delay;
159 }
160
161 void
operator -=(const Delay & delay)162 Delay::operator-=(const Delay &delay)
163 {
164 mean_ -= delay.mean_;
165 sigma2_ += delay.sigma2_;
166 }
167
168 bool
operator ==(const Delay & delay) const169 Delay::operator==(const Delay &delay) const
170 {
171 return delayEqual(*this, delay);
172 }
173
174 ////////////////////////////////////////////////////////////////
175
176 Delay
makeDelay(float delay,float sigma,float)177 makeDelay(float delay,
178 float sigma,
179 float)
180 {
181 return Delay(delay, square(sigma));
182 }
183
184 Delay
makeDelay2(float delay,float sigma2,float)185 makeDelay2(float delay,
186 float sigma2,
187 float )
188 {
189 return Delay(delay, sigma2);
190 }
191
192 float
delayAsFloat(const Delay & delay,const EarlyLate * early_late,const StaState * sta)193 delayAsFloat(const Delay &delay,
194 const EarlyLate *early_late,
195 const StaState *sta)
196 {
197 if (sta->pocvEnabled()) {
198 if (early_late == EarlyLate::early())
199 return delay.mean() - delay.sigma() * sta->sigmaFactor();
200 else if (early_late == EarlyLate::late())
201 return delay.mean() + delay.sigma() * sta->sigmaFactor();
202 else
203 sta->report()->critical(594, "unknown early/late value.");
204 }
205 return delay.mean();
206 }
207
208 float
delaySigma2(const Delay & delay,const EarlyLate *)209 delaySigma2(const Delay &delay,
210 const EarlyLate *)
211 {
212 return delay.sigma2();
213 }
214
215 const char *
delayAsString(const Delay & delay,const StaState * sta)216 delayAsString(const Delay &delay,
217 const StaState *sta)
218 {
219 return delayAsString(delay, sta, sta->units()->timeUnit()->digits());
220 }
221
222 const char *
delayAsString(const Delay & delay,const StaState * sta,int digits)223 delayAsString(const Delay &delay,
224 const StaState *sta,
225 int digits)
226 {
227 const Unit *unit = sta->units()->timeUnit();
228 if (sta->pocvEnabled()) {
229 float sigma = delay.sigma();
230 return stringPrintTmp("%s[%s]",
231 unit->asString(delay.mean(), digits),
232 unit->asString(sigma, digits));
233 }
234 else
235 return unit->asString(delay.mean(), digits);
236 }
237
238 const char *
delayAsString(const Delay & delay,const EarlyLate * early_late,const StaState * sta,int digits)239 delayAsString(const Delay &delay,
240 const EarlyLate *early_late,
241 const StaState *sta,
242 int digits)
243 {
244 float mean_sigma = delayAsFloat(delay, early_late, sta);
245 return sta->units()->timeUnit()->asString(mean_sigma, digits);
246 }
247
248 bool
delayIsInitValue(const Delay & delay,const MinMax * min_max)249 delayIsInitValue(const Delay &delay,
250 const MinMax *min_max)
251 {
252 return fuzzyEqual(delay.mean(), min_max->initValue())
253 && delay.sigma2() == 0.0;
254 }
255
256 bool
delayZero(const Delay & delay)257 delayZero(const Delay &delay)
258 {
259 return fuzzyZero(delay.mean())
260 && fuzzyZero(delay.sigma2());
261 }
262
263 bool
delayInf(const Delay & delay)264 delayInf(const Delay &delay)
265 {
266 return fuzzyInf(delay.mean());
267 }
268
269 bool
delayEqual(const Delay & delay1,const Delay & delay2)270 delayEqual(const Delay &delay1,
271 const Delay &delay2)
272 {
273 return fuzzyEqual(delay1.mean(), delay2.mean())
274 && fuzzyEqual(delay1.sigma2(), delay2.sigma2());
275 }
276
277 bool
delayLess(const Delay & delay1,const Delay & delay2,const StaState * sta)278 delayLess(const Delay &delay1,
279 const Delay &delay2,
280 const StaState *sta)
281 {
282 return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta),
283 delayAsFloat(delay2, EarlyLate::early(), sta));
284 }
285
286 bool
delayLess(const Delay & delay1,float delay2,const StaState * sta)287 delayLess(const Delay &delay1,
288 float delay2,
289 const StaState *sta)
290 {
291 return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta),
292 delay2);
293 }
294
295 bool
delayLess(const Delay & delay1,const Delay & delay2,const MinMax * min_max,const StaState * sta)296 delayLess(const Delay &delay1,
297 const Delay &delay2,
298 const MinMax *min_max,
299 const StaState *sta)
300 {
301 if (min_max == MinMax::max())
302 return delayLess(delay1, delay2, sta);
303 else
304 return delayGreater(delay1, delay2, sta);
305 }
306
307 bool
delayLessEqual(const Delay & delay1,const Delay & delay2,const StaState * sta)308 delayLessEqual(const Delay &delay1,
309 const Delay &delay2,
310 const StaState *sta)
311 {
312 return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta),
313 delayAsFloat(delay2, EarlyLate::early(), sta));
314 }
315
316 bool
delayLessEqual(const Delay & delay1,float delay2,const StaState * sta)317 delayLessEqual(const Delay &delay1,
318 float delay2,
319 const StaState *sta)
320 {
321 return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta),
322 delay2);
323 }
324
325 bool
delayLessEqual(const Delay & delay1,const Delay & delay2,const MinMax * min_max,const StaState * sta)326 delayLessEqual(const Delay &delay1,
327 const Delay &delay2,
328 const MinMax *min_max,
329 const StaState *sta)
330 {
331 if (min_max == MinMax::max())
332 return delayLessEqual(delay1, delay2, sta);
333 else
334 return delayGreaterEqual(delay1, delay2, sta);
335 }
336
337 bool
delayGreater(const Delay & delay1,const Delay & delay2,const StaState * sta)338 delayGreater(const Delay &delay1,
339 const Delay &delay2,
340 const StaState *sta)
341
342 {
343 return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta),
344 delayAsFloat(delay2, EarlyLate::late(), sta));
345 }
346
347 bool
delayGreater(const Delay & delay1,float delay2,const StaState * sta)348 delayGreater(const Delay &delay1,
349 float delay2,
350 const StaState *sta)
351 {
352 return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta),
353 delay2);
354 }
355
356 bool
delayGreaterEqual(const Delay & delay1,const Delay & delay2,const StaState * sta)357 delayGreaterEqual(const Delay &delay1,
358 const Delay &delay2,
359 const StaState *sta)
360 {
361 return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta),
362 delayAsFloat(delay2, EarlyLate::late(), sta));
363 }
364
365 bool
delayGreaterEqual(const Delay & delay1,float delay2,const StaState * sta)366 delayGreaterEqual(const Delay &delay1,
367 float delay2,
368 const StaState *sta)
369 {
370 return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta),
371 delay2);
372 }
373
374 bool
delayGreater(const Delay & delay1,const Delay & delay2,const MinMax * min_max,const StaState * sta)375 delayGreater(const Delay &delay1,
376 const Delay &delay2,
377 const MinMax *min_max,
378 const StaState *sta)
379 {
380 if (min_max == MinMax::max())
381 return delayGreater(delay1, delay2, sta);
382 else
383 return delayLess(delay1, delay2, sta);
384 }
385
386 bool
delayGreaterEqual(const Delay & delay1,const Delay & delay2,const MinMax * min_max,const StaState * sta)387 delayGreaterEqual(const Delay &delay1,
388 const Delay &delay2,
389 const MinMax *min_max,
390 const StaState *sta)
391 {
392 if (min_max == MinMax::max())
393 return delayGreaterEqual(delay1, delay2, sta);
394 else
395 return delayLessEqual(delay1, delay2, sta);
396 }
397
398 Delay
delayRemove(const Delay & delay1,const Delay & delay2)399 delayRemove(const Delay &delay1,
400 const Delay &delay2)
401 {
402 return Delay(delay1.mean() - delay2.mean(),
403 delay1.sigma2() - delay2.sigma2());
404 }
405
406 float
delayRatio(const Delay & delay1,const Delay & delay2)407 delayRatio(const Delay &delay1,
408 const Delay &delay2)
409 {
410 return delay1.mean() / delay2.mean();
411 }
412
413 Delay
operator +(float delay1,const Delay & delay2)414 operator+(float delay1,
415 const Delay &delay2)
416 {
417 return Delay(delay1 + delay2.mean(),
418 delay2.sigma2());
419 }
420
421 Delay
operator /(float delay1,const Delay & delay2)422 operator/(float delay1,
423 const Delay &delay2)
424 {
425 return Delay(delay1 / delay2.mean(),
426 delay2.sigma2());
427 }
428
429 Delay
operator *(const Delay & delay1,float delay2)430 operator*(const Delay &delay1,
431 float delay2)
432 {
433 return Delay(delay1.mean() * delay2,
434 delay1.sigma2() * delay2 * delay2);
435 }
436
437 } // namespace
438
439 #endif // (SSTA == 1)
440