1 #include <ot/timer/pin.hpp>
2 #include <ot/timer/arc.hpp>
3 #include <ot/timer/net.hpp>
4 #include <ot/timer/test.hpp>
5
6 namespace ot {
7
8 // Constructor
PrimaryOutput(Pin & pin)9 PrimaryOutput::PrimaryOutput(Pin& pin) : _pin {pin} {
10 }
11
12 // Function: rat
rat(Split el,Tran rf) const13 std::optional<float> PrimaryOutput::rat(Split el, Tran rf) const {
14 return _rat[el][rf];
15 }
16
17 // Function: slack
slack(Split el,Tran rf) const18 std::optional<float> PrimaryOutput::slack(Split el, Tran rf) const {
19 if(_pin._at[el][rf] && _rat[el][rf]) {
20 return el == MIN ? *_pin._at[el][rf] - *_rat[el][rf] : *_rat[el][rf] - *_pin._at[el][rf];
21 }
22 else {
23 return std::nullopt;
24 }
25 }
26
27 // Procedure: _scale_time
_scale_time(float s)28 void PrimaryOutput::_scale_time(float s) {
29 FOR_EACH_EL_RF_IF(el, rf, _rat[el][rf]) {
30 _rat[el][rf] = _rat[el][rf].value() * s;
31 }
32 }
33
34 // Procedure: _scale_capacitance
_scale_capacitance(float s)35 void PrimaryOutput::_scale_capacitance(float s) {
36 FOR_EACH_EL_RF_IF(el, rf, _load[el][rf]) {
37 _load[el][rf] *= s;
38 }
39 }
40
41 // ------------------------------------------------------------------------------------------------
42
43 // Constructor
PrimaryInput(Pin & pin)44 PrimaryInput::PrimaryInput(Pin& pin) : _pin {pin} {
45 }
46
47 // Procedure: _scale_time
_scale_time(float s)48 void PrimaryInput::_scale_time(float s) {
49 FOR_EACH_EL_RF(el, rf) {
50 if(_slew[el][rf]) {
51 _slew[el][rf] = _slew[el][rf].value() * s;
52 }
53 if(_at[el][rf]) {
54 _at[el][rf] = _at[el][rf].value() * s;
55 }
56 }
57 }
58
59 // ------------------------------------------------------------------------------------------------
60
61 // Constructor
At(Arc * a,Split el,Tran rf,float v)62 Pin::At::At(Arc* a, Split el, Tran rf, float v) :
63 pi_arc {a},
64 pi_el {el},
65 pi_rf {rf},
66 numeric {v} {
67 }
68
69 // ------------------------------------------------------------------------------------------------
70
71 // Constructor
Slew(Arc * a,Split el,Tran rf,float v)72 Pin::Slew::Slew(Arc* a, Split el, Tran rf, float v) :
73 pi_arc {a},
74 pi_el {el},
75 pi_rf {rf},
76 numeric {v} {
77 }
78
79 // ------------------------------------------------------------------------------------------------
80
81 // Constructor
Rat(Arc * a,Split el,Tran rf,float v)82 Pin::Rat::Rat(Arc* a, Split el, Tran rf, float v) :
83 pi_arc {a},
84 pi_el {el},
85 pi_rf {rf},
86 numeric {v} {
87 }
88
89 // ------------------------------------------------------------------------------------------------
90
91 // Constructor
Pin(const std::string & name)92 Pin::Pin(const std::string& name) : _name {name} {
93 }
94
95 // Procedure: _reset_slew
_reset_slew()96 void Pin::_reset_slew() {
97 FOR_EACH_EL_RF(el, rf) {
98 _slew[el][rf].reset();
99 }
100 }
101
102 // Procedure: _reset_at
_reset_at()103 void Pin::_reset_at() {
104 FOR_EACH_EL_RF(el, rf) {
105 _at[el][rf].reset();
106 }
107 }
108
109 // Procedure: _reset_rat
_reset_rat()110 void Pin::_reset_rat() {
111 FOR_EACH_EL_RF(el, rf) {
112 _rat[el][rf].reset();
113 }
114 }
115
116 // Function: has_self_loop
has_self_loop() const117 bool Pin::has_self_loop() const {
118 auto& arcs = num_fanins() < num_fanouts() ? _fanin : _fanout;
119 return std::find_if(arcs.begin(), arcs.end(), [] (auto arc) {
120 return arc->is_self_loop();
121 }) != arcs.end();
122 }
123
124 // Function: is_input
is_input() const125 bool Pin::is_input() const {
126 return std::visit(Functors{
127 [] (PrimaryInput*) {
128 return true;
129 },
130 [] (PrimaryOutput*) {
131 return false;
132 },
133 [] (CellpinView cp) {
134 return cp[MIN]->direction == CellpinDirection::INPUT;
135 }
136 }, _handle);
137 }
138
139 // Function: is_output
is_output() const140 bool Pin::is_output() const {
141 return std::visit(Functors{
142 [] (PrimaryInput*) {
143 return false;
144 },
145 [] (PrimaryOutput*) {
146 return true;
147 },
148 [] (CellpinView cp) {
149 return cp[MIN]->direction == CellpinDirection::OUTPUT;
150 }
151 }, _handle);
152 }
153
154 // Function: is_rct_root
155 // Query if the pin is a rc root of a net.
is_rct_root() const156 bool Pin::is_rct_root() const {
157 return std::visit(Functors{
158 [] (PrimaryInput*) {
159 return true;
160 },
161 [] (PrimaryOutput*) {
162 return false;
163 },
164 [] (CellpinView cp) {
165 return cp[MIN]->direction == CellpinDirection::OUTPUT;
166 }
167 }, _handle);
168 }
169
170 // Function: is_datapath_source
171 // Return true if the node is attached to a datapath source.
is_datapath_source() const172 bool Pin::is_datapath_source() const {
173
174 // No fanin
175 if(num_fanins() == 0) {
176 return true;
177 }
178 // Clock cell pin
179 else if(auto cp = cellpin(MIN)) {
180 return (cp->is_clock && cp->is_clock.value() == true);
181 }
182 // Primary input
183 else if(primary_input()) {
184 return true;
185 }
186 // Otherwise
187 else {
188 return false;
189 }
190 }
191
192 // Procedure: _insert_fanin
193 // Insert an arc into the fanin list of the pin.
_insert_fanin(Arc & arc)194 void Pin::_insert_fanin(Arc& arc) {
195 assert(&arc._to == this);
196 arc._fanin_satellite = _fanin.insert(_fanin.end(), &arc);
197 }
198
199 // Procedure: _insert_fanout
_insert_fanout(Arc & arc)200 void Pin::_insert_fanout(Arc& arc) {
201 assert(&arc._from == this);
202 arc._fanout_satellite = _fanout.insert(_fanout.end(), &arc);
203 }
204
205 // Procedure: _remove_fanout
_remove_fanout(Arc & arc)206 void Pin::_remove_fanout(Arc& arc) {
207 assert(arc._fanout_satellite && &arc._from == this);
208 _fanout.erase(*(arc._fanout_satellite));
209 arc._fanout_satellite.reset();
210 }
211
212 // Procedure: _remove_fanin
_remove_fanin(Arc & arc)213 void Pin::_remove_fanin(Arc& arc) {
214 assert(arc._fanin_satellite && &arc._to == this);
215 _fanin.erase(*(arc._fanin_satellite));
216 arc._fanin_satellite.reset();
217 }
218
219 // Function: _find_fanin
_find_fanin(Pin & from)220 Arc* Pin::_find_fanin(Pin& from) {
221 auto itr = std::find_if(_fanin.begin(), _fanin.end(), [&] (Arc* arc) {
222 return &(arc->_from) == &from;
223 });
224 return itr == _fanin.end() ? nullptr : *itr;
225 }
226
227 // Function: _find_fanout
_find_fanout(Pin & to)228 Arc* Pin::_find_fanout(Pin& to) {
229 auto itr = std::find_if(_fanout.begin(), _fanout.end(), [&] (Arc* arc) {
230 return &(arc->_to) == &to;
231 });
232 return itr == _fanout.end() ? nullptr : *itr;
233 }
234
235 // Function: at
at(Split el,Tran rf) const236 std::optional<float> Pin::at(Split el, Tran rf) const {
237 return _at[el][rf];
238 }
239
240 // Function: rat
rat(Split el,Tran rf) const241 std::optional<float> Pin::rat(Split el, Tran rf) const {
242 return _rat[el][rf];
243 }
244
245 // Function: slew
slew(Split el,Tran rf) const246 std::optional<float> Pin::slew(Split el, Tran rf) const {
247 return _slew[el][rf];
248 }
249
250 // Function: slack
slack(Split el,Tran rf) const251 std::optional<float> Pin::slack(Split el, Tran rf) const {
252 if(_at[el][rf] && _rat[el][rf]) {
253 return el == MIN ? *_at[el][rf] - *_rat[el][rf] : *_rat[el][rf] - *_at[el][rf];
254 }
255 else return std::nullopt;
256 }
257
258 // Function: _delta_at
_delta_at(Split lel,Tran lrf,Split rel,Tran rrf) const259 std::optional<float> Pin::_delta_at(Split lel, Tran lrf, Split rel, Tran rrf) const {
260 if(_at[lel][lrf] && _at[rel][rrf]) {
261 return *_at[lel][lrf] - *_at[rel][rrf];
262 }
263 else return std::nullopt;
264 }
265
266 // Function: _delta_slew
_delta_slew(Split lel,Tran lrf,Split rel,Tran rrf) const267 std::optional<float> Pin::_delta_slew(Split lel, Tran lrf, Split rel, Tran rrf) const {
268 if(_slew[lel][lrf] && _slew[rel][rrf]) {
269 return *_slew[lel][lrf] - *_slew[rel][rrf];
270 }
271 else return std::nullopt;
272 }
273
274 // Function: _delta_rat
_delta_rat(Split lel,Tran lrf,Split rel,Tran rrf) const275 std::optional<float> Pin::_delta_rat(Split lel, Tran lrf, Split rel, Tran rrf) const {
276 if(_rat[lel][lrf] && _rat[rel][rrf]) {
277 return *_rat[lel][lrf] - *_rat[rel][rrf];
278 }
279 else return std::nullopt;
280 }
281
282 // Function: cap
283 // Query the pin capacitance. A pin belongs to three categories: 1) cellpin, 2) primary input,
284 // and 3) primary output. A cellot_pin.has only one type of capacitance. A primary input has no
285 // capacitance. The primary output has load capacitance.
cap(Split el,Tran rf) const286 float Pin::cap(Split el, Tran rf) const {
287
288 return std::visit(Functors{
289 [] (PrimaryInput*) {
290 return 0.0f;
291 },
292 [&] (PrimaryOutput* po) {
293 return po->_load[el][rf];
294 },
295 [&] (CellpinView cp) {
296 if(rf == RISE && cp[el]->rise_capacitance) {
297 return cp[el]->rise_capacitance.value();
298 }
299 else if(rf == FALL && cp[el]->fall_capacitance) {
300 return cp[el]->fall_capacitance.value();
301 }
302 else {
303 return cp[el]->capacitance ? cp[el]->capacitance.value() : 0.0f;
304 }
305 }
306 }, _handle);
307 }
308
309 // Function: load
310 // The total capacitive load is defined as the sum of the input capacitance
311 // of all the other devices sharing the trace.
312 // Note that the capacitance of the device driving the trace is not included.
313 //float Pin::load(Split el, Tran rf) const {
314 //
315 // // Case 1: The pin is a rctree root.
316 // if(is_rct_root()) {
317 // return _net ? _net->load(el, rf) : 0.0f;
318 // }
319 //
320 // // Case 2: The pin is not a rctree root.
321 // return cap(el, rf);
322 //}
323
324 // Procedure: _relax_slew
325 // Update the slew of the node
_relax_slew(Arc * arc,Split fel,Tran frf,Split tel,Tran trf,float val)326 void Pin::_relax_slew(Arc* arc, Split fel, Tran frf, Split tel, Tran trf, float val) {
327
328 switch(tel) {
329
330 case MIN:
331 if(!_slew[tel][trf] || val < *_slew[tel][trf]) {
332 _slew[tel][trf].emplace(arc, fel, frf, val);
333 }
334 break;
335
336 case MAX:
337 if(!_slew[tel][trf] || val > *_slew[tel][trf]) {
338 _slew[tel][trf].emplace(arc, fel, frf, val);
339 }
340 break;
341 };
342 }
343
344 // Procedure: _relax_at
345 // Update the arrival time of the node from a given fanin node.
_relax_at(Arc * arc,Split fel,Tran frf,Split tel,Tran trf,float val)346 void Pin::_relax_at(Arc* arc, Split fel, Tran frf, Split tel, Tran trf, float val) {
347
348 switch (tel) {
349 case MIN:
350 if(!_at[tel][trf] || val < *_at[tel][trf]) {
351 _at[tel][trf].emplace(arc, fel, frf, val);
352 }
353 break;
354 case MAX:
355 if(!_at[tel][trf] || val > *_at[tel][trf]) {
356 _at[tel][trf].emplace(arc, fel, frf, val);
357 }
358 break;
359 }
360 }
361
362 // Procedure: _relax_rat
363 // Update the arrival time of the node
_relax_rat(Arc * arc,Split fel,Tran frf,Split tel,Tran trf,float val)364 void Pin::_relax_rat(Arc* arc, Split fel, Tran frf, Split tel, Tran trf, float val) {
365
366 switch(fel) {
367
368 case MIN:
369 if(!_rat[fel][frf] || val > *_rat[fel][frf]) {
370 _rat[fel][frf].emplace(arc, tel, trf, val);
371 }
372 break;
373
374 case MAX:
375 if(!_rat[fel][frf] || val < *_rat[fel][frf]) {
376 _rat[fel][frf].emplace(arc, tel, trf, val);
377 }
378 break;
379 };
380 }
381
382 // Procedure: _remap_cellpin
_remap_cellpin(Split el,const Cellpin * cpin)383 void Pin::_remap_cellpin(Split el, const Cellpin* cpin) {
384
385 (std::get<CellpinView>(_handle))[el] = cpin;
386
387 if(_net) {
388 _net->_rc_timing_updated = false;
389 }
390 }
391
392 // Procedure: _remap_cellpin
_remap_cellpin(Split el,const Cellpin & cpin)393 void Pin::_remap_cellpin(Split el, const Cellpin& cpin) {
394
395 (std::get<CellpinView>(_handle))[el] = &cpin;
396
397 if(_net) {
398 _net->_rc_timing_updated = false;
399 }
400 }
401
402 // Procedure: _remove_state
_remove_state(int s)403 void Pin::_remove_state(int s) {
404 if(s == 0) _state = 0;
405 else {
406 _state &= ~s;
407 }
408 }
409
410 // Procedure: _insert_state
_insert_state(int s)411 void Pin::_insert_state(int s) {
412 _state |= s;
413 }
414
415 // Function: _has_state
_has_state(int s) const416 bool Pin::_has_state(int s) const {
417 return _state & s;
418 }
419
420 // Function: _has_no_state
_has_no_state(int s) const421 bool Pin::_has_no_state(int s) const {
422 return !_has_state(s);
423 }
424
425 }; // end of namespace ot. -----------------------------------------------------------------------
426
427
428
429
430
431
432
433
434