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