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 "InputDrive.hh"
18
19 namespace sta {
20
InputDrive()21 InputDrive::InputDrive()
22 {
23 for (auto tr_index : RiseFall::rangeIndex()) {
24 for (auto mm_index : MinMax::rangeIndex())
25 drive_cells_[tr_index][mm_index] = nullptr;
26 }
27 }
28
~InputDrive()29 InputDrive::~InputDrive()
30 {
31 for (auto tr_index : RiseFall::rangeIndex()) {
32 for (auto mm_index : MinMax::rangeIndex()) {
33 InputDriveCell *drive_cell = drive_cells_[tr_index][mm_index];
34 delete drive_cell;
35 }
36 }
37 }
38
39 void
setSlew(const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)40 InputDrive::setSlew(const RiseFallBoth *rf,
41 const MinMaxAll *min_max,
42 float slew)
43 {
44 slews_.setValue(rf, min_max, slew);
45 }
46
47 void
setDriveResistance(const RiseFallBoth * rf,const MinMaxAll * min_max,float res)48 InputDrive::setDriveResistance(const RiseFallBoth *rf,
49 const MinMaxAll *min_max,
50 float res)
51 {
52 drive_resistances_.setValue(rf, min_max, res);
53 }
54
55 void
driveResistance(const RiseFall * rf,const MinMax * min_max,float & res,bool & exists)56 InputDrive::driveResistance(const RiseFall *rf,
57 const MinMax *min_max,
58 float &res,
59 bool &exists)
60 {
61 drive_resistances_.value(rf, min_max, res, exists);
62 }
63
64 bool
hasDriveResistance(const RiseFall * rf,const MinMax * min_max)65 InputDrive::hasDriveResistance(const RiseFall *rf, const MinMax *min_max)
66 {
67 return drive_resistances_.hasValue(rf, min_max);
68 }
69
70 bool
driveResistanceMinMaxEqual(const RiseFall * rf)71 InputDrive::driveResistanceMinMaxEqual(const RiseFall *rf)
72 {
73 float min_res, max_res;
74 bool min_exists, max_exists;
75 drive_resistances_.value(rf, MinMax::min(), min_res, min_exists);
76 drive_resistances_.value(rf, MinMax::max(), max_res, max_exists);
77 return min_exists && max_exists && min_res == max_res;
78 }
79
80 void
setDriveCell(LibertyLibrary * library,LibertyCell * cell,LibertyPort * from_port,float * from_slews,LibertyPort * to_port,const RiseFallBoth * rf,const MinMaxAll * min_max)81 InputDrive::setDriveCell(LibertyLibrary *library,
82 LibertyCell *cell,
83 LibertyPort *from_port,
84 float *from_slews,
85 LibertyPort *to_port,
86 const RiseFallBoth *rf,
87 const MinMaxAll *min_max)
88 {
89 for (auto rf_index : rf->rangeIndex()) {
90 for (auto mm_index : min_max->rangeIndex()) {
91 InputDriveCell *drive = drive_cells_[rf_index][mm_index];
92 if (drive) {
93 drive->setLibrary(library);
94 drive->setCell(cell);
95 drive->setFromPort(from_port);
96 drive->setFromSlews(from_slews);
97 drive->setToPort(to_port);
98 }
99 else {
100 drive = new InputDriveCell(library, cell, from_port,
101 from_slews, to_port);
102 drive_cells_[rf_index][mm_index] = drive;
103 }
104 }
105 }
106 }
107
108 void
driveCell(const RiseFall * rf,const MinMax * min_max,LibertyCell * & cell,LibertyPort * & from_port,float * & from_slews,LibertyPort * & to_port)109 InputDrive::driveCell(const RiseFall *rf,
110 const MinMax *min_max,
111 LibertyCell *&cell,
112 LibertyPort *&from_port,
113 float *&from_slews,
114 LibertyPort *&to_port)
115 {
116 InputDriveCell *drive = drive_cells_[rf->index()][min_max->index()];
117 if (drive) {
118 cell = drive->cell();
119 from_port = drive->fromPort();
120 from_slews = drive->fromSlews();
121 to_port = drive->toPort();
122 }
123 else
124 cell = nullptr;
125 }
126
127 InputDriveCell *
driveCell(const RiseFall * rf,const MinMax * min_max)128 InputDrive::driveCell(const RiseFall *rf,
129 const MinMax *min_max)
130 {
131 return drive_cells_[rf->index()][min_max->index()];
132 }
133
134 bool
hasDriveCell(const RiseFall * rf,const MinMax * min_max)135 InputDrive::hasDriveCell(const RiseFall *rf,
136 const MinMax *min_max)
137 {
138 return drive_cells_[rf->index()][min_max->index()] != nullptr;
139 }
140
141 bool
driveCellsEqual()142 InputDrive::driveCellsEqual()
143 {
144 int rise_index = RiseFall::riseIndex();
145 int fall_index = RiseFall::fallIndex();
146 int min_index = MinMax::minIndex();
147 int max_index = MinMax::maxIndex();
148 InputDriveCell *drive1 = drive_cells_[rise_index][min_index];
149 InputDriveCell *drive2 = drive_cells_[rise_index][max_index];
150 InputDriveCell *drive3 = drive_cells_[fall_index][min_index];
151 InputDriveCell *drive4 = drive_cells_[fall_index][max_index];
152 return drive1->equal(drive2)
153 && drive1->equal(drive3)
154 && drive1->equal(drive4);
155 }
156
157 void
slew(const RiseFall * rf,const MinMax * min_max,float & slew,bool & exists)158 InputDrive::slew(const RiseFall *rf,
159 const MinMax *min_max,
160 float &slew,
161 bool &exists)
162 {
163 slews_.value(rf, min_max, slew, exists);
164 }
165
166 ////////////////////////////////////////////////////////////////
167
InputDriveCell(LibertyLibrary * library,LibertyCell * cell,LibertyPort * from_port,float * from_slews,LibertyPort * to_port)168 InputDriveCell::InputDriveCell(LibertyLibrary *library,
169 LibertyCell *cell,
170 LibertyPort *from_port,
171 float *from_slews,
172 LibertyPort *to_port) :
173 library_(library),
174 cell_(cell),
175 from_port_(from_port),
176 to_port_(to_port)
177 {
178 setFromSlews(from_slews);
179 }
180
181 void
setLibrary(LibertyLibrary * library)182 InputDriveCell::setLibrary(LibertyLibrary *library)
183 {
184 library_ = library;
185 }
186
187 void
setCell(LibertyCell * cell)188 InputDriveCell::setCell(LibertyCell *cell)
189 {
190 cell_ = cell;
191 }
192
193 void
setFromPort(LibertyPort * from_port)194 InputDriveCell::setFromPort(LibertyPort *from_port)
195 {
196 from_port_ = from_port;
197 }
198
199 void
setToPort(LibertyPort * to_port)200 InputDriveCell::setToPort(LibertyPort *to_port)
201 {
202 to_port_ = to_port;
203 }
204
205 void
setFromSlews(float * from_slews)206 InputDriveCell::setFromSlews(float *from_slews)
207 {
208 for (auto tr_index : RiseFall::rangeIndex())
209 from_slews_[tr_index] = from_slews[tr_index];
210 }
211
212 bool
equal(InputDriveCell * drive) const213 InputDriveCell::equal(InputDriveCell *drive) const
214 {
215 int rise_index = RiseFall::riseIndex();
216 int fall_index = RiseFall::fallIndex();
217 return cell_ == drive->cell_
218 && from_port_ == drive->from_port_
219 && from_slews_[rise_index] == drive->from_slews_[rise_index]
220 && from_slews_[fall_index] == drive->from_slews_[fall_index]
221 && to_port_ == drive->to_port_;
222 }
223
224 } // namespace
225