liberty_db/timing/timing_type.rs
1//! <script>
2//! IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
3//! </script>
4use core::{fmt, str::FromStr};
5
6use crate::{common::items::MaxMin, expression::logic};
7
8/// # Combinational Timing Arcs
9///
10/// The timing type and timing sense define the signal propagation pattern.
11/// The default timing type is combinational. Table shows the timing
12/// type and timing sense values for combinational timing arcs.
13/// The default timing type is combinational.
14/// <a name ="reference_link" href="
15/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
16/// ?field=test
17/// &bgn
18/// =331.4
19/// &end
20/// =331.8
21/// ">Reference</a>
22/// <script>
23/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
24/// </script>
25///
26/// <table>
27/// <thead>
28/// <tr>
29/// <th>Timing type</th>
30/// <th></th>
31/// <th>Timing sense</th>
32/// <th></th>
33/// </tr>
34/// <tr>
35/// <th></th>
36/// <th><code>positive_unate</code></th>
37/// <th><code>negative_unate</code></th>
38/// <th><code>non_unate</code></th>
39/// </tr>
40/// </thead>
41/// <tbody>
42/// <tr>
43/// <td><code>combinational</code></td>
44/// <td>R->R, F->F</td>
45/// <td>R->F, F->R</td>
46/// <td>{R,F}->{R,F}</td>
47/// </tr>
48/// <tr>
49/// <td><code>combinational_rise</code></td>
50/// <td>R->R</td>
51/// <td>F->R</td>
52/// <td>{R,F}->R</td>
53/// </tr>
54/// <tr>
55/// <td><code>combinational_fall</code></td>
56/// <td>F->F</td>
57/// <td>R->F</td>
58/// <td>{R,F}->F</td>
59/// </tr>
60/// <tr>
61/// <td><code>three_state_disable</code></td>
62/// <td>R->{0Z,1Z}</td>
63/// <td>F->{0Z,1Z}</td>
64/// <td>{R,F}->{0Z,1Z}</td>
65/// </tr>
66/// <tr>
67/// <td><code>three_state_enable</code></td>
68/// <td>R->{Z0,Z1}</td>
69/// <td>F->{Z0,Z1}</td>
70/// <td>{R,F}->{Z0,Z1}</td>
71/// </tr>
72/// <tr>
73/// <td><code>three_state_disable_rise</code></td>
74/// <td>R->0Z</td>
75/// <td>F->0Z</td>
76/// <td>{R,F}->0Z</td>
77/// </tr>
78/// <tr>
79/// <td><code>three_state_disable_fall</code></td>
80/// <td>R->1Z</td>
81/// <td>F->1Z</td>
82/// <td>{R,F}->1Z</td>
83/// </tr>
84/// <tr>
85/// <td><code>three_state_enable_rise</code></td>
86/// <td>R->Z1</td>
87/// <td>F->Z1</td>
88/// <td>{R,F}->Z1</td>
89/// </tr>
90/// <tr>
91/// <td><code>three_state_enable_fall</code></td>
92/// <td>R->Z0</td>
93/// <td>F->Z0</td>
94/// <td>{R,F}->Z0</td>
95/// </tr>
96/// </tbody>
97/// </table>
98#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
99#[derive(serde::Serialize, serde::Deserialize)]
100pub enum ArcCombinational {
101 /// `combinational`(`Defualt`)/
102 /// `combinational_rise`/
103 /// `combinational_fall`
104 ///
105 /// <a name ="reference_link" href="
106 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
107 /// ?field=test
108 /// &bgn
109 /// =331.11
110 /// &end
111 /// =331.13
112 /// ">Reference</a>
113 Combinational(Option<logic::Edge>),
114 /// `three_state_disable`/
115 /// `three_state_disable_rise`/
116 /// `three_state_disable_fall`
117 ///
118 /// <a name ="reference_link" href="
119 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
120 /// ?field=test
121 /// &bgn
122 /// =331.14
123 /// +331.16
124 /// &end
125 /// =331.14
126 /// +331.17
127 /// ">Reference</a>
128 ThreeStateDisable(Option<logic::Edge>),
129 /// `three_state_enable`/
130 /// `three_state_enable_rise`/
131 /// `three_state_enable_fall`
132 ///
133 /// <a name ="reference_link" href="
134 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
135 /// ?field=test
136 /// &bgn
137 /// =331.15
138 /// +331.18
139 /// &end
140 /// =331.15
141 /// +331.19
142 /// ">Reference</a>
143 ThreeStateEnable(Option<logic::Edge>),
144}
145
146impl ArcCombinational {
147 const COMBINATIONAL: &'static str = "combinational";
148 const COMBINATIONAL_RISE: &'static str = "combinational_rise";
149 const COMBINATIONAL_FALL: &'static str = "combinational_fall";
150 const THREE_STATE_DISABLE: &'static str = "three_state_disable";
151 const THREE_STATE_DISABLE_RISE: &'static str = "three_state_disable_rise";
152 const THREE_STATE_DISABLE_FALL: &'static str = "three_state_disable_fall";
153 const THREE_STATE_ENABLE: &'static str = "three_state_enable";
154 const THREE_STATE_ENABLE_RISE: &'static str = "three_state_enable_rise";
155 const THREE_STATE_ENABLE_FALL: &'static str = "three_state_enable_fall";
156}
157
158impl fmt::Display for ArcCombinational {
159 #[inline]
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 match self {
162 Self::Combinational(edge) => match edge {
163 Some(_edge) => match _edge {
164 logic::Edge::F => write!(f, "{}", Self::COMBINATIONAL_FALL),
165 logic::Edge::R => write!(f, "{}", Self::COMBINATIONAL_RISE),
166 },
167 None => write!(f, "{}", Self::COMBINATIONAL),
168 },
169 Self::ThreeStateDisable(edge) => match edge {
170 Some(_edge) => match _edge {
171 logic::Edge::F => write!(f, "{}", Self::THREE_STATE_DISABLE_FALL),
172 logic::Edge::R => write!(f, "{}", Self::THREE_STATE_DISABLE_RISE),
173 },
174 None => write!(f, "{}", Self::THREE_STATE_DISABLE),
175 },
176 Self::ThreeStateEnable(edge) => match edge {
177 Some(_edge) => match _edge {
178 logic::Edge::F => write!(f, "{}", Self::THREE_STATE_ENABLE_FALL),
179 logic::Edge::R => write!(f, "{}", Self::THREE_STATE_ENABLE_RISE),
180 },
181 None => write!(f, "{}", Self::THREE_STATE_ENABLE),
182 },
183 }
184 }
185}
186
187/// # Sequential Timing Arcs
188///
189/// <a name ="reference_link" href="
190/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
191/// ?field=test
192/// &bgn
193/// =331.20
194/// &end
195/// =333.29
196/// ">Reference</a>
197/// <script>
198/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
199/// </script>
200///
201/// ## Example
202/// A sample library with the `timing_type` attribute and `minimum_pulse_width` and `minimum_period` values.
203/// ``` liberty
204/// library(ASIC) {
205/// ...
206/// delay_model : table_lookup;
207/// ...
208/// lu_table_template(pulse_width_template) {
209/// variable_1 : related_pin_transition;
210/// index_1 ("1.0, 2.0, 3.0");
211/// }
212/// cell(flop) {
213/// ...
214/// pin(CK) {
215/// direction : input;
216/// capacitance : 0.00707171;
217/// timing() {
218/// timing_type : "min_pulse_width";
219/// related_pin : "CK";
220/// ...
221/// rise_constraint("pulse_width_template") {
222/// index_1("0.000000, 1.000000, 2.00000");
223/// values ("6.000000, 6.250000, 7.2500000" );
224/// }
225/// fall_constraint("pulse_width_template") {
226/// index_1("0.000000, 1.000000, 2.00000");
227/// values ("6.000000, 6.250000, 7.2500000" );
228/// }
229/// }
230/// timing() {
231/// timing_type : "minimum_period";
232/// related_pin : "CK";
233/// rise_constraint("pulse_width_template") {
234/// index_1(" .000000, 1.000000, 2.00000");
235/// values ("6.000000, 6.250000, 7.2500000" );
236/// }
237/// fall_constraint("pulse_width_template") {
238/// index_1("0.000000, 1.000000, 2.00000");
239/// values ("6.000000, 6.250000, 7.2500000" );
240/// }
241/// }
242/// }
243/// ...
244/// } /* end cell */
245/// } /* end library */
246/// ```
247#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
248#[derive(serde::Serialize, serde::Deserialize)]
249pub enum ArcSequential {
250 /// `rising_edge`/
251 /// `falling_edge`
252 ///
253 /// Identifies a timing arc whose output pin is sensitive to a
254 /// `rising`/`falling` signal at the input pin.
255 /// <a name ="reference_link" href="
256 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
257 /// ?field=test
258 /// &bgn
259 /// =331.21
260 /// +331.24
261 /// &end
262 /// =331.23
263 /// +331.26
264 /// ">Reference</a>
265 Edge(logic::Edge),
266 /// `preset`
267 ///
268 /// Preset arcs affect only the rise arrival time of the arc’s endpoint pin.
269 /// A preset arc implies that you are asserting a logic 1 on the output pin
270 /// when the designated `related_pin` is asserted.
271 /// <a name ="reference_link" href="
272 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
273 /// ?field=test
274 /// &bgn
275 /// =331.27
276 /// &end
277 /// =331.30
278 /// ">Reference</a>
279 Preset,
280 /// `clear`
281 ///
282 /// Clear arcs affect only the fall arrival time of the arc’s endpoint pin.
283 /// A clear arc implies that you are asserting a logic 0 on the output pin
284 /// when the designated `related_pin` is asserted.
285 /// <a name ="reference_link" href="
286 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
287 /// ?field=test
288 /// &bgn
289 /// =332.2
290 /// &end
291 /// =332.5
292 /// ">Reference</a>
293 Clear,
294 /// `hold_rising`/
295 /// `hold_falling`
296 ///
297 /// Designates the `rising`/`falling` edge of the related pin for the hold check.
298 /// <a name ="reference_link" href="
299 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
300 /// ?field=test
301 /// &bgn
302 /// =332.6
303 /// +332.8
304 /// &end
305 /// =332.7
306 /// +332.9
307 /// ">Reference</a>
308 Hold(logic::Edge),
309 /// `setup_rising`/
310 /// `setup_falling`
311 ///
312 /// Designates the `rising`/`falling` edge of the related pin for the setup check
313 /// on clocked elements.
314 /// <a name ="reference_link" href="
315 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
316 /// ?field=test
317 /// &bgn
318 /// =332.10
319 /// +332.13
320 /// &end
321 /// =332.12
322 /// +332.15
323 /// ">Reference</a>
324 Setup(logic::Edge),
325 /// `recovery_rising`/
326 /// `recovery_falling`
327 ///
328 /// Uses the rising edge of the related pin for the recovery time check.
329 /// The clock is `rising-edge-triggered`/`falling-edge-triggered`.
330 /// <a name ="reference_link" href="
331 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
332 /// ?field=test
333 /// &bgn
334 /// =332.16
335 /// +332.19
336 /// &end
337 /// =332.18
338 /// +332.21
339 /// ">Reference</a>
340 Recovery(logic::Edge),
341 /// `skew_rising`/
342 /// `skew_falling`
343 ///
344 /// The timing constraint interval is measured from the rising edge of the
345 /// reference pin (specified in `related_pin`) to a transition edge of the
346 /// parent pin of the timing group.
347 ///
348 /// The `intrinsic_rise` value is the maximum skew time between the
349 /// reference pin `rising`/`falling` and the parent pin rising.
350 ///
351 /// The `intrinsic_fall` value is the maximum skew time between the
352 /// reference pin `rising`/`falling` and the parent pin falling.
353 /// <a name ="reference_link" href="
354 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
355 /// ?field=test
356 /// &bgn
357 /// =332.22
358 /// +332.28
359 /// &end
360 /// =332.27
361 /// +332.33
362 /// ">Reference</a>
363 Skew(logic::Edge),
364 /// `removal_rising`/
365 /// `removal_falling`
366 ///
367 /// Used when the cell is a `low-enable`/`high-enable` latch or a
368 /// `rising-edge-triggered`/`falling-edge-triggered` flip-flop.
369 ///
370 /// For active-low asynchronous control signals, define the removal
371 /// time with the `intrinsic_rise` attribute.
372 ///
373 /// For active-high asynchronous control signals, define the removal
374 /// time with the `intrinsic_fall` attribute.
375 /// <a name ="reference_link" href="
376 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
377 /// ?field=test
378 /// &bgn
379 /// =333.2
380 /// +333.7
381 /// &end
382 /// =333.6
383 /// +333.11
384 /// ">Reference</a>
385 Removal(logic::Edge),
386 /// `min_pulse_width`
387 ///
388 /// This value lets you specify the minimum pulse width for a clock pin.
389 /// The timing check is performed on the pin itself, so the `related pin`
390 /// should be the same. You need to specify both rise and fall constraints
391 /// to calculate the high and low pulse widths.
392 /// <a name ="reference_link" href="
393 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
394 /// ?field=test
395 /// &bgn
396 /// =333.12
397 /// &end
398 /// =333.16
399 /// ">Reference</a>
400 MinPulseWidth,
401 /// `minimum_period`
402 ///
403 /// This value lets you specify the minimum period for a clock pin.
404 /// The timing check is performed on the pin itself, so the `related pin`
405 /// should be the same. You need to specify both rise and fall constraints
406 /// to calculate the minimum clock period.
407 ///
408 /// Rise constraint is characterization data when the clock waveform has a
409 /// rising start edge. Fall constraint is characterization data when the
410 /// start edge of a waveform is falling.
411 /// <a name ="reference_link" href="
412 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
413 /// ?field=test
414 /// &bgn
415 /// =333.17
416 /// &end
417 /// =333.23
418 /// ">Reference</a>
419 MinimumPeriod,
420 /// `max_clock_tree_path`/
421 /// `min_clock_tree_path`
422 ///
423 /// Used in `timing` groups under a clock pin. Defines the `maximum`/`minimum`
424 /// clock tree path constraint.
425 /// <a name ="reference_link" href="
426 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
427 /// ?field=test
428 /// &bgn
429 /// =333.24
430 /// +333.27
431 /// &end
432 /// =333.26
433 /// +333.28
434 /// ">Reference</a>
435 ClockTreePath(MaxMin),
436}
437
438impl ArcSequential {
439 const RISING_EDGE: &'static str = "rising_edge";
440 const FALLING_EDGE: &'static str = "falling_edge";
441 const PRESET: &'static str = "preset";
442 const CLEAR: &'static str = "clear";
443 const HOLD_RISING: &'static str = "hold_rising";
444 const HOLD_FALLING: &'static str = "hold_falling";
445 const SETUP_RISING: &'static str = "setup_rising";
446 const SETUP_FALLING: &'static str = "setup_falling";
447 const RECOVERY_RISING: &'static str = "recovery_rising";
448 const RECOVERY_FALLING: &'static str = "recovery_falling";
449 const SKEW_RISING: &'static str = "skew_rising";
450 const SKEW_FALLING: &'static str = "skew_falling";
451 const REMOVAL_RISING: &'static str = "removal_rising";
452 const REMOVAL_FALLING: &'static str = "removal_falling";
453 const MIN_PULSE_WIDTH: &'static str = "min_pulse_width";
454 const MINIMUM_PERIOD: &'static str = "minimum_period";
455 const MAX_CLOCK_TREE_PATH: &'static str = "max_clock_tree_path";
456 const MIN_CLOCK_TREE_PATH: &'static str = "min_clock_tree_path";
457}
458
459impl fmt::Display for ArcSequential {
460 #[inline]
461 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462 match self {
463 Self::Edge(edge) => match edge {
464 logic::Edge::F => write!(f, "{}", Self::FALLING_EDGE),
465 logic::Edge::R => write!(f, "{}", Self::RISING_EDGE),
466 },
467 Self::Preset => write!(f, "{}", Self::PRESET),
468 Self::Clear => write!(f, "{}", Self::CLEAR),
469 Self::Hold(edge) => match edge {
470 logic::Edge::F => write!(f, "{}", Self::HOLD_FALLING),
471 logic::Edge::R => write!(f, "{}", Self::HOLD_RISING),
472 },
473 Self::Setup(edge) => match edge {
474 logic::Edge::F => write!(f, "{}", Self::SETUP_FALLING),
475 logic::Edge::R => write!(f, "{}", Self::SETUP_RISING),
476 },
477 Self::Recovery(edge) => match edge {
478 logic::Edge::F => write!(f, "{}", Self::RECOVERY_FALLING),
479 logic::Edge::R => write!(f, "{}", Self::RECOVERY_RISING),
480 },
481 Self::Skew(edge) => match edge {
482 logic::Edge::F => write!(f, "{}", Self::SKEW_FALLING),
483 logic::Edge::R => write!(f, "{}", Self::SKEW_RISING),
484 },
485 Self::Removal(edge) => match edge {
486 logic::Edge::F => write!(f, "{}", Self::REMOVAL_FALLING),
487 logic::Edge::R => write!(f, "{}", Self::REMOVAL_RISING),
488 },
489 Self::MinPulseWidth => write!(f, "{}", Self::MIN_PULSE_WIDTH),
490 Self::MinimumPeriod => write!(f, "{}", Self::MINIMUM_PERIOD),
491 Self::ClockTreePath(max_min) => match max_min {
492 MaxMin::Max => write!(f, "{}", Self::MAX_CLOCK_TREE_PATH),
493 MaxMin::Min => write!(f, "{}", Self::MIN_CLOCK_TREE_PATH),
494 },
495 }
496 }
497}
498
499/// # Nonsequential Timing Arcs
500///
501/// In some nonsequential cells, the setup and hold timing constraints are specified
502/// on the data pin with a nonclock pin as the related pin. It requires the signal of
503/// a pin to be stable for a specified period of time before and after another pin of
504/// the same cell range state so that the cell can function as expected.
505/// <a name ="reference_link" href="
506/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
507/// ?field=test
508/// &bgn
509/// =335.29
510/// &end
511/// =335.37
512/// ">Reference</a>
513/// <script>
514/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
515/// </script>
516#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
517#[derive(serde::Serialize, serde::Deserialize)]
518pub enum ArcNonSequential {
519 /// `non_seq_setup_rising`/
520 /// `non_seq_setup_falling`
521 ///
522 /// Defines (with `non_seq_setup_falling`/`non_seq_setup_rising`) the timing arcs used
523 /// for setup checks between pins with nonsequential behavior. The related pin in
524 /// a timing arc is used for the timing check.
525 /// <a name ="reference_link" href="
526 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
527 /// ?field=test
528 /// &bgn
529 /// =335.34
530 /// +335.38
531 /// &end
532 /// =335.37
533 /// +335.41
534 /// ">Reference</a>
535 NonSeqSetup(logic::Edge),
536 /// `non_seq_hold_rising`/
537 /// `non_seq_hold_falling`
538 ///
539 /// Defines (with `non_seq_hold_falling`/`non_seq_hold_rising`) the timing arcs used
540 /// for hold checks between pins with nonsequential behavior. The related pin in
541 /// a timing arc is used for the timing check.
542 /// <a name ="reference_link" href="
543 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
544 /// ?field=test
545 /// &bgn
546 /// =335.42
547 /// +336.2
548 /// &end
549 /// =335.45
550 /// +336.5
551 /// ">Reference</a>
552 NonSeqHold(logic::Edge),
553}
554
555impl ArcNonSequential {
556 const NON_SEQ_SETUP_RISING: &'static str = "non_seq_setup_rising";
557 const NON_SEQ_SETUP_FALLING: &'static str = "non_seq_setup_falling";
558 const NON_SEQ_HOLD_RISING: &'static str = "non_seq_hold_rising";
559 const NON_SEQ_HOLD_FALLING: &'static str = "non_seq_hold_falling";
560}
561
562impl fmt::Display for ArcNonSequential {
563 #[inline]
564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565 match self {
566 Self::NonSeqSetup(edge) => match edge {
567 logic::Edge::F => write!(f, "{}", Self::NON_SEQ_SETUP_FALLING),
568 logic::Edge::R => write!(f, "{}", Self::NON_SEQ_SETUP_RISING),
569 },
570 Self::NonSeqHold(edge) => match edge {
571 logic::Edge::F => write!(f, "{}", Self::NON_SEQ_HOLD_FALLING),
572 logic::Edge::R => write!(f, "{}", Self::NON_SEQ_HOLD_RISING),
573 },
574 }
575 }
576}
577
578/// # No-Change Timing Arcs
579///
580/// This feature models the timing requirement of latch devices with latch-enable signals.
581/// The four no-change timing types define the pulse waveforms of both the constrained signal
582/// and the related signal in standard CMOS and nonlinear CMOS delay models.
583/// The information is used in static timing verification during synthesis.
584/// <a name ="reference_link" href="
585/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
586/// ?field=test
587/// &bgn
588/// =336.6
589/// &end
590/// =336.10
591/// ">Reference</a>
592/// <script>
593/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
594/// </script>
595#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
596#[derive(serde::Serialize, serde::Deserialize)]
597pub enum ArcNoChange {
598 /// `nochange_high_high`/
599 /// `nochange_high_low`/
600 /// `nochange_low_high`/
601 /// `nochange_low_low`
602 ///
603 /// Indicates a `positive`/`positive`/`negative`/`negative` pulse on the constrained pin
604 /// and a `positive`/`negative`/`positive`/`negative` pulse on the related pin.
605 /// <a name ="reference_link" href="
606 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html
607 /// ?field=test
608 /// &bgn
609 /// =336.11
610 /// +336.14
611 /// +336.17
612 /// +336.20
613 /// &end
614 /// =336.13
615 /// +336.16
616 /// +336.19
617 /// +336.22
618 /// ">Reference</a>
619 NoChange(logic::Level, logic::Level),
620}
621
622impl ArcNoChange {
623 const NOCHANGE_HIGH_HIGH: &'static str = "nochange_high_high";
624 const NOCHANGE_HIGH_LOW: &'static str = "nochange_high_low";
625 const NOCHANGE_LOW_HIGH: &'static str = "nochange_low_high";
626 const NOCHANGE_LOW_LOW: &'static str = "nochange_low_low";
627}
628
629impl fmt::Display for ArcNoChange {
630 #[inline]
631 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632 match self {
633 Self::NoChange(s1, s2) => match (s1, s2) {
634 (logic::Level::H, logic::Level::H) => {
635 write!(f, "{}", Self::NOCHANGE_HIGH_HIGH)
636 }
637 (logic::Level::H, logic::Level::L) => {
638 write!(f, "{}", Self::NOCHANGE_HIGH_LOW)
639 }
640 (logic::Level::L, logic::Level::H) => {
641 write!(f, "{}", Self::NOCHANGE_LOW_HIGH)
642 }
643 (logic::Level::L, logic::Level::L) => {
644 write!(f, "{}", Self::NOCHANGE_LOW_LOW)
645 }
646 },
647 }
648 }
649}
650
651/// The `timing_type` attribute distinguishes between combinational
652/// and sequential cells by defining the type of timing arc.
653///
654/// If this attribute is not assigned, the cell is considered combinational (Default).
655/// <a name ="reference_link" href="
656/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=330.8+331.2+331.21+332.2+333.2+334.2+335.3+336.2&end=330.41+331.19+331.30+332.33+333.37+334.53+335.45+336.22
657/// ">Reference</a>
658/// <script>
659/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
660/// </script>
661///
662/// You must distinguish between combinational and sequential timing types,
663/// because each type serves a different purpose.
664///
665/// The Design Compiler tool uses the combinational timing arcs information to calculate
666/// the physical delays in timing propagation and to trace paths. The timing analyzer uses
667/// path-tracing arcs for circuit timing analysis.
668///
669/// The Design Compiler tool uses the sequential timing arcs information to determine
670/// rule-based design optimization constraints. More information on optimization
671/// constraints is available in the Design Compiler documentation.
672///
673/// The following sections show the `timing_type` attribute values for the following
674/// timing arcs. For information about when to use the different types, see the
675/// *Synopsys Liberty User Guide*.
676///
677/// + [`Combinational`](crate::timing::ArcCombinational)
678/// + [`Sequential`](crate::timing::ArcSequential)
679/// + [`NonSequential`](crate::timing::ArcNonSequential)
680/// + [`NoChange`](crate::timing::ArcNoChange)
681///
682/// #### Syntax
683/// `timing_type : combinational | combinational_rise | combinational_fall | three_state_disable |
684/// three_state_disable_rise | three_state_disable_fall | three_state_enable | three_state_enable_rise |
685/// three_state_enable_fall | rising_edge | falling_edge | preset | clear | hold_rising | hold_falling |
686/// setup_rising | setup_falling | recovery_rising | recovery_falling | skew_rising | skew_falling |
687/// removal_rising | removal_falling | min_pulse_width | minimum_period | max_clock_tree_path |
688/// min_clock_tree_path |non_seq_setup_rising | non_seq_setup_falling | non_seq_hold_rising |
689/// non_seq_hold_falling | nochange_high_high | nochange_high_low | nochange_low_high | nochange_low_low ;`
690#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
691// #[derive(liberty_macros::SingleSimple)]
692#[derive(serde::Serialize, serde::Deserialize)]
693pub enum TimingType {
694 /// [`Combinational`](crate::timing::ArcCombinational)
695 Combinational(ArcCombinational),
696 /// [`Sequential`](crate::timing::ArcSequential)
697 Sequential(ArcSequential),
698 /// [`NonSequential`](crate::timing::ArcNonSequential)
699 NonSequential(ArcNonSequential),
700 /// [`NoChange`](crate::timing::ArcNoChange)
701 NoChange(ArcNoChange),
702}
703crate::ast::impl_self_builder!(TimingType);
704crate::ast::impl_simple!(TimingType);
705
706impl FromStr for TimingType {
707 type Err = fmt::Error;
708 #[inline]
709 fn from_str(s: &str) -> Result<Self, Self::Err> {
710 match s {
711 ArcCombinational::COMBINATIONAL => Ok(Self::COMBINATIONAL),
712 ArcCombinational::COMBINATIONAL_RISE => Ok(Self::COMBINATIONAL_RISE),
713 ArcCombinational::COMBINATIONAL_FALL => Ok(Self::COMBINATIONAL_FALL),
714 ArcCombinational::THREE_STATE_DISABLE => Ok(Self::THREE_STATE_DISABLE),
715 ArcCombinational::THREE_STATE_DISABLE_RISE => Ok(Self::THREE_STATE_DISABLE_RISE),
716 ArcCombinational::THREE_STATE_DISABLE_FALL => Ok(Self::THREE_STATE_DISABLE_FALL),
717 ArcCombinational::THREE_STATE_ENABLE => Ok(Self::THREE_STATE_ENABLE),
718 ArcCombinational::THREE_STATE_ENABLE_RISE => Ok(Self::THREE_STATE_ENABLE_RISE),
719 ArcCombinational::THREE_STATE_ENABLE_FALL => Ok(Self::THREE_STATE_ENABLE_FALL),
720 ArcSequential::RISING_EDGE => Ok(Self::RISING_EDGE),
721 ArcSequential::FALLING_EDGE => Ok(Self::FALLING_EDGE),
722 ArcSequential::PRESET => Ok(Self::PRESET),
723 ArcSequential::CLEAR => Ok(Self::CLEAR),
724 ArcSequential::HOLD_RISING => Ok(Self::HOLD_RISING),
725 ArcSequential::HOLD_FALLING => Ok(Self::HOLD_FALLING),
726 ArcSequential::SETUP_RISING => Ok(Self::SETUP_RISING),
727 ArcSequential::SETUP_FALLING => Ok(Self::SETUP_FALLING),
728 ArcSequential::RECOVERY_RISING => Ok(Self::RECOVERY_RISING),
729 ArcSequential::RECOVERY_FALLING => Ok(Self::RECOVERY_FALLING),
730 ArcSequential::SKEW_RISING => Ok(Self::SKEW_RISING),
731 ArcSequential::SKEW_FALLING => Ok(Self::SKEW_FALLING),
732 ArcSequential::REMOVAL_RISING => Ok(Self::REMOVAL_RISING),
733 ArcSequential::REMOVAL_FALLING => Ok(Self::REMOVAL_FALLING),
734 ArcSequential::MIN_PULSE_WIDTH => Ok(Self::MIN_PULSE_WIDTH),
735 ArcSequential::MINIMUM_PERIOD => Ok(Self::MINIMUM_PERIOD),
736 ArcSequential::MAX_CLOCK_TREE_PATH => Ok(Self::MAX_CLOCK_TREE_PATH),
737 ArcSequential::MIN_CLOCK_TREE_PATH => Ok(Self::MIN_CLOCK_TREE_PATH),
738 ArcNonSequential::NON_SEQ_SETUP_RISING => Ok(Self::NON_SEQ_SETUP_RISING),
739 ArcNonSequential::NON_SEQ_SETUP_FALLING => Ok(Self::NON_SEQ_SETUP_FALLING),
740 ArcNonSequential::NON_SEQ_HOLD_RISING => Ok(Self::NON_SEQ_HOLD_RISING),
741 ArcNonSequential::NON_SEQ_HOLD_FALLING => Ok(Self::NON_SEQ_HOLD_FALLING),
742 ArcNoChange::NOCHANGE_HIGH_HIGH => Ok(Self::NOCHANGE_HIGH_HIGH),
743 ArcNoChange::NOCHANGE_HIGH_LOW => Ok(Self::NOCHANGE_HIGH_LOW),
744 ArcNoChange::NOCHANGE_LOW_HIGH => Ok(Self::NOCHANGE_LOW_HIGH),
745 ArcNoChange::NOCHANGE_LOW_LOW => Ok(Self::NOCHANGE_LOW_LOW),
746 _ => Err(fmt::Error),
747 }
748 }
749}
750
751impl fmt::Display for TimingType {
752 #[inline]
753 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
754 f.write_str(match *self {
755 Self::COMBINATIONAL => ArcCombinational::COMBINATIONAL,
756 Self::COMBINATIONAL_RISE => ArcCombinational::COMBINATIONAL_RISE,
757 Self::COMBINATIONAL_FALL => ArcCombinational::COMBINATIONAL_FALL,
758 Self::THREE_STATE_DISABLE => ArcCombinational::THREE_STATE_DISABLE,
759 Self::THREE_STATE_DISABLE_RISE => ArcCombinational::THREE_STATE_DISABLE_RISE,
760 Self::THREE_STATE_DISABLE_FALL => ArcCombinational::THREE_STATE_DISABLE_FALL,
761 Self::THREE_STATE_ENABLE => ArcCombinational::THREE_STATE_ENABLE,
762 Self::THREE_STATE_ENABLE_RISE => ArcCombinational::THREE_STATE_ENABLE_RISE,
763 Self::THREE_STATE_ENABLE_FALL => ArcCombinational::THREE_STATE_ENABLE_FALL,
764 Self::RISING_EDGE => ArcSequential::RISING_EDGE,
765 Self::FALLING_EDGE => ArcSequential::FALLING_EDGE,
766 Self::PRESET => ArcSequential::PRESET,
767 Self::CLEAR => ArcSequential::CLEAR,
768 Self::HOLD_RISING => ArcSequential::HOLD_RISING,
769 Self::HOLD_FALLING => ArcSequential::HOLD_FALLING,
770 Self::SETUP_RISING => ArcSequential::SETUP_RISING,
771 Self::SETUP_FALLING => ArcSequential::SETUP_FALLING,
772 Self::RECOVERY_RISING => ArcSequential::RECOVERY_RISING,
773 Self::RECOVERY_FALLING => ArcSequential::RECOVERY_FALLING,
774 Self::SKEW_RISING => ArcSequential::SKEW_RISING,
775 Self::SKEW_FALLING => ArcSequential::SKEW_FALLING,
776 Self::REMOVAL_RISING => ArcSequential::REMOVAL_RISING,
777 Self::REMOVAL_FALLING => ArcSequential::REMOVAL_FALLING,
778 Self::MIN_PULSE_WIDTH => ArcSequential::MIN_PULSE_WIDTH,
779 Self::MINIMUM_PERIOD => ArcSequential::MINIMUM_PERIOD,
780 Self::MAX_CLOCK_TREE_PATH => ArcSequential::MAX_CLOCK_TREE_PATH,
781 Self::MIN_CLOCK_TREE_PATH => ArcSequential::MIN_CLOCK_TREE_PATH,
782 Self::NON_SEQ_SETUP_RISING => ArcNonSequential::NON_SEQ_SETUP_RISING,
783 Self::NON_SEQ_SETUP_FALLING => ArcNonSequential::NON_SEQ_SETUP_FALLING,
784 Self::NON_SEQ_HOLD_RISING => ArcNonSequential::NON_SEQ_HOLD_RISING,
785 Self::NON_SEQ_HOLD_FALLING => ArcNonSequential::NON_SEQ_HOLD_FALLING,
786 Self::NOCHANGE_HIGH_HIGH => ArcNoChange::NOCHANGE_HIGH_HIGH,
787 Self::NOCHANGE_HIGH_LOW => ArcNoChange::NOCHANGE_HIGH_LOW,
788 Self::NOCHANGE_LOW_HIGH => ArcNoChange::NOCHANGE_LOW_HIGH,
789 Self::NOCHANGE_LOW_LOW => ArcNoChange::NOCHANGE_LOW_LOW,
790 })
791 }
792}
793
794impl TimingType {
795 /// `COMBINATIONAL`
796 pub const COMBINATIONAL: Self =
797 Self::Combinational(ArcCombinational::Combinational(None));
798 /// `COMBINATIONAL_RISE`
799 pub const COMBINATIONAL_RISE: Self =
800 Self::Combinational(ArcCombinational::Combinational(Some(logic::Edge::R)));
801 /// `COMBINATIONAL_FALL`
802 pub const COMBINATIONAL_FALL: Self =
803 Self::Combinational(ArcCombinational::Combinational(Some(logic::Edge::F)));
804 /// `THREE_STATE_DISABLE`
805 pub const THREE_STATE_DISABLE: Self =
806 Self::Combinational(ArcCombinational::ThreeStateDisable(None));
807 /// `THREE_STATE_DISABLE_RISE`
808 pub const THREE_STATE_DISABLE_RISE: Self =
809 Self::Combinational(ArcCombinational::ThreeStateDisable(Some(logic::Edge::R)));
810 /// `THREE_STATE_DISABLE_FALL`
811 pub const THREE_STATE_DISABLE_FALL: Self =
812 Self::Combinational(ArcCombinational::ThreeStateDisable(Some(logic::Edge::F)));
813 /// `THREE_STATE_ENABLE`
814 pub const THREE_STATE_ENABLE: Self =
815 Self::Combinational(ArcCombinational::ThreeStateEnable(None));
816 /// `THREE_STATE_ENABLE_RISE`
817 pub const THREE_STATE_ENABLE_RISE: Self =
818 Self::Combinational(ArcCombinational::ThreeStateEnable(Some(logic::Edge::R)));
819 /// `THREE_STATE_ENABLE_FALL`
820 pub const THREE_STATE_ENABLE_FALL: Self =
821 Self::Combinational(ArcCombinational::ThreeStateEnable(Some(logic::Edge::F)));
822 /// `RISING_EDGE`
823 pub const RISING_EDGE: Self = Self::Sequential(ArcSequential::Edge(logic::Edge::R));
824 /// `FALLING_EDGE`
825 pub const FALLING_EDGE: Self = Self::Sequential(ArcSequential::Edge(logic::Edge::F));
826 /// `PRESET`
827 pub const PRESET: Self = Self::Sequential(ArcSequential::Preset);
828 /// `CLEAR`
829 pub const CLEAR: Self = Self::Sequential(ArcSequential::Clear);
830 /// `HOLD_RISING`
831 pub const HOLD_RISING: Self = Self::Sequential(ArcSequential::Hold(logic::Edge::R));
832 /// `HOLD_FALLING`
833 pub const HOLD_FALLING: Self = Self::Sequential(ArcSequential::Hold(logic::Edge::F));
834 /// `SETUP_RISING`
835 pub const SETUP_RISING: Self = Self::Sequential(ArcSequential::Setup(logic::Edge::R));
836 /// `SETUP_FALLING`
837 pub const SETUP_FALLING: Self = Self::Sequential(ArcSequential::Setup(logic::Edge::F));
838 /// `RECOVERY_RISING`
839 pub const RECOVERY_RISING: Self =
840 Self::Sequential(ArcSequential::Recovery(logic::Edge::R));
841 /// `RECOVERY_FALLING`
842 pub const RECOVERY_FALLING: Self =
843 Self::Sequential(ArcSequential::Recovery(logic::Edge::F));
844 /// `SKEW_RISING`
845 pub const SKEW_RISING: Self = Self::Sequential(ArcSequential::Skew(logic::Edge::R));
846 /// `SKEW_FALLING`
847 pub const SKEW_FALLING: Self = Self::Sequential(ArcSequential::Skew(logic::Edge::F));
848 /// `REMOVAL_RISING`
849 pub const REMOVAL_RISING: Self =
850 Self::Sequential(ArcSequential::Removal(logic::Edge::R));
851 /// `REMOVAL_FALLING`
852 pub const REMOVAL_FALLING: Self =
853 Self::Sequential(ArcSequential::Removal(logic::Edge::F));
854 /// `MIN_PULSE_WIDTH`
855 pub const MIN_PULSE_WIDTH: Self = Self::Sequential(ArcSequential::MinPulseWidth);
856 /// `MINIMUM_PERIOD`
857 pub const MINIMUM_PERIOD: Self = Self::Sequential(ArcSequential::MinimumPeriod);
858 /// `MAX_CLOCK_TREE_PATH`
859 pub const MAX_CLOCK_TREE_PATH: Self =
860 Self::Sequential(ArcSequential::ClockTreePath(MaxMin::Max));
861 /// `MIN_CLOCK_TREE_PATH`
862 pub const MIN_CLOCK_TREE_PATH: Self =
863 Self::Sequential(ArcSequential::ClockTreePath(MaxMin::Min));
864 /// `NON_SEQ_SETUP_RISING`
865 pub const NON_SEQ_SETUP_RISING: Self =
866 Self::NonSequential(ArcNonSequential::NonSeqSetup(logic::Edge::R));
867 /// `NON_SEQ_SETUP_FALLING`
868 pub const NON_SEQ_SETUP_FALLING: Self =
869 Self::NonSequential(ArcNonSequential::NonSeqSetup(logic::Edge::F));
870 /// `NON_SEQ_HOLD_RISING`
871 pub const NON_SEQ_HOLD_RISING: Self =
872 Self::NonSequential(ArcNonSequential::NonSeqHold(logic::Edge::R));
873 /// `NON_SEQ_HOLD_FALLING`
874 pub const NON_SEQ_HOLD_FALLING: Self =
875 Self::NonSequential(ArcNonSequential::NonSeqHold(logic::Edge::F));
876 /// `NOCHANGE_HIGH_HIGH`
877 pub const NOCHANGE_HIGH_HIGH: Self =
878 Self::NoChange(ArcNoChange::NoChange(logic::Level::H, logic::Level::H));
879 /// `NOCHANGE_HIGH_LOW`
880 pub const NOCHANGE_HIGH_LOW: Self =
881 Self::NoChange(ArcNoChange::NoChange(logic::Level::H, logic::Level::L));
882 /// `NOCHANGE_LOW_HIGH`
883 pub const NOCHANGE_LOW_HIGH: Self =
884 Self::NoChange(ArcNoChange::NoChange(logic::Level::L, logic::Level::H));
885 /// `NOCHANGE_LOW_LOW`
886 pub const NOCHANGE_LOW_LOW: Self =
887 Self::NoChange(ArcNoChange::NoChange(logic::Level::L, logic::Level::L));
888 const LIST: [Self; 35] = [
889 Self::COMBINATIONAL,
890 Self::COMBINATIONAL_RISE,
891 Self::COMBINATIONAL_FALL,
892 Self::THREE_STATE_DISABLE,
893 Self::THREE_STATE_DISABLE_RISE,
894 Self::THREE_STATE_DISABLE_FALL,
895 Self::THREE_STATE_ENABLE,
896 Self::THREE_STATE_ENABLE_RISE,
897 Self::THREE_STATE_ENABLE_FALL,
898 Self::RISING_EDGE,
899 Self::FALLING_EDGE,
900 Self::PRESET,
901 Self::CLEAR,
902 Self::HOLD_RISING,
903 Self::HOLD_FALLING,
904 Self::SETUP_RISING,
905 Self::SETUP_FALLING,
906 Self::RECOVERY_RISING,
907 Self::RECOVERY_FALLING,
908 Self::SKEW_RISING,
909 Self::SKEW_FALLING,
910 Self::REMOVAL_RISING,
911 Self::REMOVAL_FALLING,
912 Self::MIN_PULSE_WIDTH,
913 Self::MINIMUM_PERIOD,
914 Self::MAX_CLOCK_TREE_PATH,
915 Self::MIN_CLOCK_TREE_PATH,
916 Self::NON_SEQ_SETUP_RISING,
917 Self::NON_SEQ_SETUP_FALLING,
918 Self::NON_SEQ_HOLD_RISING,
919 Self::NON_SEQ_HOLD_FALLING,
920 Self::NOCHANGE_HIGH_HIGH,
921 Self::NOCHANGE_HIGH_LOW,
922 Self::NOCHANGE_LOW_HIGH,
923 Self::NOCHANGE_LOW_LOW,
924 ];
925 /// `iter`
926 #[inline]
927 pub fn iter() -> impl Iterator<Item = Self> {
928 Self::LIST.iter().copied()
929 }
930}