use crate::ast::{
CodeFormatter, ComplexAttri, ComplexParseError, Indentation, ParseScope, SimpleAttri,
};
use core::{
fmt::{self, Write},
str::FromStr,
};
use strum_macros::{Display, EnumString};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum AntennaDiodeType {
#[strum(serialize = "power")]
Power,
#[strum(serialize = "ground")]
Ground,
#[strum(serialize = "power_and_ground")]
PowerAndGround,
}
impl SimpleAttri for AntennaDiodeType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum Direction {
#[strum(serialize = "input")]
Input,
#[strum(serialize = "output")]
Output,
#[strum(serialize = "inout")]
Inout,
#[strum(serialize = "internal")]
Internal,
}
impl SimpleAttri for Direction {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum DontFault {
#[strum(serialize = "sa0")]
Sa0,
#[strum(serialize = "sa1")]
Sa1,
#[strum(serialize = "sao1")]
Sao1,
}
impl SimpleAttri for DontFault {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum DriverType {
#[strum(serialize = "pull_up")]
PullUp,
#[strum(serialize = "pull_down")]
PullDown,
#[strum(serialize = "open_drain")]
OpenDrain,
#[strum(serialize = "open_source")]
OpenSource,
#[strum(serialize = "bus_hold")]
BusHold,
#[strum(serialize = "resistive")]
Resistive,
#[strum(serialize = "resistive_0")]
Resistive0,
#[strum(serialize = "resistive_1")]
Resistive1,
}
impl SimpleAttri for DriverType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum NextstateType {
#[strum(serialize = "data")]
Data,
#[strum(serialize = "preset")]
Preset,
#[strum(serialize = "clear")]
Clear,
#[strum(serialize = "load")]
Load,
#[strum(serialize = "scan_in")]
ScanIn,
#[strum(serialize = "scan_enable")]
ScanEnable,
}
impl SimpleAttri for NextstateType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum PinFuncType {
#[strum(serialize = "clock_enable")]
ClockEnable,
#[strum(serialize = "active_high")]
ActiveHigh,
#[strum(serialize = "active_low")]
ActiveLow,
#[strum(serialize = "active_rising")]
ActiveRising,
#[strum(serialize = "active_falling")]
ActiveFalling,
}
impl SimpleAttri for PinFuncType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum RestoreEdgeType {
#[strum(serialize = "edge_trigger")]
EdgeTrigger,
#[strum(serialize = "leading")]
Leading,
#[strum(serialize = "trailing")]
Trailing,
}
impl SimpleAttri for RestoreEdgeType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum SignalType {
#[strum(serialize = "test_scan_in")]
TestScanIn,
#[strum(serialize = "test_scan_in_inverted")]
TestScanInInverted,
#[strum(serialize = "test_scan_out")]
TestScanOut,
#[strum(serialize = "test_scan_out_inverted")]
TestScanOutInverted,
#[strum(serialize = "test_scan_enable")]
TestScanEnable,
#[strum(serialize = "test_scan_enable_inverted")]
TestScanEnableInverted,
#[strum(serialize = "test_scan_clock")]
TestScanClock,
#[strum(serialize = "test_scan_clock_a")]
TestScanClockA,
#[strum(serialize = "test_scan_clock_b")]
TestScanClockB,
#[strum(serialize = "test_clock")]
TestClock,
}
impl SimpleAttri for SignalType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Default)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum SlewControl {
#[strum(serialize = "low")]
Low,
#[strum(serialize = "medium")]
Medium,
#[strum(serialize = "high")]
High,
#[default]
#[strum(serialize = "none")]
None,
}
impl SimpleAttri for SlewControl {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum OneZero {
#[strum(serialize = "1")]
One,
#[strum(serialize = "0")]
Zero,
}
impl SimpleAttri for OneZero {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
enum OneValue {
#[strum(serialize = "1")]
One,
#[strum(serialize = "0")]
Zero,
#[strum(serialize = "x")]
Unkown,
}
#[derive(Debug, Clone, Eq, PartialEq, Copy)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct TwoValue(OneValue, OneValue);
impl SimpleAttri for TwoValue {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
impl fmt::Display for TwoValue {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.0, self.1)
}
}
impl FromStr for TwoValue {
type Err = strum::ParseError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() != 2 {
return Err(strum::ParseError::VariantNotFound);
}
let mut i = s.chars();
if let Some(c1) = i.next() {
if let Some(c2) = i.next() {
let mut tmp = [0; 1];
return Ok(Self(
OneValue::from_str(c1.encode_utf8(&mut tmp))?,
OneValue::from_str(c2.encode_utf8(&mut tmp))?,
));
}
}
Err(strum::ParseError::VariantNotFound)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Display, EnumString)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum PinClass {
#[strum(serialize = "save")]
Save,
#[strum(serialize = "restore")]
Restore,
#[strum(serialize = "save_restore")]
SaveRestore,
}
#[derive(Debug, Clone, Copy)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct RetentionPin {
pub pin_class: PinClass,
pub disable_value: OneZero,
}
impl ComplexAttri for RetentionPin {
#[inline]
fn parse<'a, I: Iterator<Item = &'a Vec<&'a str>>>(
iter: I,
_scope: &mut ParseScope,
) -> Result<Self, ComplexParseError> {
let mut i = iter.flat_map(IntoIterator::into_iter);
let pin_class: PinClass = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(_) => return Err(ComplexParseError::Other),
},
None => return Err(ComplexParseError::LengthDismatch),
};
let disable_value: OneZero = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(_) => return Err(ComplexParseError::Other),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
Err(ComplexParseError::LengthDismatch)
} else {
Ok(Self { pin_class, disable_value })
}
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
write!(f, "{}, {}", self.pin_class, self.disable_value)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn two_value() {
assert_eq!(Ok(TwoValue(OneValue::Unkown, OneValue::One)), TwoValue::from_str("x1"));
assert_eq!(Ok(TwoValue(OneValue::Zero, OneValue::One)), TwoValue::from_str("01"));
assert_eq!(Err(strum::ParseError::VariantNotFound), TwoValue::from_str("1"));
assert_eq!(Err(strum::ParseError::VariantNotFound), TwoValue::from_str("111"));
assert_eq!(Err(strum::ParseError::VariantNotFound), TwoValue::from_str("1-"));
}
#[test]
fn retention_pin() {
let pin = crate::ast::test_parse_fmt::<crate::Cell>(
r#"(cell1){
pin(A){
retention_pin (save_restore, 1);
}
pin(B){
retention_pin (restore, 0);
}
pin(C){
retention_pin ("save", 0);
}
}"#,
r#"
liberty_db::cell::Cell (cell1) {
| pin (A) {
| | retention_pin (save_restore, 1);
| }
| pin (B) {
| | retention_pin (restore, 0);
| }
| pin (C) {
| | retention_pin (save, 0);
| }
}"#,
);
}
}