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}