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 "RCDelayCalc.hh"
18 
19 #include "Liberty.hh"
20 #include "Network.hh"
21 #include "Sdc.hh"
22 #include "Parasitics.hh"
23 #include "GraphDelayCalc.hh"
24 
25 namespace sta {
26 
RCDelayCalc(StaState * sta)27 RCDelayCalc::RCDelayCalc(StaState *sta) :
28   LumpedCapDelayCalc(sta)
29 {
30 }
31 
32 ArcDelayCalc *
copy()33 RCDelayCalc::copy()
34 {
35   return new RCDelayCalc(this);
36 }
37 
38 void
inputPortDelay(const Pin *,float in_slew,const RiseFall * rf,Parasitic * parasitic,const DcalcAnalysisPt *)39 RCDelayCalc::inputPortDelay(const Pin *,
40 			    float in_slew,
41 			    const RiseFall *rf,
42 			    Parasitic *parasitic,
43 			    const DcalcAnalysisPt *)
44 {
45   drvr_parasitic_ = parasitic;
46   drvr_slew_ = in_slew;
47   drvr_rf_ = rf;
48   drvr_cell_ = nullptr;
49   drvr_library_ = network_->defaultLibertyLibrary();
50   multi_drvr_slew_factor_ = 1.0F;
51 }
52 
53 // For DSPF on an input port the elmore delay is used as the time
54 // constant of an exponential waveform.  The delay to the logic
55 // threshold and slew are computed for the exponential waveform.
56 // Note that this uses the driver thresholds and relies on
57 // thresholdAdjust to convert the delay and slew to the load's thresholds.
58 void
dspfWireDelaySlew(const Pin *,float elmore,ArcDelay & wire_delay,Slew & load_slew)59 RCDelayCalc::dspfWireDelaySlew(const Pin *,
60 			       float elmore,
61 			       ArcDelay &wire_delay,
62 			       Slew &load_slew)
63 {
64   float vth = .5;
65   float vl = .2;
66   float vh = .8;
67   float slew_derate = 1.0;
68   if (drvr_library_) {
69     vth = drvr_library_->inputThreshold(drvr_rf_);
70     vl = drvr_library_->slewLowerThreshold(drvr_rf_);
71     vh = drvr_library_->slewUpperThreshold(drvr_rf_);
72     slew_derate = drvr_library_->slewDerateFromLibrary();
73   }
74   wire_delay = static_cast<float>(-elmore * log(1.0 - vth));
75   load_slew = (drvr_slew_ + elmore * log((1.0 - vl) / (1.0 - vh))
76 	       / slew_derate) * multi_drvr_slew_factor_;
77 }
78 
79 } // namespace
80