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