1use crate::{
2 Ctx,
3 ast::{
4 Attributes, CodeFormatter, ComplexAttri, ComplexParseError, GroupComments, GroupFn,
5 Indentation, ParseScope, SimpleAttri,
6 },
7 expression::logic::{Edge, Static},
8};
9use core::{
10 fmt::{self, Write},
11 str::FromStr,
12};
13use strum::{Display, EnumString};
14
15#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
24#[derive(serde::Serialize, serde::Deserialize)]
25pub enum AntennaDiodeType {
26 #[strum(serialize = "power")]
28 Power,
29 #[strum(serialize = "ground")]
31 Ground,
32 #[strum(serialize = "power_and_ground")]
34 PowerAndGround,
35}
36crate::ast::impl_self_builder!(AntennaDiodeType);
37crate::ast::impl_simple!(AntennaDiodeType);
38
39#[derive(Debug, Clone)]
51#[derive(liberty_macros::Group)]
52#[mut_set::derive::item]
53#[derive(serde::Serialize, serde::Deserialize)]
54#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
55pub struct TLatch<C: 'static + Ctx> {
56 #[liberty(name)]
58 #[id(borrow = str)]
59 pub name: String,
60 #[liberty(comments)]
62 comments: GroupComments,
63 #[liberty(extra_ctx)]
64 pub extra_ctx: C::Other,
65 #[liberty(attributes)]
67 pub attributes: Attributes,
68 #[liberty(simple)]
70 pub edge_type: Option<Edge>,
71 #[liberty(simple)]
72 pub tdisable: Option<bool>,
73}
74impl<C: 'static + Ctx> GroupFn<C> for TLatch<C> {}
75
76#[derive(Debug, Clone)]
124#[derive(liberty_macros::Group)]
125#[mut_set::derive::item]
126#[derive(serde::Serialize, serde::Deserialize)]
127#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
128pub struct HyperbolicNoise<C: 'static + Ctx> {
129 #[liberty(name)]
131 #[id]
132 pub name: Option<String>,
133 #[liberty(comments)]
135 comments: GroupComments,
136 #[liberty(extra_ctx)]
137 pub extra_ctx: C::Other,
138 #[liberty(attributes)]
140 pub attributes: Attributes,
141 #[liberty(simple)]
142 pub height_coefficient: f64,
143 #[liberty(simple)]
144 pub area_coefficient: f64,
145 #[liberty(simple)]
146 pub width_coefficient: f64,
147}
148impl<C: 'static + Ctx> GroupFn<C> for HyperbolicNoise<C> {}
149
150#[derive(Debug, Clone)]
171#[derive(liberty_macros::Group)]
172#[derive(serde::Serialize, serde::Deserialize)]
173#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
174pub struct MemoryWrite<C: 'static + Ctx> {
175 #[liberty(name)]
177 pub name: Option<String>,
178 #[liberty(comments)]
180 comments: GroupComments,
181 #[liberty(extra_ctx)]
182 pub extra_ctx: C::Other,
183 #[liberty(attributes)]
185 pub attributes: Attributes,
186 #[liberty(simple)]
187 pub address: Option<String>,
188 #[liberty(simple)]
189 pub clocked_on: Option<String>,
190 #[liberty(simple)]
191 pub enable: Option<String>,
192}
193impl<C: 'static + Ctx> GroupFn<C> for MemoryWrite<C> {}
194
195#[derive(Debug, Clone)]
214#[derive(liberty_macros::Group)]
215#[derive(serde::Serialize, serde::Deserialize)]
216#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
217pub struct MemoryRead<C: 'static + Ctx> {
218 #[liberty(name)]
220 pub name: Option<String>,
221 #[liberty(comments)]
223 comments: GroupComments,
224 #[liberty(extra_ctx)]
225 pub extra_ctx: C::Other,
226 #[liberty(attributes)]
228 pub attributes: Attributes,
229 #[liberty(simple)]
230 pub address: Option<String>,
231}
232
233impl<C: 'static + Ctx> GroupFn<C> for MemoryRead<C> {}
234
235#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
244#[derive(serde::Serialize, serde::Deserialize)]
245pub enum Direction {
246 #[strum(serialize = "input")]
247 Input,
248 #[strum(serialize = "output")]
249 Output,
250 #[strum(serialize = "inoutput", to_string = "inout")]
251 Inout,
252 #[strum(serialize = "internal")]
253 Internal,
254}
255crate::ast::impl_self_builder!(Direction);
256crate::ast::impl_simple!(Direction);
257
258#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
259#[derive(serde::Serialize, serde::Deserialize)]
260pub enum DontFault {
261 #[strum(serialize = "sa0")]
262 Sa0,
263 #[strum(serialize = "sa1")]
264 Sa1,
265 #[strum(serialize = "sao1")]
266 Sao1,
267}
268crate::ast::impl_self_builder!(DontFault);
269crate::ast::impl_simple!(DontFault);
270
271#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
272#[derive(serde::Serialize, serde::Deserialize)]
273pub enum DriverType {
274 #[strum(serialize = "pull_up")]
275 PullUp,
276 #[strum(serialize = "pull_down")]
277 PullDown,
278 #[strum(serialize = "open_drain")]
279 OpenDrain,
280 #[strum(serialize = "open_source")]
281 OpenSource,
282 #[strum(serialize = "bus_hold")]
283 BusHold,
284 #[strum(serialize = "resistive")]
285 Resistive,
286 #[strum(serialize = "resistive_0")]
287 Resistive0,
288 #[strum(serialize = "resistive_1")]
289 Resistive1,
290}
291
292bitflags::bitflags! {
293 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
295 #[derive(serde::Serialize, serde::Deserialize)]
296 #[serde(transparent)]
297 pub struct AllDriverType: u8 {
298 const pull_up = 0b0000_0001;
299 const pull_down = 0b0000_0010;
300 const open_drain = 0b0000_0100;
301 const open_source = 0b0000_1000;
302 const bus_hold = 0b0000_1000;
303 const resistive = 0b0001_0000;
304 const resistive_0 = 0b0100_0000;
305 const resistive_1 = 0b1000_0000;
306 }
307}
308
309crate::ast::impl_self_builder!(AllDriverType);
310impl<C: 'static + Ctx> SimpleAttri<C> for AllDriverType {
311 #[inline]
312 fn nom_parse<'a>(
313 i: &'a str,
314 scope: &mut ParseScope<'_>,
315 ) -> crate::ast::SimpleParseRes<'a, Self> {
316 crate::ast::nom_parse_from_str::<C, _>(i, scope)
317 }
318 #[inline]
319 fn fmt_self<T: Write, I: Indentation>(
320 &self,
321 f: &mut CodeFormatter<'_, T, I>,
322 ) -> fmt::Result {
323 if self.bits().is_power_of_two() {
324 write!(f, "{self}")
325 } else {
326 write!(f, "\"{self}\"")
327 }
328 }
329}
330impl FromStr for AllDriverType {
331 type Err = <DriverType as FromStr>::Err;
332 #[inline]
333 fn from_str(s: &str) -> Result<Self, Self::Err> {
334 let mut out = Self::empty();
335 for t in s.split_ascii_whitespace() {
336 match t.parse()? {
337 DriverType::PullUp => out.insert(Self::pull_up),
338 DriverType::PullDown => out.insert(Self::pull_down),
339 DriverType::OpenDrain => out.insert(Self::open_drain),
340 DriverType::OpenSource => out.insert(Self::open_source),
341 DriverType::BusHold => out.insert(Self::bus_hold),
342 DriverType::Resistive => out.insert(Self::resistive),
343 DriverType::Resistive0 => out.insert(Self::resistive_0),
344 DriverType::Resistive1 => out.insert(Self::resistive_1),
345 }
346 }
347 Ok(out)
348 }
349}
350impl fmt::Display for AllDriverType {
351 #[inline]
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 let mut has_write = false;
354 if self.contains(Self::pull_up) {
355 has_write = true;
356 write!(f, "{}", DriverType::PullUp)?;
357 }
358 if self.contains(Self::pull_down) {
359 if has_write {
360 write!(f, " ")?;
361 } else {
362 has_write = true;
363 }
364 write!(f, "{}", DriverType::PullDown)?;
365 }
366 if self.contains(Self::open_drain) {
367 if has_write {
368 write!(f, " ")?;
369 } else {
370 has_write = true;
371 }
372 write!(f, "{}", DriverType::OpenDrain)?;
373 }
374 if self.contains(Self::open_source) {
375 if has_write {
376 write!(f, " ")?;
377 } else {
378 has_write = true;
379 }
380 write!(f, "{}", DriverType::OpenSource)?;
381 }
382 if self.contains(Self::bus_hold) {
383 if has_write {
384 write!(f, " ")?;
385 } else {
386 has_write = true;
387 }
388 write!(f, "{}", DriverType::BusHold)?;
389 }
390 if self.contains(Self::resistive) {
391 if has_write {
392 write!(f, " ")?;
393 } else {
394 has_write = true;
395 }
396 write!(f, "{}", DriverType::Resistive)?;
397 }
398 if self.contains(Self::resistive_0) {
399 if has_write {
400 write!(f, " ")?;
401 } else {
402 has_write = true;
403 }
404 write!(f, "{}", DriverType::Resistive0)?;
405 }
406 if self.contains(Self::resistive_1) {
407 if has_write {
408 write!(f, " ")?;
409 }
410 write!(f, "{}", DriverType::Resistive1)?;
411 }
412 Ok(())
413 }
414}
415
416#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, Display, EnumString)]
417#[derive(serde::Serialize, serde::Deserialize)]
418pub enum NextstateType {
419 #[default]
421 #[strum(serialize = "data")]
422 Data,
423 #[strum(serialize = "preset")]
425 Preset,
426 #[strum(serialize = "clear")]
428 Clear,
429 #[strum(serialize = "load")]
431 Load,
432 #[strum(serialize = "scan_in")]
434 ScanIn,
435 #[strum(serialize = "scan_enable")]
437 ScanEnable,
438}
439crate::ast::impl_self_builder!(NextstateType);
440crate::ast::impl_simple!(NextstateType);
441
442#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
443#[derive(serde::Serialize, serde::Deserialize)]
444pub enum PinFuncType {
445 #[strum(serialize = "clock_enable")]
446 ClockEnable,
447 #[strum(serialize = "active_high")]
448 ActiveHigh,
449 #[strum(serialize = "active_low")]
450 ActiveLow,
451 #[strum(serialize = "active_rising")]
452 ActiveRising,
453 #[strum(serialize = "active_falling")]
454 ActiveFalling,
455}
456crate::ast::impl_self_builder!(PinFuncType);
457crate::ast::impl_simple!(PinFuncType);
458
459#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
460#[derive(serde::Serialize, serde::Deserialize)]
461pub enum RestoreEdgeType {
462 #[strum(serialize = "edge_trigger")]
463 EdgeTrigger,
464 #[strum(serialize = "leading")]
465 Leading,
466 #[strum(serialize = "trailing")]
467 Trailing,
468}
469crate::ast::impl_self_builder!(RestoreEdgeType);
470crate::ast::impl_simple!(RestoreEdgeType);
471
472#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
473#[derive(serde::Serialize, serde::Deserialize)]
474pub enum SignalType {
475 #[strum(serialize = "test_scan_in")]
476 TestScanIn,
477 #[strum(serialize = "test_scan_in_inverted")]
478 TestScanInInverted,
479 #[strum(serialize = "test_scan_out")]
480 TestScanOut,
481 #[strum(serialize = "test_scan_out_inverted")]
482 TestScanOutInverted,
483 #[strum(serialize = "test_scan_enable")]
484 TestScanEnable,
485 #[strum(serialize = "test_scan_enable_inverted")]
486 TestScanEnableInverted,
487 #[strum(serialize = "test_scan_clock")]
488 TestScanClock,
489 #[strum(serialize = "test_scan_clock_a")]
490 TestScanClockA,
491 #[strum(serialize = "test_scan_clock_b")]
492 TestScanClockB,
493 #[strum(serialize = "test_clock")]
494 TestClock,
495}
496crate::ast::impl_self_builder!(SignalType);
497crate::ast::impl_simple!(SignalType);
498
499#[derive(Default)]
500#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
501#[derive(serde::Serialize, serde::Deserialize)]
502pub enum SlewControl {
503 #[strum(serialize = "low")]
504 Low,
505 #[strum(serialize = "medium")]
506 Medium,
507 #[strum(serialize = "high")]
508 High,
509 #[default]
510 #[strum(serialize = "none")]
511 None,
512}
513crate::ast::impl_self_builder!(SlewControl);
514crate::ast::impl_simple!(SlewControl);
515
516#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
531#[derive(serde::Serialize, serde::Deserialize)]
532pub enum OneZero {
533 #[strum(serialize = "1")]
535 One,
536 #[strum(serialize = "0")]
538 Zero,
539}
540crate::ast::impl_self_builder!(OneZero);
541crate::ast::impl_simple!(OneZero);
542
543#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
544#[derive(serde::Serialize, serde::Deserialize)]
545enum OneValue {
546 #[strum(serialize = "1")]
547 One,
548 #[strum(serialize = "0")]
549 Zero,
550 #[strum(serialize = "x")]
551 Unkown,
552}
553#[derive(Debug, Clone, Eq, PartialEq, Copy)]
566#[derive(serde::Serialize, serde::Deserialize)]
567pub struct TwoValue(OneValue, OneValue);
568crate::ast::impl_self_builder!(TwoValue);
569crate::ast::impl_simple!(TwoValue);
570
571impl fmt::Display for TwoValue {
572 #[inline]
573 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
574 write!(f, "{}{}", self.0, self.1)
575 }
576}
577impl FromStr for TwoValue {
578 type Err = strum::ParseError;
579 #[inline]
580 fn from_str(s: &str) -> Result<Self, Self::Err> {
581 if s.len() != 2 {
582 return Err(strum::ParseError::VariantNotFound);
583 }
584 let mut i = s.chars();
585 if let Some(c1) = i.next()
586 && let Some(c2) = i.next()
587 {
588 let mut tmp = [0; 1];
589 return Ok(Self(
590 OneValue::from_str(c1.encode_utf8(&mut tmp))?,
591 OneValue::from_str(c2.encode_utf8(&mut tmp))?,
592 ));
593 }
594 Err(strum::ParseError::VariantNotFound)
595 }
596}
597
598#[derive(Debug, Clone, Eq, PartialEq)]
606#[derive(serde::Serialize, serde::Deserialize)]
607pub enum PinClass {
608 Save,
610 Restore,
612 SaveRestore,
614 PinName(String),
615}
616impl FromStr for PinClass {
617 type Err = ();
618 #[inline]
619 fn from_str(s: &str) -> Result<Self, Self::Err> {
620 match s {
621 "save" => Ok(Self::Save),
622 "restore" => Ok(Self::Restore),
623 "save_restore" => Ok(Self::SaveRestore),
624 _ => Ok(Self::PinName(s.to_owned())),
625 }
626 }
627}
628impl fmt::Display for PinClass {
629 #[inline]
630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
631 match self {
632 Self::Save => write!(f, "save"),
633 Self::Restore => write!(f, "restore"),
634 Self::SaveRestore => write!(f, "save_restore"),
635 Self::PinName(pin) => write!(f, "{pin}"),
636 }
637 }
638}
639#[derive(Debug, Clone)]
664#[derive(serde::Serialize, serde::Deserialize)]
665pub struct RetentionPin {
666 pub pin_class: PinClass,
668 pub disable_value: Static,
670}
671crate::ast::impl_self_builder!(RetentionPin);
672impl<C: 'static + Ctx> ComplexAttri<C> for RetentionPin {
673 #[inline]
674 fn parse<'a, I: Iterator<Item = &'a &'a str>>(
675 mut iter: I,
676 _scope: &mut ParseScope<'_>,
677 ) -> Result<Self, ComplexParseError> {
678 let pin_class: PinClass = match iter.next() {
679 Some(&s) => match s.parse() {
680 Ok(f) => f,
681 Err(_) => return Err(ComplexParseError::Other),
682 },
683 None => return Err(ComplexParseError::LengthDismatch),
684 };
685 let disable_value = match iter.next() {
686 Some(&s) => match s {
687 "1" => Static::H,
688 "0" => Static::L,
689 "X" | "x" => Static::X,
690 "Z" | "z" => Static::Z,
691 _ => return Err(ComplexParseError::UnsupportedWord),
692 },
693 None => return Err(ComplexParseError::LengthDismatch),
694 };
695 if iter.next().is_some() {
696 Err(ComplexParseError::LengthDismatch)
697 } else {
698 Ok(Self { pin_class, disable_value })
699 }
700 }
701 #[inline]
702 fn fmt_self<T: Write, I: Indentation>(
703 &self,
704 f: &mut CodeFormatter<'_, T, I>,
705 ) -> fmt::Result {
706 write!(
707 f,
708 "{}, {}",
709 self.pin_class,
710 match self.disable_value {
711 Static::X => "x",
712 Static::Z => "z",
713 Static::H => "1",
714 Static::L => "0",
715 }
716 )
717 }
718}
719
720#[cfg(test)]
721mod test {
722 use crate::DefaultCtx;
723
724 use super::*;
725 #[test]
726 fn two_value() {
727 assert_eq!(Ok(TwoValue(OneValue::Unkown, OneValue::One)), TwoValue::from_str("x1"));
728 assert_eq!(Ok(TwoValue(OneValue::Zero, OneValue::One)), TwoValue::from_str("01"));
729 assert_eq!(Err(strum::ParseError::VariantNotFound), TwoValue::from_str("1"));
730 assert_eq!(Err(strum::ParseError::VariantNotFound), TwoValue::from_str("111"));
731 assert_eq!(Err(strum::ParseError::VariantNotFound), TwoValue::from_str("1-"));
732 }
733 #[test]
734 fn retention_pin() {
735 let cell = crate::ast::test_parse_fmt::<crate::Cell<DefaultCtx>>(
736 r#"(cell1){
737 pin(A){
738 retention_pin (save_restore, 1);
739 }
740 pin(B){
741 retention_pin (restore, 0);
742 }
743 pin(C){
744 retention_pin ("save", 0);
745 }
746 }"#,
747 r#"
748liberty_db::cell::Cell (cell1) {
749| pin (A) {
750| | retention_pin (save_restore, 1);
751| }
752| pin (B) {
753| | retention_pin (restore, 0);
754| }
755| pin (C) {
756| | retention_pin (save, 0);
757| }
758}"#,
759 );
760 }
761 #[test]
762 fn driver_type() {
763 let cell = crate::ast::test_parse_fmt::<crate::Cell<DefaultCtx>>(
764 r#"(cell1){
765 pin(A){
766 direction: inout;
767 driver_type : "pull_up pull_down open_drain open_source bus_hold";
768 }
769 pin(B){
770 driver_type : pull_up;
771 }
772 pin(C){
773 driver_type : "bus_hold";
774 }
775 }"#,
776 r#"
777liberty_db::cell::Cell (cell1) {
778| pin (A) {
779| | direction : inout;
780| | driver_type : "pull_up pull_down open_drain open_source bus_hold";
781| }
782| pin (B) {
783| | driver_type : pull_up;
784| }
785| pin (C) {
786| | driver_type : open_source bus_hold;
787| }
788}"#,
789 );
790 }
791}