liberty_db/library/
items.rs

1//! <script>
2//! IFRAME('https://zao111222333.github.io/liberty-db/2020.09/user_guide.html');
3//! </script>
4// use std::ops::DerefMut;
5
6use crate::{
7  Ctx,
8  ast::{
9    Attributes, BuilderScope, CodeFormatter, ComplexAttri, ComplexParseError,
10    DefinedType, GroupComments, GroupFn, Indentation, LibertySet, LibertyVec, ParseScope,
11  },
12  common::{items::IdVector, parse_f64},
13  expression::{Formula, logic},
14  table::VoltageName,
15};
16use core::fmt::{self, Write};
17
18/// The `sensitization` group defined at the library level describes.
19///
20/// the complete state patterns for a specific list of pins (defined by the `pin_names` attribute)
21/// that are referenced and instantiated as stimuli in the timing arc.
22///
23/// Vector attributes in the group define all possible pin states used as stimuli.
24/// Actual stimulus waveforms can be described by a combination of these vectors.
25/// Multiple sensitization groups are allowed in a library. Each `sensitization` group
26/// can be referenced by multiple cells, and each cell can make reference to
27/// multiple `sensitization`  groups.
28///
29/// <a name ="reference_link" href="
30/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=88.10&end=88.16
31/// ">Reference</a>
32#[derive(Debug, Clone)]
33#[derive(liberty_macros::Group)]
34#[mut_set::derive::item]
35#[derive(serde::Serialize, serde::Deserialize)]
36#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
37pub struct Sensitization<C: 'static + Ctx> {
38  /// name
39  #[id(borrow = str)]
40  #[liberty(name)]
41  pub name: String,
42  /// group comments
43  #[liberty(comments)]
44  comments: GroupComments,
45  #[liberty(extra_ctx)]
46  pub extra_ctx: C::Other,
47  /// group undefined attributes
48  #[liberty(attributes)]
49  pub attributes: Attributes,
50  /// The `pin_names` attribute specified at the library level defines
51  /// a default list of pin names. All vectors in this `sensitization` group
52  /// are the exhaustive list of all possible transitions of the input pins
53  /// and their subsequent output response.
54  ///
55  /// The `pin_names` attribute is required, and it must be declared in
56  /// the `sensitization` group before all vector declarations.
57  /// <a name ="reference_link" href="
58  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=88.28&end=88.32
59  /// ">Reference</a>
60  #[liberty(complex)]
61  pub pin_names: Vec<String>,
62  /// # vector Complex Attribute
63  ///
64  /// Similar to the `pin_names` attribute,
65  /// the `vector` attribute describes a transition pattern for the specified pins.
66  /// The stimulus is described by an ordered list of vectors.
67  ///
68  /// The arguments for the `vector` attribute are as follows:
69  ///
70  /// `vector id`
71  ///
72  /// The `vector id`  argument is an identifier to the vector string (a number tag
73  /// that defines the list of possible sensitization combinations in a cell).
74  /// The vector id value must be an integer greater than or equal to zero and
75  /// unique among all vectors in the current `sensitization` group. It is recommended
76  /// that you start numbering from 0 or 1.
77  ///
78  /// `vector string`
79  ///
80  /// The `vector string` argument represents a pin transition state. The string consists
81  /// of the following transition status values: 0, 1, X, and Z where each character is separated by a space.
82  /// The number of elements in the vector string must equal the number of arguments in `pin_names`.
83  ///
84  /// The `vector` attribute can also be declared as:
85  ///
86  /// `vector (positive_integer, "{0|1|X|Z} [0|1|X|Z]…");`
87  ///
88  /// ## Syntax
89  ///
90  /// `vector (integer, string);`
91  ///
92  /// ## Example
93  /// ``` text
94  /// sensitization(sensitization_nand2) {
95  ///   pin_names ( IN1, IN2, OUT1 );
96  ///   vector ( 1, "0 0 1" );
97  ///   vector ( 2, "0 1 1" );
98  ///   vector ( 3, "1 0 1" );
99  ///   vector ( 4, "1 1 0" );
100  /// }
101  /// ```
102  /// <a name ="reference_link" href="
103  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=89.5&end=89.29
104  /// ">Reference</a>
105  #[liberty(complex)]
106  pub vector: LibertyVec<SensitizationVector>,
107}
108
109/// # vector Complex Attribute
110///
111/// Similar to the `pin_names` attribute,
112/// the `vector` attribute describes a transition pattern for the specified pins.
113/// The stimulus is described by an ordered list of vectors.
114///
115/// The arguments for the `vector` attribute are as follows:
116///
117/// `vector id`
118///
119/// The `vector id`  argument is an identifier to the vector string (a number tag
120/// that defines the list of possible sensitization combinations in a cell).
121/// The vector id value must be an integer greater than or equal to zero and
122/// unique among all vectors in the current `sensitization` group. It is recommended
123/// that you start numbering from 0 or 1.
124///
125/// `vector string`
126///
127/// The `vector string` argument represents a pin transition state. The string consists
128/// of the following transition status values: 0, 1, X, and Z where each character is separated by a space.
129/// The number of elements in the vector string must equal the number of arguments in `pin_names`.
130///
131/// The `vector` attribute can also be declared as:
132///
133/// `vector (positive_integer, "{0|1|X|Z} [0|1|X|Z]…");`
134///
135/// ## Syntax
136///
137/// `vector (integer, string);`
138///
139/// ## Example
140/// ``` text
141/// sensitization(sensitization_nand2) {
142///   pin_names ( IN1, IN2, OUT1 );
143///   vector ( 1, "0 0 1" );
144///   vector ( 2, "0 1 1" );
145///   vector ( 3, "1 0 1" );
146///   vector ( 4, "1 1 0" );
147/// }
148/// ```
149/// <a name ="reference_link" href="
150/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=89.5&end=89.29
151/// ">Reference</a>
152#[derive(Debug, Clone, Default, PartialEq, Eq)]
153#[derive(serde::Serialize, serde::Deserialize)]
154pub struct SensitizationVector {
155  id: usize,
156  states: Vec<logic::Static>,
157}
158crate::ast::impl_self_builder!(SensitizationVector);
159impl<C: 'static + Ctx> ComplexAttri<C> for SensitizationVector {
160  #[inline]
161  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
162    mut iter: I,
163    _scope: &mut ParseScope<'_>,
164  ) -> Result<Self, ComplexParseError> {
165    let id: usize = match iter.next() {
166      Some(&s) => lexical_core::parse(s.as_bytes())?,
167      None => return Err(ComplexParseError::LengthDismatch),
168    };
169    let states = match iter.next() {
170      Some(&s) => match s
171        .split_ascii_whitespace()
172        .map(|t| match t {
173          "1" => Ok(logic::Static::H),
174          "0" => Ok(logic::Static::L),
175          "X" | "x" => Ok(logic::Static::X),
176          "Z" | "z" => Ok(logic::Static::Z),
177          _ => Err(ComplexParseError::UnsupportedWord),
178        })
179        .collect::<Result<Vec<logic::Static>, _>>()
180      {
181        Ok(states) => states,
182        Err(_) => return Err(ComplexParseError::UnsupportedWord),
183      },
184      None => return Err(ComplexParseError::LengthDismatch),
185    };
186    if iter.next().is_some() {
187      return Err(ComplexParseError::LengthDismatch);
188    }
189    Ok(Self { id, states })
190  }
191  #[inline]
192  fn fmt_self<T: Write, I: Indentation>(
193    &self,
194    f: &mut CodeFormatter<'_, T, I>,
195  ) -> fmt::Result {
196    f.write_num(self.id)?;
197    f.write_str(", ")?;
198    crate::ast::join_fmt(
199      self.states.iter(),
200      f,
201      |state, ff| {
202        write!(
203          ff,
204          "{}",
205          match state {
206            logic::Static::Z => "Z",
207            logic::Static::X => "X",
208            logic::Static::H => "1",
209            logic::Static::L => "0",
210          }
211        )
212      },
213      |ff| write!(ff, " "),
214    )
215  }
216}
217
218#[cfg(test)]
219mod test_sensitization {
220  use super::*;
221  use crate::DefaultCtx;
222
223  #[test]
224  fn sensitization() {
225    let sense = crate::ast::test_parse_fmt::<Sensitization<DefaultCtx>>(
226      r#"(sensitization_nand2) {
227        pin_names ( IN1, IN2, OUT1 );
228        vector ( 1, "0 0 1" );
229        vector ( 2, "0 X 1" );
230        vector ( 3, "Z 0 1" );
231        vector ( 4, "1 1 0" );
232      }"#,
233      r#"
234liberty_db::library::items::Sensitization (sensitization_nand2) {
235| pin_names (IN1, IN2, OUT1);
236| vector (1, "0 0 1");
237| vector (2, "0 X 1");
238| vector (3, "Z 0 1");
239| vector (4, "1 1 0");
240}"#,
241    );
242    assert_eq!(
243      sense.vector,
244      vec![
245        SensitizationVector {
246          id: 1,
247          states: vec![logic::Static::L, logic::Static::L, logic::Static::H,]
248        },
249        SensitizationVector {
250          id: 2,
251          states: vec![logic::Static::L, logic::Static::X, logic::Static::H,]
252        },
253        SensitizationVector {
254          id: 3,
255          states: vec![logic::Static::Z, logic::Static::L, logic::Static::H,]
256        },
257        SensitizationVector {
258          id: 4,
259          states: vec![logic::Static::H, logic::Static::H, logic::Static::L,]
260        }
261      ]
262    );
263    let sense1 = crate::ast::test_parse_fmt::<Sensitization<DefaultCtx>>(
264      r#"(sensitization_nand2) {
265        vector ( 1, "0 0 1" );
266        vector ( 2, "0 X 9" );
267        vector ( 3, "Z 0 1" );
268        vector ( 4, "1 1 0" );
269      }"#,
270      r#"
271liberty_db::library::items::Sensitization (sensitization_nand2) {
272| vector (1, "0 0 1");
273| vector (3, "Z 0 1");
274| vector (4, "1 1 0");
275| vector (2, "0 X 9"); /* user defined attribute */
276}"#,
277    );
278    assert!(sense1.attributes.len() == 1);
279  }
280}
281impl<C: 'static + Ctx> GroupFn<C> for Sensitization<C> {}
282
283/// Use the `voltage_map`  attribute to associate a voltage name
284/// with relative voltage values referenced by the cell-level `pg_pin`  groups.
285///
286/// <a name ="reference_link" href="
287/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=39.15&end=39.16
288/// ">Reference</a>
289#[mut_set::derive::item]
290#[derive(Debug, Clone, Default)]
291#[derive(serde::Serialize, serde::Deserialize)]
292pub struct VoltageMap {
293  /// name
294  #[id(borrow = str)]
295  pub name: String,
296  /// voltage
297  pub voltage: f64,
298}
299impl VoltageMap {
300  pub(super) fn add2scope<C: 'static + Ctx>(&mut self, scope: &mut BuilderScope<C>) {
301    _ = scope.voltage_map.insert(self.name.clone(), self.voltage);
302  }
303}
304crate::ast::impl_self_builder!(VoltageMap);
305impl<C: 'static + Ctx> ComplexAttri<C> for VoltageMap {
306  #[inline]
307  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
308    mut iter: I,
309    _scope: &mut ParseScope<'_>,
310  ) -> Result<Self, ComplexParseError> {
311    let name = match iter.next() {
312      Some(&s) => String::from(s),
313      None => return Err(ComplexParseError::LengthDismatch),
314    };
315    let voltage = match iter.next() {
316      Some(s) => parse_f64(s)?,
317      None => return Err(ComplexParseError::LengthDismatch),
318    };
319    if iter.next().is_some() {
320      return Err(ComplexParseError::LengthDismatch);
321    }
322    Ok(Self { name, voltage })
323  }
324  #[inline]
325  fn fmt_self<T: Write, I: Indentation>(
326    &self,
327    f: &mut CodeFormatter<'_, T, I>,
328  ) -> fmt::Result {
329    write!(f, "{}, ", self.name)?;
330    f.write_num(self.voltage)
331  }
332}
333
334#[mut_set::derive::item]
335#[derive(Debug, Clone, Default)]
336#[derive(serde::Serialize, serde::Deserialize)]
337pub struct VoltageMapping {
338  /// name
339  #[id]
340  pub name: VoltageName,
341  /// value
342  pub value: String,
343}
344crate::ast::impl_self_builder!(VoltageMapping);
345impl<C: 'static + Ctx> ComplexAttri<C> for VoltageMapping {
346  #[inline]
347  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
348    mut iter: I,
349    _scope: &mut ParseScope<'_>,
350  ) -> Result<Self, ComplexParseError> {
351    let name = match iter.next() {
352      Some(&s) => s.parse()?,
353      None => return Err(ComplexParseError::LengthDismatch),
354    };
355    let value = match iter.next() {
356      Some(&s) => String::from(s),
357      None => return Err(ComplexParseError::LengthDismatch),
358    };
359    if iter.next().is_some() {
360      return Err(ComplexParseError::LengthDismatch);
361    }
362    Ok(Self { name, value })
363  }
364  #[inline]
365  fn fmt_self<T: Write, I: Indentation>(
366    &self,
367    f: &mut CodeFormatter<'_, T, I>,
368  ) -> fmt::Result {
369    write!(f, "{}, {}", self.name, self.value)
370  }
371}
372
373/// An `input_voltage`  group is defined in the library  group to designate
374/// a set of input voltage ranges for your cells.
375///
376/// <a name ="reference_link" href="
377/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=61.32&end=61.33
378/// ">Reference</a>
379#[derive(Debug, Clone)]
380#[derive(liberty_macros::Group)]
381#[mut_set::derive::item]
382#[derive(serde::Serialize, serde::Deserialize)]
383#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
384pub struct InputVoltage<C: 'static + Ctx> {
385  /// name
386  #[id(borrow = str)]
387  #[liberty(name)]
388  pub name: String,
389  /// group comments
390  #[liberty(comments)]
391  comments: GroupComments,
392  #[liberty(extra_ctx)]
393  pub extra_ctx: C::Other,
394  /// group undefined attributes
395  #[liberty(attributes)]
396  pub attributes: Attributes,
397  /// The maximum input voltage for which the input to the core is guaranteed to be a logic 0
398  /// <a name ="reference_link" href="
399  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=62.7&end=62.8
400  /// ">Reference</a>
401  #[liberty(simple)]
402  pub vil: Formula,
403  /// The minimum input voltage for which the input to the core is guaranteed to be a logic 1
404  /// <a name ="reference_link" href="
405  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=62.10&end=62.11
406  /// ">Reference</a>
407  #[liberty(simple)]
408  pub vih: Formula,
409  /// The minimum acceptable input voltage.
410  /// <a name ="reference_link" href="
411  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=62.13&end=62.13
412  /// ">Reference</a>
413  #[liberty(simple)]
414  pub vimin: Formula,
415  /// The maximum acceptable input voltage.
416  /// <a name ="reference_link" href="
417  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=62.15&end=62.16
418  /// ">Reference</a>
419  #[liberty(simple)]
420  pub vimax: Formula,
421}
422impl<C: 'static + Ctx> GroupFn<C> for InputVoltage<C> {}
423
424/// You define an `output_voltage` group in the `library` group to designate a set of output
425/// voltage level ranges to drive output cells.
426///
427/// <a name ="reference_link" href="
428/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=75.22&end=75.23
429/// ">Reference</a>
430#[derive(Debug, Clone)]
431#[derive(liberty_macros::Group)]
432#[mut_set::derive::item]
433#[derive(serde::Serialize, serde::Deserialize)]
434#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
435pub struct OutputVoltage<C: 'static + Ctx> {
436  /// name
437  #[id(borrow = str)]
438  #[liberty(name)]
439  pub name: String,
440  /// group comments
441  #[liberty(comments)]
442  comments: GroupComments,
443  #[liberty(extra_ctx)]
444  pub extra_ctx: C::Other,
445  /// group undefined attributes
446  #[liberty(attributes)]
447  pub attributes: Attributes,
448  /// The maximum output voltage generated to represent a logic 0.
449  /// <a name ="reference_link" href="
450  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=75.45&end=75.46
451  /// ">Reference</a>
452  #[liberty(simple)]
453  pub vol: Formula,
454  /// The minimum output voltage generated to represent a logic 1.
455  /// <a name ="reference_link" href="
456  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=76.3&end=76.4
457  /// ">Reference</a>
458  #[liberty(simple)]
459  pub voh: Formula,
460  /// The minimum output voltage the pad can generate.
461  /// <a name ="reference_link" href="
462  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=76.5&end=76.6
463  /// ">Reference</a>
464  #[liberty(simple)]
465  pub vomin: Formula,
466  /// The maximum output voltage the pad can generate.
467  /// <a name ="reference_link" href="
468  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=76.7&end=76.8
469  /// ">Reference</a>
470  #[liberty(simple)]
471  pub vomax: Formula,
472}
473impl<C: 'static + Ctx> GroupFn<C> for OutputVoltage<C> {}
474
475/// Use the `delay_model`  attribute to specify which delay model
476/// to use in the delay calculations.
477///
478/// The `delay_model`  attribute must be the first attribute in the library
479/// if a technology attribute is not present.
480/// Otherwise, it should follow the technology attribute.
481/// <a name ="reference_link" href="
482/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=24.3&end=24.6
483/// ">Reference</a>
484#[derive(Debug, Clone, Copy)]
485#[derive(Hash, PartialEq, Eq, Default)]
486#[derive(Ord, PartialOrd)]
487#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
488#[derive(serde::Serialize, serde::Deserialize)]
489pub enum DelayModel {
490  /// `table_lookup`
491  #[default]
492  #[strum(serialize = "lookup_table", to_string = "table_lookup")]
493  TableLookup,
494  #[strum(serialize = "polynomial")]
495  Polynomial,
496}
497crate::ast::impl_self_builder!(DelayModel);
498crate::ast::impl_simple!(DelayModel);
499
500/// Use this group to define operating conditions;
501///
502/// that is, `process`, `voltage`, and `temperature`.
503/// You define an `operating_conditions`  group at the library-level, as shown here:
504/// <a name ="reference_link" href="
505/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=72.3&end=72.4
506/// ">Reference</a>
507#[derive(Debug, Clone)]
508#[derive(liberty_macros::Group)]
509#[mut_set::derive::item]
510#[derive(serde::Serialize, serde::Deserialize)]
511#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
512pub struct OperatingConditions<C: 'static + Ctx> {
513  /// name
514  #[id(borrow = str)]
515  #[liberty(name)]
516  pub name: String,
517  /// group comments
518  #[liberty(comments)]
519  comments: GroupComments,
520  #[liberty(extra_ctx)]
521  pub extra_ctx: C::Other,
522  /// group undefined attributes
523  #[liberty(attributes)]
524  pub attributes: Attributes,
525  /// An optional attribute, you can use `calc_mode`  to specify an associated process mode.
526  /// <a name ="reference_link" href="
527  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=72.28&end=72.28
528  /// ">Reference</a>
529  #[liberty(simple)]
530  pub calc_mode: Option<String>,
531  /// Use this optional attribute to specify values for up to five user-defined variables.
532  /// <a name ="reference_link" href="
533  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=72.36&end=72.37
534  /// ">Reference</a>
535  #[liberty(simple)]
536  pub parameteri: Option<f64>,
537  /// Use the `process`  attribute to specify a scaling factor to account for variations in the outcome of the actual semiconductor manufacturing steps.
538  ///
539  /// A floating-point number from 0 through 100.
540  /// <a name ="reference_link" href="
541  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=72.44+73.7&end=72.45+73.8
542  /// ">Reference</a>
543  #[liberty(simple)]
544  pub process: f64,
545  /// Use the `process_label`  attribute to specify the name of the current process.
546  /// <a name ="reference_link" href="
547  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=73.9&end=73.10
548  /// ">Reference</a>
549  #[liberty(simple)]
550  pub process_label: Option<String>,
551  /// Use the `temperature`  attribute to specify the ambient temperature in which the design is to operate.
552  /// <a name ="reference_link" href="
553  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=73.15&end=73.16
554  /// ">Reference</a>
555  #[liberty(simple)]
556  pub temperature: f64,
557  /// Use the `tree_type`  attribute to specify the environment interconnect model.
558  ///
559  /// Valid values are `best_case_tree`, `balanced_tree`, and `worst_case_tree`.
560  /// <a name ="reference_link" href="
561  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=73.24+73.30&end=73.25+73.31
562  /// ">Reference</a>
563  #[liberty(simple)]
564  pub tree_type: Option<TreeType>,
565  /// Use the `voltage`  attribute to specify the operating voltage of the design; typically 5 volts for a CMOS library.
566  ///
567  /// A floating-point number from 0 through 1000, representing the absolute value of the actual voltage
568  /// <a name ="reference_link" href="
569  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=73.32+74.3&end=73.33+74.4
570  /// ">Reference</a>
571  #[liberty(simple)]
572  #[liberty(default = 5.0)]
573  pub voltage: f64,
574}
575impl<C: 'static + Ctx> GroupFn<C> for OperatingConditions<C> {}
576
577/// You can define one or more `fpga_isd`  groups at the library level
578/// to specify the drive current, I/O voltages, and slew rates for FPGA parts and cells
579///
580/// When you specify more than one `fpga_isd`  group, you **must** also define
581/// the library-level `default_fpga_isd`  attribute to specify which `fpga_isd`
582/// group is the default
583/// <a name ="reference_link" href="
584/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=63.22+63.25&end=63.23+63.27
585/// ">Reference</a>
586#[derive(Debug, Clone)]
587#[derive(liberty_macros::Group)]
588#[mut_set::derive::item]
589#[derive(serde::Serialize, serde::Deserialize)]
590#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
591pub struct FpgaIsd<C: 'static + Ctx> {
592  /// name
593  #[liberty(name)]
594  #[id(borrow = str)]
595  pub name: String,
596  /// group comments
597  #[liberty(comments)]
598  comments: GroupComments,
599  #[liberty(extra_ctx)]
600  pub extra_ctx: C::Other,
601  /// group undefined attributes
602  #[liberty(attributes)]
603  pub attributes: Attributes,
604  /// The `drive`  attribute is optional and specifies the output current of the FPGA part or the FPGA cell.
605  /// <a name ="reference_link" href="
606  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=64.7&end=64.8
607  /// ">Reference</a>
608  #[liberty(simple)]
609  pub drive: String,
610  /// The `io_type`  attribute is required and specifies the input or output voltage of the FPGA part or the FPGA cell.
611  /// <a name ="reference_link" href="
612  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=64.17&end=64.18
613  /// ">Reference</a>
614  #[liberty(simple)]
615  pub io_type: String,
616  /// The `slew`  attribute is optional and specifies whether the slew of the FPGA part or the FPGA cell is FAST or SLOW.
617  /// <a name ="reference_link" href="
618  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=64.27&end=64.28
619  /// ">Reference</a>
620  #[liberty(simple)]
621  pub slew: Option<FPGASlew>,
622}
623impl<C: 'static + Ctx> GroupFn<C> for FpgaIsd<C> {}
624
625/// The `slew`  attribute is optional and specifies whether the slew of the FPGA part or the FPGA cell is FAST or SLOW.
626///
627/// <a name ="reference_link" href="
628/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=64.27&end=64.28
629/// ">Reference</a>
630#[derive(Debug, Clone, Copy)]
631#[derive(Hash, PartialEq, Eq)]
632#[derive(Ord, PartialOrd)]
633#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
634#[derive(serde::Serialize, serde::Deserialize)]
635pub enum FPGASlew {
636  /// `FAST`
637  #[strum(serialize = "FAST")]
638  FAST,
639  /// `SLOW`
640  #[strum(serialize = "SLOW")]
641  SLOW,
642}
643crate::ast::impl_self_builder!(FPGASlew);
644crate::ast::impl_simple!(FPGASlew);
645
646/// Use the `tree_type`  attribute to specify the environment interconnect model.
647///
648/// Valid values are `best_case_tree`, `balanced_tree`, and `worst_case_tree`.
649/// <a name ="reference_link" href="
650/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=73.24+73.30&end=73.25+73.31
651/// ">Reference</a>
652#[derive(Debug, Clone, Copy)]
653#[derive(Hash, PartialEq, Eq)]
654#[derive(Ord, PartialOrd)]
655#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
656#[derive(serde::Serialize, serde::Deserialize)]
657pub enum TreeType {
658  /// `best_case_tree`
659  #[strum(serialize = "best_case_tree")]
660  BestCaseTree,
661  /// `balanced_tree`
662  #[strum(serialize = "balanced_tree")]
663  BalancedTree,
664  /// `worst_case_tree`
665  #[strum(serialize = "worst_case_tree")]
666  WorstCaseTree,
667}
668crate::ast::impl_self_builder!(TreeType);
669crate::ast::impl_simple!(TreeType);
670
671/// The `technology`  attribute statement specifies the technology
672/// family being used in the library.
673/// When you define the technology  attribute,
674/// it must be the first attribute you use and it must be placed at the top of the listing.
675/// <a name ="reference_link" href="
676/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=39.3&end=39.5
677/// ">Reference</a>
678#[derive(Debug, Clone, Copy)]
679#[derive(Hash, PartialEq, Eq)]
680#[derive(Ord, PartialOrd)]
681#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
682#[derive(serde::Serialize, serde::Deserialize)]
683pub enum Technology {
684  /// `cmos`
685  #[strum(serialize = "cmos")]
686  CMOS,
687  /// `fpga`
688  #[strum(serialize = "fpga")]
689  FPGA,
690}
691crate::ast::impl_self_builder!(Technology);
692impl<C: 'static + Ctx> ComplexAttri<C> for Technology {
693  #[inline]
694  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
695    mut iter: I,
696    _scope: &mut ParseScope<'_>,
697  ) -> Result<Self, ComplexParseError> {
698    let v1: Self = match iter.next() {
699      Some(&s) => s.parse()?,
700      None => return Err(ComplexParseError::LengthDismatch),
701    };
702    if iter.next().is_some() {
703      return Err(ComplexParseError::LengthDismatch);
704    }
705    Ok(v1)
706  }
707  #[inline]
708  fn fmt_self<T: Write, I: Indentation>(
709    &self,
710    f: &mut CodeFormatter<'_, T, I>,
711  ) -> fmt::Result {
712    write!(f, "{self}")
713  }
714}
715
716/// Use this attribute to define new, temporary, or user-defined attributes
717/// for use in symbol and technology libraries.
718///
719/// You can use either a space or a comma to separate the arguments.
720/// The following example shows how to define a new string attribute called `bork`,
721/// which is valid in a `pin`  group:
722///
723/// ### Example
724/// ``` liberty
725/// define ("bork", "pin", "string") ;
726/// ```
727/// You give the new library attribute a value by using the simple attribute syntax:
728/// ``` liberty
729/// bork : "nimo" ;
730/// ```
731/// <a name ="reference_link" href="
732/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.5&end=36.21
733/// ">Reference</a>
734#[mut_set::derive::item]
735#[derive(Debug, Clone, Default)]
736#[derive(serde::Serialize, serde::Deserialize)]
737pub struct Define {
738  /// The name of the attribute you are creating.
739  /// <a name ="reference_link" href="
740  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.10&end=36.11
741  /// ">Reference</a>
742  #[id(borrow = str)]
743  pub attribute_name: String,
744  /// The name of the group statement in which the attribute is to be used.
745  /// <a name ="reference_link" href="
746  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.12&end=36.13
747  /// ">Reference</a>
748  #[id(borrow = str)]
749  pub group_name: String,
750  /// The type of the attribute that you are creating; valid values are Boolean, string, integer, or float
751  /// <a name ="reference_link" href="
752  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.14&end=36.15
753  /// ">Reference</a>
754  pub attribute_type: AttributeType,
755}
756/// The type of the attribute that you are creating; valid values are Boolean, string, integer, or float
757///
758/// <a name ="reference_link" href="
759/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.14&end=36.15
760/// ">Reference</a>
761#[derive(Debug, Clone, Copy, Default)]
762#[derive(Hash, PartialEq, Eq)]
763#[derive(Ord, PartialOrd)]
764#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
765#[derive(serde::Serialize, serde::Deserialize)]
766pub enum AttributeType {
767  /// Boolean
768  #[default]
769  #[strum(serialize = "Boolean", to_string = "boolean")]
770  Boolean,
771  /// string
772  #[strum(serialize = "string")]
773  String,
774  /// integer
775  #[strum(serialize = "integer")]
776  Integer,
777  /// float
778  #[strum(serialize = "float")]
779  Float,
780}
781crate::ast::impl_self_builder!(Define);
782impl<C: 'static + Ctx> ComplexAttri<C> for Define {
783  #[inline]
784  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
785    mut iter: I,
786    scope: &mut ParseScope<'_>,
787  ) -> Result<Self, ComplexParseError> {
788    let attribute_name = match iter.next() {
789      Some(&s) => String::from(s),
790      None => return Err(ComplexParseError::LengthDismatch),
791    };
792    let group_name = match iter.next() {
793      Some(&s) => String::from(s),
794      None => return Err(ComplexParseError::LengthDismatch),
795    };
796    let attribute_type = match iter.next() {
797      Some(&s) => s.parse()?,
798      None => return Err(ComplexParseError::LengthDismatch),
799    };
800    if iter.next().is_some() {
801      return Err(ComplexParseError::LengthDismatch);
802    }
803    _ = scope.define_map.insert(
804      (group_name.clone(), attribute_name.clone()),
805      DefinedType::Simple(attribute_type),
806    );
807    Ok(Self { attribute_name, group_name, attribute_type })
808  }
809  #[inline]
810  fn fmt_self<T: Write, I: Indentation>(
811    &self,
812    f: &mut CodeFormatter<'_, T, I>,
813  ) -> fmt::Result {
814    write!(f, "{}, {}, {}", self.attribute_name, self.group_name, self.attribute_type)
815  }
816}
817
818/// Use this special attribute to define new, temporary, or user-defined groups
819/// for use in technology libraries.
820///
821/// <a name ="reference_link" href="
822/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=37.24&end=37.25
823/// ">Reference</a>
824#[mut_set::derive::item]
825#[derive(Debug, Clone, Default)]
826#[derive(serde::Serialize, serde::Deserialize)]
827pub struct DefineGroup {
828  /// The name of the user-defined group.
829  /// <a name ="reference_link" href="
830  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=37.33&end=37.34
831  /// ">Reference</a>
832  #[id(borrow = str)]
833  pub group: String,
834  /// The name of the group statement in which the attribute is to be used.
835  /// <a name ="reference_link" href="
836  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=37.35&end=37.36
837  /// ">Reference</a>
838  #[id(borrow = str)]
839  pub parent_name: String,
840}
841crate::ast::impl_self_builder!(DefineGroup);
842impl<C: 'static + Ctx> ComplexAttri<C> for DefineGroup {
843  #[inline]
844  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
845    mut iter: I,
846    scope: &mut ParseScope<'_>,
847  ) -> Result<Self, ComplexParseError> {
848    let group = match iter.next() {
849      Some(&s) => String::from(s),
850      None => return Err(ComplexParseError::LengthDismatch),
851    };
852    let parent_name = match iter.next() {
853      Some(&s) => String::from(s),
854      None => return Err(ComplexParseError::LengthDismatch),
855    };
856    if iter.next().is_some() {
857      return Err(ComplexParseError::LengthDismatch);
858    }
859    _ = scope
860      .define_map
861      .insert((parent_name.clone(), group.clone()), DefinedType::Group);
862    Ok(Self { group, parent_name })
863  }
864  #[inline]
865  fn fmt_self<T: Write, I: Indentation>(
866    &self,
867    f: &mut CodeFormatter<'_, T, I>,
868  ) -> fmt::Result {
869    write!(f, "{}, {}", self.group, self.parent_name)
870  }
871}
872
873/// The `define_cell_area`  attribute defines the area resources a `cell` uses,
874/// such as the number of pad slots.
875///
876/// <a name ="reference_link" href="
877/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.23&end=36.24
878/// ">Reference</a>
879#[mut_set::derive::item]
880#[derive(Debug, Clone, Default)]
881#[derive(serde::Serialize, serde::Deserialize)]
882pub struct DefineCellArea {
883  /// A name of a resource type.
884  /// You can associate more than one `area_name` attribute with each of the predefined resource types.
885  /// <a name ="reference_link" href="
886  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.28&end=36.29
887  /// ">Reference</a>
888  #[id(borrow = str)]
889  pub area_name: String,
890  /// The resource type can be
891  /// + `pad_slots`
892  /// + `pad_input_driver_sites`
893  /// + `pad_output_driver_sites`
894  /// + `pad_driver_sites`
895  ///
896  /// Use the `pad_driver_sites` type when you do not need to discriminate between
897  /// input and output pad driver sites.
898  /// <a name ="reference_link" href="
899  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=37.3&end=37.11
900  /// ">Reference</a>
901  pub resource_type: ResourceType,
902}
903/// The resource type can be
904/// + `pad_slots`
905/// + `pad_input_driver_sites`
906/// + `pad_output_driver_sites`
907/// + `pad_driver_sites`
908///
909/// Use the `pad_driver_sites` type when you do not need to discriminate between
910/// input and output pad driver sites.
911/// <a name ="reference_link" href="
912/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=37.3&end=37.11
913/// ">Reference</a>
914#[derive(Debug, Clone, Copy, Default)]
915#[derive(Hash, PartialEq, Eq)]
916#[derive(Ord, PartialOrd)]
917#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
918#[derive(serde::Serialize, serde::Deserialize)]
919pub enum ResourceType {
920  /// `pad_slots`
921  #[default]
922  #[strum(serialize = "pad_slots")]
923  PadSlots,
924  /// `pad_input_driver_sites`
925  #[strum(serialize = "pad_input_driver_sites")]
926  PadInputDriverSites,
927  /// `pad_output_driver_sites`
928  #[strum(serialize = "pad_output_driver_sites")]
929  PadOutputDriverSites,
930  /// `pad_driver_sites`
931  #[strum(serialize = "pad_driver_sites")]
932  PadDriverSites,
933}
934crate::ast::impl_self_builder!(DefineCellArea);
935impl<C: 'static + Ctx> ComplexAttri<C> for DefineCellArea {
936  #[inline]
937  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
938    mut iter: I,
939    _scope: &mut ParseScope<'_>,
940  ) -> Result<Self, ComplexParseError> {
941    let area_name = match iter.next() {
942      Some(&s) => String::from(s),
943      None => return Err(ComplexParseError::LengthDismatch),
944    };
945    let resource_type = match iter.next() {
946      Some(&s) => match s.parse() {
947        Ok(f) => f,
948        Err(_) => return Err(ComplexParseError::UnsupportedWord),
949      },
950      None => return Err(ComplexParseError::LengthDismatch),
951    };
952    if iter.next().is_some() {
953      return Err(ComplexParseError::LengthDismatch);
954    }
955    Ok(Self { area_name, resource_type })
956  }
957  #[inline]
958  fn fmt_self<T: Write, I: Indentation>(
959    &self,
960    f: &mut CodeFormatter<'_, T, I>,
961  ) -> fmt::Result {
962    write!(f, "{}, {}", self.area_name, self.resource_type)
963  }
964}
965
966/// A `wire_load`  group is defined in a `library`  group, as follows.
967///
968/// <a name ="reference_link" href="
969/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=94.16&end=94.17
970/// ">Reference</a>
971#[derive(Debug, Clone)]
972#[derive(liberty_macros::Group)]
973#[mut_set::derive::item]
974#[derive(serde::Serialize, serde::Deserialize)]
975pub struct WireLoad<C: 'static + Ctx> {
976  /// name
977  #[id(borrow = str)]
978  #[liberty(name)]
979  pub name: String,
980  /// group comments
981  #[liberty(comments)]
982  comments: GroupComments,
983  #[liberty(extra_ctx)]
984  pub extra_ctx: C::Other,
985  /// group undefined attributes
986  #[liberty(attributes)]
987  pub attributes: Attributes,
988  /// Use this attribute to specify area per unit length of interconnect wire.
989  /// <a name ="reference_link" href="
990  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=94.31&end=94.32
991  /// ">Reference</a>
992  #[liberty(simple)]
993  pub area: f64,
994  /// Use this attribute to specify capacitance per unit length of interconnect wire.
995  /// <a name ="reference_link" href="
996  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=95.5&end=95.6
997  /// ">Reference</a>
998  #[liberty(simple)]
999  pub capacitance: f64,
1000  /// Use this attribute to specify wire resistance per unit length of interconnect wire.
1001  /// <a name ="reference_link" href="
1002  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=95.15&end=95.16
1003  /// ">Reference</a>
1004  #[liberty(simple)]
1005  pub resistance: f64,
1006  /// Use this attribute to characterize linear fanout length behavior
1007  /// beyond the scope of the longest length specified
1008  /// in the `fanout_length`  attribute.
1009  /// <a name ="reference_link" href="
1010  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=95.25&end=95.26
1011  /// ">Reference</a>
1012  #[liberty(simple)]
1013  pub slope: f64,
1014  /// Use this attribute to define values for fanout and length
1015  /// when you create the wire load manually.
1016  /// fanoutAn integer representing the total number of pins, minus one, on the net driven by the given output.lengthA floating-point number representing the estimated amount of metal that is statistically found on a network with the given number of pins.
1017  ///
1018  /// Examples
1019  /// ``` liberty
1020  /// library (example)  
1021  ///   ...
1022  ///   wire_load (small) {  
1023  ///     area : 0.0 ;  
1024  ///     capacitance : 1.0 ;  
1025  ///     resistance : 0.0 ;  
1026  ///     slope : 0.0 ;  
1027  ///     fanout_length (1,1.68) ;
1028  ///   }
1029  /// }
1030  /// ```
1031  /// <a name ="reference_link" href="
1032  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=96.3&end=96.34
1033  /// ">Reference</a>
1034  #[liberty(complex)]
1035  pub fanout_length: LibertySet<FanoutLength>,
1036}
1037impl<C: 'static + Ctx> GroupFn<C> for WireLoad<C> {}
1038
1039/// Use this attribute to define values for fanout and length
1040/// when you create the wire load manually.
1041///
1042/// fanout: An integer representing the total number of pins, minus one, on the net driven by the given output.lengthA floating-point number representing the estimated amount of metal that is statistically found on a network with the given number of pins.
1043///
1044/// Examples
1045/// ``` liberty
1046/// library (example)  
1047///   ...
1048///   wire_load (small) {  
1049///     area : 0.0 ;  
1050///     capacitance : 1.0 ;  
1051///     resistance : 0.0 ;  
1052///     slope : 0.0 ;  
1053///     fanout_length (1,1.68) ;
1054///   }
1055/// }
1056/// ```
1057/// <a name ="reference_link" href="
1058/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=96.3&end=96.34
1059/// ">Reference</a>
1060#[derive(Debug, Clone, Default, Copy)]
1061#[mut_set::derive::item]
1062#[derive(serde::Serialize, serde::Deserialize)]
1063pub struct FanoutLength {
1064  /// An integer representing the total number of pins, minus one, on the net driven by the given output
1065  /// <a name ="reference_link" href="
1066  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=96.19&end=96.20
1067  /// ">Reference</a>
1068  #[id]
1069  pub fanout: u32,
1070  /// A floating-point number representing the estimated amount of metal
1071  /// that is statistically found on a network with the given number of pins
1072  /// <a name ="reference_link" href="
1073  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=96.22&end=96.23
1074  /// ">Reference</a>
1075  pub length: f64,
1076  /// `average_capacitance`
1077  pub average_capacitance: Option<f64>,
1078  /// `standard_deviation`
1079  pub standard_deviation: Option<f64>,
1080  /// `number_of_nets`
1081  pub number_of_nets: Option<u32>,
1082}
1083crate::ast::impl_self_builder!(FanoutLength);
1084impl<C: 'static + Ctx> ComplexAttri<C> for FanoutLength {
1085  #[inline]
1086  fn parse<'a, I: Iterator<Item = &'a &'a str>>(
1087    mut iter: I,
1088    _scope: &mut ParseScope<'_>,
1089  ) -> Result<Self, ComplexParseError> {
1090    let fanout = match iter.next() {
1091      Some(&s) => lexical_core::parse(s.as_bytes())?,
1092      None => return Err(ComplexParseError::LengthDismatch),
1093    };
1094    let length = match iter.next() {
1095      Some(s) => parse_f64(s)?,
1096      None => return Err(ComplexParseError::LengthDismatch),
1097    };
1098    let average_capacitance =
1099      if let Some(s) = iter.next() { Some(parse_f64(s)?) } else { None };
1100    let standard_deviation =
1101      if let Some(s) = iter.next() { Some(parse_f64(s)?) } else { None };
1102    let number_of_nets = if let Some(s) = iter.next() {
1103      Some(lexical_core::parse(s.as_bytes())?)
1104    } else {
1105      None
1106    };
1107
1108    if iter.next().is_some() {
1109      return Err(ComplexParseError::LengthDismatch);
1110    }
1111    Ok(Self {
1112      fanout,
1113      length,
1114      average_capacitance,
1115      standard_deviation,
1116      number_of_nets,
1117    })
1118  }
1119  #[inline]
1120  fn fmt_self<T: Write, I: Indentation>(
1121    &self,
1122    f: &mut CodeFormatter<'_, T, I>,
1123  ) -> fmt::Result {
1124    f.write_num(self.fanout)?;
1125    f.write_str(", ")?;
1126    f.write_num(self.length)?;
1127    if let (Some(average_capacitance), Some(standard_deviation), Some(number_of_nets)) =
1128      (self.average_capacitance, self.standard_deviation, self.number_of_nets)
1129    {
1130      f.write_str(", ")?;
1131      f.write_num(average_capacitance)?;
1132      f.write_str(", ")?;
1133      f.write_num(standard_deviation)?;
1134      f.write_str(", ")?;
1135      f.write_num(number_of_nets)?;
1136    }
1137    Ok(())
1138  }
1139}
1140
1141/// A `wire_load_selection`  group is defined in a `library`  group, as follows.
1142///
1143/// <a name ="reference_link" href="
1144/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=94.16&end=94.17
1145/// ">Reference</a>
1146#[derive(Debug, Clone)]
1147#[derive(liberty_macros::Group)]
1148#[mut_set::derive::item]
1149#[derive(serde::Serialize, serde::Deserialize)]
1150pub struct WireLoadSection<C: 'static + Ctx> {
1151  /// name
1152  #[id(borrow = str)]
1153  #[liberty(name)]
1154  pub name: String,
1155  /// group comments
1156  #[liberty(comments)]
1157  comments: GroupComments,
1158  #[liberty(extra_ctx)]
1159  pub extra_ctx: C::Other,
1160  /// group undefined attributes
1161  #[liberty(attributes)]
1162  pub attributes: Attributes,
1163  /// Use this attribute to specify area per unit length of interconnect wire.
1164  /// <a name ="reference_link" href="
1165  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=94.31&end=94.32
1166  /// ">Reference</a>
1167  #[liberty(complex)]
1168  pub wire_load_from_area: (f64, f64, String),
1169}
1170impl<C: 'static + Ctx> GroupFn<C> for WireLoadSection<C> {}
1171
1172/// The `base_curve_type` attribute specifies the type of base curve.
1173///
1174/// The valid values for `base_curve_type`  are `ccs_timing_half_curve`  and `ccs_half_curve`.
1175/// The `ccs_half_curve`  value allows you to model compact CCS power
1176/// and compact CCS timing data within the same `base_curves`  group.
1177/// You must specify `ccs_half_curve` before specifying `ccs_timing_half_curve`.
1178///
1179/// **Syntax**
1180/// ``` text
1181/// base_curve_type: enum (ccs_half_curve, ccs_timing_half_curve);
1182/// ```
1183/// **Example**
1184/// ``` text
1185/// base_curve_type : ccs_timing_half_curve ;
1186/// ```
1187/// <a name ="reference_link" href="
1188/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=40.21+40.26&end=40.25+40.29
1189/// ">Reference</a>
1190#[derive(Debug, Clone, Copy)]
1191#[derive(Hash, PartialEq, Eq)]
1192#[derive(Ord, PartialOrd, Default)]
1193#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
1194#[derive(serde::Serialize, serde::Deserialize)]
1195pub enum BaseCurveType {
1196  /// The `ccs_half_curve`  value allows you to model compact CCS power
1197  #[strum(serialize = "ccs_half_curve")]
1198  #[default]
1199  CcsHalfCurve,
1200  /// You must specify `ccs_half_curve` before specifying `ccs_timing_half_curve`.
1201  #[strum(serialize = "ccs_timing_half_curve")]
1202  CcsTimingHalfCurve,
1203}
1204crate::ast::impl_self_builder!(BaseCurveType);
1205crate::ast::impl_simple!(BaseCurveType);
1206
1207/// The `base_curves`  group is a library-level group that contains
1208/// the detailed description of normalized base curves.
1209///
1210/// **Syntax**
1211/// ``` text
1212/// library (my_compact_ccs_lib) {
1213///   …
1214///   base_curves (base_curves_name) {
1215///     …
1216///   }
1217/// }
1218/// ```
1219/// **Example**
1220/// ``` text
1221/// library(my_lib) {
1222///   …
1223///   base_curves (ctbct1) {
1224///     …
1225///   }
1226/// }
1227/// ```
1228/// <a name ="reference_link" href="
1229/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=39.32+40.2&end=39.33+40.15
1230/// ">Reference</a>
1231#[derive(Debug, Clone)]
1232#[derive(liberty_macros::Group)]
1233#[mut_set::derive::item]
1234#[derive(serde::Serialize, serde::Deserialize)]
1235pub struct BaseCurves<C: 'static + Ctx> {
1236  /// name
1237  #[liberty(name)]
1238  #[id(borrow = str)]
1239  pub name: String,
1240  /// group comments
1241  #[liberty(comments)]
1242  comments: GroupComments,
1243  #[liberty(extra_ctx)]
1244  pub extra_ctx: C::Other,
1245  /// group undefined attributes
1246  #[liberty(attributes)]
1247  pub attributes: Attributes,
1248  /// The `base_curve_type` attribute specifies the type of base curve.
1249  /// The valid values for `base_curve_type`  are `ccs_timing_half_curve`  and `ccs_half_curve`.
1250  /// The `ccs_half_curve`  value allows you to model compact CCS power
1251  /// and compact CCS timing data within the same `base_curves`  group.
1252  /// You must specify `ccs_half_curve` before specifying `ccs_timing_half_curve`.
1253  ///
1254  /// **Syntax**
1255  /// ``` text
1256  /// base_curve_type: enum (ccs_half_curve, ccs_timing_half_curve);
1257  /// ```
1258  /// **Example**
1259  /// ``` text
1260  /// base_curve_type : ccs_timing_half_curve ;
1261  /// ```
1262  /// <a name ="reference_link" href="
1263  /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=40.21+40.26&end=40.25+40.29
1264  /// ">Reference</a>
1265  #[liberty(simple)]
1266  pub base_curve_type: BaseCurveType,
1267  #[liberty(complex)]
1268  pub curve_x: Vec<f64>,
1269  #[liberty(complex)]
1270  pub curve_y: LibertySet<IdVector>,
1271}
1272
1273impl<C: 'static + Ctx> GroupFn<C> for BaseCurves<C> {}
1274
1275/// The `power_supply` group captures all nominal information about voltage variation.
1276/// It is defined before the `operating_conditions` group and before the `cell` groups.
1277/// All the power supply names defined in the `power_supply` group exist in the
1278/// `operating_conditions` group. Define the `power_supply` group at the library level.
1279///
1280/// Syntax
1281/// ```text
1282/// power_supply () {
1283///   default_power_rail : string ;
1284///   power_rail (string, float) ;
1285///   power_rail (string, float) ;
1286///   ...
1287/// }
1288/// ```
1289/// Example
1290/// ```text
1291/// power_supply () {
1292///   default_power_rail : VDD0;
1293///   power_rail (VDD1, 5.0) ;
1294///   power_rail (VDD2, 3.3) ;
1295/// }
1296/// ```
1297/// <a name ="reference_link" href="
1298/// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=51.33+52.2&end=51.34+52.16
1299/// ">Reference</a>
1300/// <script>
1301/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/user_guide.html');
1302/// </script>
1303#[derive(Debug, Clone)]
1304#[derive(liberty_macros::Group)]
1305#[derive(serde::Serialize, serde::Deserialize)]
1306#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
1307pub struct PowerSupply<C: 'static + Ctx> {
1308  /// group comments
1309  #[liberty(comments)]
1310  comments: GroupComments,
1311  #[liberty(extra_ctx)]
1312  pub extra_ctx: C::Other,
1313  /// group undefined attributes
1314  #[liberty(attributes)]
1315  pub attributes: Attributes,
1316  #[liberty(simple)]
1317  pub default_power_rail: Option<String>,
1318  #[liberty(complex)]
1319  pub power_rail: LibertySet<VoltageMap>,
1320}
1321impl<C: 'static + Ctx> GroupFn<C> for PowerSupply<C> {}
1322
1323#[cfg(test)]
1324mod test {
1325  use crate::DefaultCtx;
1326
1327  #[test]
1328  fn input_voltage() {
1329    let g = crate::ast::test_parse_fmt::<super::InputVoltage<DefaultCtx>>(
1330      r#"(cmos_schmitt) {
1331        vil : 0.3 * VDD ;
1332        vih : 0.7 * VDD ;
1333        vimin : -0.5 ;
1334        vimax : VDD + 0.5 ;
1335      }"#,
1336      r#"
1337liberty_db::library::items::InputVoltage (cmos_schmitt) {
1338| vil : 0.3 * VDD;
1339| vih : 0.7 * VDD;
1340| vimin : -0.5;
1341| vimax : VDD + 0.5;
1342}"#,
1343    );
1344  }
1345  #[test]
1346  fn base_curves() {
1347    let g = crate::ast::test_parse_fmt::<super::BaseCurves<DefaultCtx>>(
1348      r#"("nc_compact_ccs_curve_1") {
1349      base_curve_type : "ccs_timing_half_curve";
1350      curve_x("0.1000000, 0.2000000, 0.3000000, 0.4000000, 0.5000000, 0.6000000, 0.7000000, 0.8000000, 0.9000000");
1351      curve_y(1, \
1352        "0.9965371, 0.9930742, 0.9584770, 0.9165637, 0.8271961, 0.7425452, 0.6009643, 0.4459254, 0.2653107");
1353      curve_y(2, \
1354        "0.9887274, 0.9695129, 0.9443244, 0.9183546, 0.8705093, 0.8062681, 0.6984753, 0.5213233, 0.2657268");
1355      curve_y(3, \
1356        "0.9895478, 0.9774914, 0.9389569, 0.8934003, 0.8125975, 0.7144581, 0.5786802, 0.4298566, 0.2542494");
1357      curve_y(4, \
1358        "0.9944934, 0.9784088, 0.9620733, 0.9304195, 0.8888662, 0.8329558, 0.7240709, 0.5580780, 0.3037784");
1359      curve_y(5, \
1360        "0.9922672, 0.9664605, 0.9307680, 0.8888898, 0.8146837, 0.7076250, 0.5811826, 0.4366006, 0.2619239");   
1361    }"#,
1362      r#"
1363liberty_db::library::items::BaseCurves (nc_compact_ccs_curve_1) {
1364| base_curve_type : ccs_timing_half_curve;
1365| curve_x ("0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9");
1366| curve_y (1, \
1367| | "0.9965371, 0.9930742, 0.958477, 0.9165637, 0.8271961, 0.7425452, 0.6009643, 0.4459254, 0.2653107");
1368| curve_y (2, \
1369| | "0.9887274, 0.9695129, 0.9443244, 0.9183546, 0.8705093, 0.8062681, 0.6984753, 0.5213233, 0.2657268");
1370| curve_y (3, \
1371| | "0.9895478, 0.9774914, 0.9389569, 0.8934003, 0.8125975, 0.7144581, 0.5786802, 0.4298566, 0.2542494");
1372| curve_y (4, \
1373| | "0.9944934, 0.9784088, 0.9620733, 0.9304195, 0.8888662, 0.8329558, 0.7240709, 0.558078, 0.3037784");
1374| curve_y (5, \
1375| | "0.9922672, 0.9664605, 0.930768, 0.8888898, 0.8146837, 0.707625, 0.5811826, 0.4366006, 0.2619239");
1376}"#,
1377    );
1378  }
1379}