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}