1 #ifndef OT_TIMER_TIMER_HPP_
2 #define OT_TIMER_TIMER_HPP_
3
4 #include <ot/timer/gate.hpp>
5 #include <ot/timer/pin.hpp>
6 #include <ot/timer/arc.hpp>
7 #include <ot/timer/net.hpp>
8 #include <ot/timer/test.hpp>
9 #include <ot/timer/clock.hpp>
10 #include <ot/timer/endpoint.hpp>
11 #include <ot/timer/path.hpp>
12 #include <ot/timer/sfxt.hpp>
13 #include <ot/timer/pfxt.hpp>
14 #include <ot/timer/cppr.hpp>
15 #include <ot/timer/scc.hpp>
16 #include <ot/static/logger.hpp>
17 #include <ot/spef/spef.hpp>
18 #include <ot/verilog/verilog.hpp>
19 #include <ot/sdc/sdc.hpp>
20 #include <ot/tau/tau15.hpp>
21
22 namespace ot {
23
24 // Class: Timer
25 class Timer {
26
27 friend class Shell;
28
29 constexpr static int FULL_TIMING = 0x01;
30 constexpr static int EPTS_UPDATED = 0x02;
31 constexpr static int AREA_UPDATED = 0x04;
32 constexpr static int POWER_UPDATED = 0x08;
33
34 public:
35
36 // Builder
37 Timer& set_num_threads(unsigned);
38 Timer& read_celllib(std::filesystem::path, std::optional<Split> = {});
39 Timer& read_verilog(std::filesystem::path);
40 Timer& read_spef(std::filesystem::path);
41 Timer& read_sdc(std::filesystem::path);
42 Timer& read_timing(std::filesystem::path);
43 Timer& insert_net(std::string);
44 Timer& insert_gate(std::string, std::string);
45 Timer& repower_gate(std::string, std::string);
46 Timer& remove_net(std::string);
47 Timer& remove_gate(std::string);
48 Timer& disconnect_pin(std::string);
49 Timer& connect_pin(std::string, std::string);
50 Timer& insert_primary_input(std::string);
51 Timer& insert_primary_output(std::string);
52 Timer& set_at(std::string, Split, Tran, std::optional<float>);
53 Timer& set_rat(std::string, Split, Tran, std::optional<float>);
54 Timer& set_slew(std::string, Split, Tran, std::optional<float>);
55 Timer& set_load(std::string, Split, Tran, std::optional<float>);
56 Timer& create_clock(std::string, float);
57 Timer& create_clock(std::string, std::string, float);
58 Timer& cppr(bool);
59 Timer& set_time_unit(second_t);
60 Timer& set_capacitance_unit(farad_t);
61 Timer& set_resistance_unit(ohm_t);
62 Timer& set_voltage_unit(volt_t);
63 Timer& set_power_unit(watt_t);
64 Timer& set_current_unit(ampere_t);
65
66 // Action.
67 void update_timing();
68
69 std::optional<float> report_at(const std::string&, Split, Tran);
70 std::optional<float> report_rat(const std::string&, Split, Tran);
71 std::optional<float> report_slew(const std::string&, Split, Tran);
72 std::optional<float> report_slack(const std::string&, Split, Tran);
73 std::optional<float> report_load(const std::string&, Split, Tran);
74 std::optional<float> report_area();
75 std::optional<float> report_leakage_power();
76 std::optional<float> report_tns(std::optional<Split> = {}, std::optional<Tran> = {});
77 std::optional<float> report_wns(std::optional<Split> = {}, std::optional<Tran> = {});
78 std::optional<size_t> report_fep(std::optional<Split> = {}, std::optional<Tran> = {});
79
80 std::vector<Path> report_timing(size_t);
81 std::vector<Path> report_timing(size_t, Split);
82 std::vector<Path> report_timing(size_t, Tran);
83 std::vector<Path> report_timing(size_t, Split, Tran);
84 std::vector<Path> report_timing(PathGuide);
85
86 // Accessor
87 void dump_graph(std::ostream&) const;
88 void dump_taskflow(std::ostream&) const;
89 void dump_cell(std::ostream&, const std::string&, Split) const;
90 void dump_celllib(std::ostream&, Split) const;
91 void dump_net_load(std::ostream&) const;
92 void dump_pin_cap(std::ostream&) const;
93 void dump_at(std::ostream&) const;
94 void dump_rat(std::ostream&) const;
95 void dump_slew(std::ostream&) const;
96 void dump_slack(std::ostream&) const;
97 void dump_timer(std::ostream&) const;
98 void dump_verilog(std::ostream&, const std::string&) const;
99 void dump_spef(std::ostream&) const;
100 void dump_rctree(std::ostream&) const;
101
102 inline auto num_primary_inputs() const;
103 inline auto num_primary_outputs() const;
104 inline auto num_pins() const;
105 inline auto num_nets() const;
106 inline auto num_arcs() const;
107 inline auto num_gates() const;
108 inline auto num_tests() const;
109 inline auto num_sccs() const;
110 inline auto time_unit() const;
111 inline auto power_unit() const;
112 inline auto resistance_unit() const;
113 inline auto current_unit() const;
114 inline auto voltage_unit() const;
115 inline auto capacitance_unit() const;
116
117 inline const auto& primary_inputs() const;
118 inline const auto& primary_outputs() const;
119 inline const auto& pins() const;
120 inline const auto& nets() const;
121 inline const auto& gates() const;
122 inline const auto& clocks() const;
123 inline const auto& tests() const;
124 inline const auto& arcs() const;
125
126 private:
127
128 mutable std::shared_mutex _mutex;
129
130 tf::Taskflow _taskflow;
131 tf::Executor _executor;
132
133 int _state {0};
134
135 bool _scc_analysis {false};
136
137 std::optional<tf::Task> _lineage;
138 std::optional<CpprAnalysis> _cppr_analysis;
139 std::optional<second_t> _time_unit;
140 std::optional<watt_t> _power_unit;
141 std::optional<ohm_t> _resistance_unit;
142 std::optional<farad_t> _capacitance_unit;
143 std::optional<ampere_t> _current_unit;
144 std::optional<volt_t> _voltage_unit;
145
146 TimingData<std::optional<Celllib>, MAX_SPLIT> _celllib;
147
148 std::unordered_map<std::string, PrimaryInput> _pis;
149 std::unordered_map<std::string, PrimaryOutput> _pos;
150 std::unordered_map<std::string, Pin> _pins;
151 std::unordered_map<std::string, Net> _nets;
152 std::unordered_map<std::string, Gate> _gates;
153 std::unordered_map<std::string, Clock> _clocks;
154
155 std::list<Test> _tests;
156 std::list<Arc> _arcs;
157 std::list<Pin*> _frontiers;
158 std::list<SCC> _sccs;
159
160 TimingData<std::vector<Endpoint>, MAX_SPLIT, MAX_TRAN> _endpoints;
161 TimingData<std::optional<float>, MAX_SPLIT, MAX_TRAN> _wns;
162 TimingData<std::optional<float>, MAX_SPLIT, MAX_TRAN> _tns;
163 TimingData<std::optional<size_t>, MAX_SPLIT, MAX_TRAN> _fep;
164
165 std::optional<float> _area;
166 std::optional<float> _leakage_power;
167
168 std::deque<Pin*> _fprop_cands;
169 std::deque<Pin*> _bprop_cands;
170
171 IndexGenerator<size_t> _pin_idx_gen {0u};
172 IndexGenerator<size_t> _arc_idx_gen {0u};
173
174 std::vector<Pin*> _scc_cands;
175 std::vector<Pin*> _idx2pin;
176 std::vector<Arc*> _idx2arc;
177
178 std::vector<Endpoint*> _worst_endpoints(size_t);
179 std::vector<Endpoint*> _worst_endpoints(size_t, Split);
180 std::vector<Endpoint*> _worst_endpoints(size_t, Tran);
181 std::vector<Endpoint*> _worst_endpoints(size_t, Split, Tran);
182 std::vector<Endpoint*> _worst_endpoints(const PathGuide&);
183
184 std::vector<Path> _report_timing(std::vector<Endpoint*>&&, size_t);
185
186 bool _is_redundant_timing(const Timing&, Split) const;
187
188 void _to_time_unit(const second_t&);
189 void _to_capacitance_unit(const farad_t&);
190 void _to_resistance_unit(const ohm_t&);
191 void _to_power_unit(const watt_t&);
192 void _to_current_unit(const ampere_t&);
193 void _to_voltage_unit(const volt_t&);
194 void _add_to_lineage(tf::Task);
195 void _rebase_unit(Celllib&);
196 void _rebase_unit(spef::Spef&);
197 void _update_timing();
198 void _update_endpoints();
199 void _update_area();
200 void _update_power();
201 void _fprop_rc_timing(Pin&);
202 void _fprop_slew(Pin&);
203 void _fprop_delay(Pin&);
204 void _fprop_at(Pin&);
205 void _fprop_test(Pin&);
206 void _bprop_rat(Pin&);
207 void _build_prop_cands();
208 void _build_fprop_cands(Pin&);
209 void _build_bprop_cands(Pin&);
210 void _build_prop_tasks();
211 void _clear_prop_tasks();
212 void _read_spef(spef::Spef&);;
213 void _verilog(vlog::Module&);
214 void _timing(tau15::Timing&);
215 void _read_sdc(sdc::SDC&);
216 void _read_sdc(sdc::SetInputDelay&);
217 void _read_sdc(sdc::SetInputTransition&);
218 void _read_sdc(sdc::SetOutputDelay&);
219 void _read_sdc(sdc::SetLoad&);
220 void _read_sdc(sdc::CreateClock&);
221 void _connect_pin(Pin&, Net&);
222 void _disconnect_pin(Pin&);
223 void _insert_frontier(Pin&);
224 void _remove_frontier(Pin&);
225 void _remove_scc(SCC&);
226 void _clear_frontiers();
227 void _insert_primary_output(const std::string&);
228 void _insert_primary_input(const std::string&);
229 void _insert_gate(const std::string&, const std::string&);
230 void _insert_gate_arcs(Gate&);
231 void _remove_gate_arcs(Gate&);
232 void _repower_gate(const std::string&, const std::string&);
233 void _remove_gate(Gate&);
234 void _remove_net(Net&);
235 void _remove_pin(Pin&);
236 void _remove_arc(Arc&);
237 void _remove_test(Test&);
238 void _set_at(PrimaryInput&, Split, Tran, std::optional<float>);
239 void _set_slew(PrimaryInput&, Split, Tran, std::optional<float>);
240 void _set_rat(PrimaryOutput&, Split, Tran, std::optional<float>);
241 void _set_load(PrimaryOutput&, Split, Tran, std::optional<float>);
242 void _cppr(bool);
243 void _topologize(SfxtCache&, size_t) const;
244 void _spfa(SfxtCache&) const;
245 void _spdp(SfxtCache&) const;
246 void _recover_prefix(Path&, const SfxtCache&, size_t) const;
247 void _recover_datapath(Path&, const SfxtCache&) const;
248 void _recover_datapath(Path&, const SfxtCache&, const PfxtNode*, size_t) const;
249 void _enable_full_timing_update();
250 void _merge_celllib(Celllib&, Split);
251 void _insert_full_timing_frontiers();
252 void _spur(Endpoint&, size_t, PathHeap&) const;
253 void _spur(PfxtCache&, const PfxtNode&) const;
254 void _dump_graph(std::ostream&) const;
255 void _dump_taskflow(std::ostream&) const;
256 void _dump_cell(std::ostream&, const std::string&, Split) const;
257 void _dump_celllib(std::ostream&, Split) const;
258 void _dump_net_load(std::ostream&) const;
259 void _dump_pin_cap(std::ostream&) const;
260 void _dump_slew(std::ostream&) const;
261 void _dump_slack(std::ostream&) const;
262 void _dump_at(std::ostream&) const;
263 void _dump_rat(std::ostream&) const;
264 void _dump_timer(std::ostream&) const;
265 void _dump_timing(std::ostream&) const;
266 void _dump_verilog(std::ostream&, const std::string&) const;
267 void _dump_spef(std::ostream&) const;
268 void _dump_rctree(std::ostream&) const;
269
270 template <typename... T, std::enable_if_t<(sizeof...(T)>1), void>* = nullptr >
271 void _insert_frontier(T&&...);
272
273 SfxtCache _sfxt_cache(const Endpoint&) const;
274 SfxtCache _sfxt_cache(const PrimaryOutput&, Split, Tran) const;
275 SfxtCache _sfxt_cache(const Test&, Split, Tran) const;
276 CpprCache _cppr_cache(const Test&, Split, Tran) const;
277 PfxtCache _pfxt_cache(const SfxtCache&) const;
278
279 Net& _insert_net(const std::string&);
280 Pin& _insert_pin(const std::string&);
281 Arc& _insert_arc(Pin&, Pin&, Net&);
282 Arc& _insert_arc(Pin&, Pin&, Test&);
283 Arc& _insert_arc(Pin&, Pin&, TimingView);
284 SCC& _insert_scc(std::vector<Pin*>&);
285 Test& _insert_test(Arc&);
286 Clock& _create_clock(const std::string&, Pin&, float);
287 Clock& _create_clock(const std::string&, float);
288
289 std::optional<float> _report_at(const std::string&, Split, Tran);
290 std::optional<float> _report_rat(const std::string&, Split, Tran);
291 std::optional<float> _report_slew(const std::string&, Split, Tran);
292 std::optional<float> _report_slack(const std::string&, Split, Tran);
293 std::optional<float> _report_load(const std::string&, Split, Tran);
294 std::optional<float> _cppr_credit(const Test&, Split, Tran) const;
295 std::optional<float> _cppr_credit(const CpprCache&, Pin&, Split, Tran) const;
296 std::optional<float> _cppr_offset(const CpprCache&, Pin&, Split, Tran) const;
297 std::optional<float> _sfxt_offset(const SfxtCache&, size_t) const;
298
299 size_t _max_pin_name_size() const;
300 size_t _max_net_name_size() const;
301
302 inline auto _encode_pin(Pin&, Tran) const;
303 inline auto _decode_pin(size_t) const;
304 inline auto _encode_arc(Arc&, Tran, Tran) const;
305 inline auto _decode_arc(size_t) const;
306 inline auto _has_state(int) const;
307 inline auto _insert_state(int);
308 inline auto _remove_state(int = 0);
309
310 };
311
312 // Procedure: _insert_frontier
313 template <typename... T, std::enable_if_t<(sizeof...(T)>1), void>*>
_insert_frontier(T &&...pins)314 void Timer::_insert_frontier(T&&... pins) {
315 (_insert_frontier(pins), ...);
316 }
317
318 // Function: num_primary_inputs
num_primary_inputs() const319 inline auto Timer::num_primary_inputs() const {
320 return _pis.size();
321 }
322
323 // Function: num_primary_outputs
num_primary_outputs() const324 inline auto Timer::num_primary_outputs() const {
325 return _pos.size();
326 }
327
328 // Function: num_pins
num_pins() const329 inline auto Timer::num_pins() const {
330 return _pins.size();
331 }
332
333 // Function: num_nets
num_nets() const334 inline auto Timer::num_nets() const {
335 return _nets.size();
336 }
337
338 // Function: num_arcs
num_arcs() const339 inline auto Timer::num_arcs() const {
340 return _arcs.size();
341 }
342
343 // Function: num_gates
num_gates() const344 inline auto Timer::num_gates() const {
345 return _gates.size();
346 }
347
348 // Function: num_tests
num_tests() const349 inline auto Timer::num_tests() const {
350 return _tests.size();
351 }
352
353 // Function: num_sccs
num_sccs() const354 inline auto Timer::num_sccs() const {
355 return _sccs.size();
356 }
357
358 // Function: time_unit
time_unit() const359 inline auto Timer::time_unit() const {
360 return _time_unit;
361 }
362
363 // Function: power_unit
power_unit() const364 inline auto Timer::power_unit() const {
365 return _power_unit;
366 }
367
368 // Function: resistance_unit
resistance_unit() const369 inline auto Timer::resistance_unit() const {
370 return _resistance_unit;
371 }
372
373 // Function: current_unit
current_unit() const374 inline auto Timer::current_unit() const {
375 return _current_unit;
376 }
377
378 // Function: voltage_unit
voltage_unit() const379 inline auto Timer::voltage_unit() const {
380 return _voltage_unit;
381 }
382
383 // Function: capacitance_unit
capacitance_unit() const384 inline auto Timer::capacitance_unit() const {
385 return _capacitance_unit;
386 }
387
388 // Function: primary_inputs
389 // expose the primary input data structure to users
primary_inputs() const390 inline const auto& Timer::primary_inputs() const {
391 return _pis;
392 }
393
394 // Function: primary_outputs
395 // Expose the primary output data structure to users
primary_outputs() const396 inline const auto& Timer::primary_outputs() const {
397 return _pos;
398 }
399
400 // Function: pins
401 // Expose the pin data structure to users
pins() const402 inline const auto& Timer::pins() const {
403 return _pins;
404 }
405
406 // Function: nets
407 // Expose the net data structure to users
nets() const408 inline const auto& Timer::nets() const {
409 return _nets;
410 }
411
412 // Function: gates
413 // Expose the gate data structure to users
gates() const414 inline const auto& Timer::gates() const {
415 return _gates;
416 }
417
418 // Function: clocks
419 // Expose the clock data structure to users
clocks() const420 inline const auto& Timer::clocks() const {
421 return _clocks;
422 }
423
424 // Function: tests
425 // Expose the test data structure to users
tests() const426 inline const auto& Timer::tests() const {
427 return _tests;
428 }
429
430 // Function: arcs
431 // Expose the arc data structure to users
arcs() const432 inline const auto& Timer::arcs() const {
433 return _arcs;
434 }
435
436 // Function: _encode_pin
_encode_pin(Pin & pin,Tran rf) const437 inline auto Timer::_encode_pin(Pin& pin, Tran rf) const {
438 return rf == RISE ? pin._idx : pin._idx + _idx2pin.size();
439 }
440
441 // Function: _decode_pin
_decode_pin(size_t idx) const442 inline auto Timer::_decode_pin(size_t idx) const {
443 return std::make_tuple(_idx2pin[idx%_idx2pin.size()], idx<_idx2pin.size() ? RISE : FALL);
444 }
445
446 // Function: _encode_arc
_encode_arc(Arc & arc,Tran frf,Tran trf) const447 inline auto Timer::_encode_arc(Arc& arc, Tran frf, Tran trf) const {
448 if(frf == RISE) {
449 return arc._idx + (trf == RISE ? 0 : _idx2arc.size());
450 }
451 else {
452 return arc._idx + (trf == RISE ? _idx2arc.size()*2 : _idx2arc.size()*3);
453 }
454 }
455
456 // Function: _decode_arc
_decode_arc(size_t idx) const457 inline auto Timer::_decode_arc(size_t idx) const {
458 if(auto s = _idx2arc.size(); idx < s) {
459 return std::make_tuple(_idx2arc[idx % s], RISE, RISE);
460 }
461 else if(idx < 2*s) {
462 return std::make_tuple(_idx2arc[idx % s], RISE, FALL);
463 }
464 else if(idx < 3*s) {
465 return std::make_tuple(_idx2arc[idx % s], FALL, RISE);
466 }
467 else {
468 return std::make_tuple(_idx2arc[idx % s], FALL, FALL);
469 }
470 }
471
472 // Function: _has_state
_has_state(int s) const473 inline auto Timer::_has_state(int s) const {
474 return _state & s;
475 }
476
477 // Procedure: _insert_state
_insert_state(int s)478 inline auto Timer::_insert_state(int s) {
479 _state |= s;
480 }
481
482 // Procedure: _remove_state
_remove_state(int s)483 inline auto Timer::_remove_state(int s) {
484 if(s == 0) _state = 0;
485 else {
486 _state &= ~s;
487 }
488 }
489
490 }; // end of namespace ot ------------------------------------------------------------------------
491
492 #endif
493
494
495
496
497