use core::{fmt, str::FromStr};
use crate::{
ast::{ParseScope, SimpleAttri},
expression::logic,
types::MaxMin,
};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum ArcCombinational {
Combinational(Option<logic::Edge>),
ThreeStateDisable(Option<logic::Edge>),
ThreeStateEnable(Option<logic::Edge>),
}
impl ArcCombinational {
const COMBINATIONAL: &'static str = "combinational";
const COMBINATIONAL_RISE: &'static str = "combinational_rise";
const COMBINATIONAL_FALL: &'static str = "combinational_fall";
const THREE_STATE_DISABLE: &'static str = "three_state_disable";
const THREE_STATE_DISABLE_RISE: &'static str = "three_state_disable_rise";
const THREE_STATE_DISABLE_FALL: &'static str = "three_state_disable_fall";
const THREE_STATE_ENABLE: &'static str = "three_state_enable";
const THREE_STATE_ENABLE_RISE: &'static str = "three_state_enable_rise";
const THREE_STATE_ENABLE_FALL: &'static str = "three_state_enable_fall";
}
impl fmt::Display for ArcCombinational {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Combinational(edge) => match edge {
Some(_edge) => match _edge {
logic::Edge::Fall => write!(f, "{}", Self::COMBINATIONAL_FALL),
logic::Edge::Rise => write!(f, "{}", Self::COMBINATIONAL_RISE),
},
None => write!(f, "{}", Self::COMBINATIONAL),
},
Self::ThreeStateDisable(edge) => match edge {
Some(_edge) => match _edge {
logic::Edge::Fall => write!(f, "{}", Self::THREE_STATE_DISABLE_FALL),
logic::Edge::Rise => write!(f, "{}", Self::THREE_STATE_DISABLE_RISE),
},
None => write!(f, "{}", Self::THREE_STATE_DISABLE),
},
Self::ThreeStateEnable(edge) => match edge {
Some(_edge) => match _edge {
logic::Edge::Fall => write!(f, "{}", Self::THREE_STATE_ENABLE_FALL),
logic::Edge::Rise => write!(f, "{}", Self::THREE_STATE_ENABLE_RISE),
},
None => write!(f, "{}", Self::THREE_STATE_ENABLE),
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum ArcSequential {
Edge(logic::Edge),
Preset,
Clear,
Hold(logic::Edge),
Setup(logic::Edge),
Recovery(logic::Edge),
Skew(logic::Edge),
Removal(logic::Edge),
MinPulseWidth,
MinimumPeriod,
ClockTreePath(MaxMin),
}
impl ArcSequential {
const RISING_EDGE: &'static str = "rising_edge";
const FALLING_EDGE: &'static str = "falling_edge";
const PRESET: &'static str = "preset";
const CLEAR: &'static str = "clear";
const HOLD_RISING: &'static str = "hold_rising";
const HOLD_FALLING: &'static str = "hold_falling";
const SETUP_RISING: &'static str = "setup_rising";
const SETUP_FALLING: &'static str = "setup_falling";
const RECOVERY_RISING: &'static str = "recovery_rising";
const RECOVERY_FALLING: &'static str = "recovery_falling";
const SKEW_RISING: &'static str = "skew_rising";
const SKEW_FALLING: &'static str = "skew_falling";
const REMOVAL_RISING: &'static str = "removal_rising";
const REMOVAL_FALLING: &'static str = "removal_falling";
const MIN_PULSE_WIDTH: &'static str = "min_pulse_width";
const MINIMUM_PERIOD: &'static str = "minimum_period";
const MAX_CLOCK_TREE_PATH: &'static str = "max_clock_tree_path";
const MIN_CLOCK_TREE_PATH: &'static str = "min_clock_tree_path";
}
impl fmt::Display for ArcSequential {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Edge(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::FALLING_EDGE),
logic::Edge::Rise => write!(f, "{}", Self::RISING_EDGE),
},
Self::Preset => write!(f, "{}", Self::PRESET),
Self::Clear => write!(f, "{}", Self::CLEAR),
Self::Hold(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::HOLD_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::HOLD_RISING),
},
Self::Setup(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::SETUP_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::SETUP_RISING),
},
Self::Recovery(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::RECOVERY_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::RECOVERY_RISING),
},
Self::Skew(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::SKEW_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::SKEW_RISING),
},
Self::Removal(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::REMOVAL_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::REMOVAL_RISING),
},
Self::MinPulseWidth => write!(f, "{}", Self::MIN_PULSE_WIDTH),
Self::MinimumPeriod => write!(f, "{}", Self::MINIMUM_PERIOD),
Self::ClockTreePath(max_min) => match max_min {
MaxMin::Max => write!(f, "{}", Self::MAX_CLOCK_TREE_PATH),
MaxMin::Min => write!(f, "{}", Self::MIN_CLOCK_TREE_PATH),
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum ArcNonSequential {
NonSeqSetup(logic::Edge),
NonSeqHold(logic::Edge),
}
impl ArcNonSequential {
const NON_SEQ_SETUP_RISING: &'static str = "non_seq_setup_rising";
const NON_SEQ_SETUP_FALLING: &'static str = "non_seq_setup_falling";
const NON_SEQ_HOLD_RISING: &'static str = "non_seq_hold_rising";
const NON_SEQ_HOLD_FALLING: &'static str = "non_seq_hold_falling";
}
impl fmt::Display for ArcNonSequential {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NonSeqSetup(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::NON_SEQ_SETUP_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::NON_SEQ_SETUP_RISING),
},
Self::NonSeqHold(edge) => match edge {
logic::Edge::Fall => write!(f, "{}", Self::NON_SEQ_HOLD_FALLING),
logic::Edge::Rise => write!(f, "{}", Self::NON_SEQ_HOLD_RISING),
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum ArcNoChange {
NoChange(logic::Level, logic::Level),
}
impl ArcNoChange {
const NOCHANGE_HIGH_HIGH: &'static str = "nochange_high_high";
const NOCHANGE_HIGH_LOW: &'static str = "nochange_high_low";
const NOCHANGE_LOW_HIGH: &'static str = "nochange_low_high";
const NOCHANGE_LOW_LOW: &'static str = "nochange_low_low";
}
impl fmt::Display for ArcNoChange {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoChange(s1, s2) => match (s1, s2) {
(logic::Level::High, logic::Level::High) => {
write!(f, "{}", Self::NOCHANGE_HIGH_HIGH)
}
(logic::Level::High, logic::Level::Low) => {
write!(f, "{}", Self::NOCHANGE_HIGH_LOW)
}
(logic::Level::Low, logic::Level::High) => {
write!(f, "{}", Self::NOCHANGE_LOW_HIGH)
}
(logic::Level::Low, logic::Level::Low) => {
write!(f, "{}", Self::NOCHANGE_LOW_LOW)
}
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum TimingType {
Combinational(ArcCombinational),
Sequential(ArcSequential),
NonSequential(ArcNonSequential),
NoChange(ArcNoChange),
}
impl SimpleAttri for TimingType {
#[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 FromStr for TimingType {
type Err = fmt::Error;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
ArcCombinational::COMBINATIONAL => Ok(Self::COMBINATIONAL),
ArcCombinational::COMBINATIONAL_RISE => Ok(Self::COMBINATIONAL_RISE),
ArcCombinational::COMBINATIONAL_FALL => Ok(Self::COMBINATIONAL_FALL),
ArcCombinational::THREE_STATE_DISABLE => Ok(Self::THREE_STATE_DISABLE),
ArcCombinational::THREE_STATE_DISABLE_RISE => Ok(Self::THREE_STATE_DISABLE_RISE),
ArcCombinational::THREE_STATE_DISABLE_FALL => Ok(Self::THREE_STATE_DISABLE_FALL),
ArcCombinational::THREE_STATE_ENABLE => Ok(Self::THREE_STATE_ENABLE),
ArcCombinational::THREE_STATE_ENABLE_RISE => Ok(Self::THREE_STATE_ENABLE_RISE),
ArcCombinational::THREE_STATE_ENABLE_FALL => Ok(Self::THREE_STATE_ENABLE_FALL),
ArcSequential::RISING_EDGE => Ok(Self::RISING_EDGE),
ArcSequential::FALLING_EDGE => Ok(Self::FALLING_EDGE),
ArcSequential::PRESET => Ok(Self::PRESET),
ArcSequential::CLEAR => Ok(Self::CLEAR),
ArcSequential::HOLD_RISING => Ok(Self::HOLD_RISING),
ArcSequential::HOLD_FALLING => Ok(Self::HOLD_FALLING),
ArcSequential::SETUP_RISING => Ok(Self::SETUP_RISING),
ArcSequential::SETUP_FALLING => Ok(Self::SETUP_FALLING),
ArcSequential::RECOVERY_RISING => Ok(Self::RECOVERY_RISING),
ArcSequential::RECOVERY_FALLING => Ok(Self::RECOVERY_FALLING),
ArcSequential::SKEW_RISING => Ok(Self::SKEW_RISING),
ArcSequential::SKEW_FALLING => Ok(Self::SKEW_FALLING),
ArcSequential::REMOVAL_RISING => Ok(Self::REMOVAL_RISING),
ArcSequential::REMOVAL_FALLING => Ok(Self::REMOVAL_FALLING),
ArcSequential::MIN_PULSE_WIDTH => Ok(Self::MIN_PULSE_WIDTH),
ArcSequential::MINIMUM_PERIOD => Ok(Self::MINIMUM_PERIOD),
ArcSequential::MAX_CLOCK_TREE_PATH => Ok(Self::MAX_CLOCK_TREE_PATH),
ArcSequential::MIN_CLOCK_TREE_PATH => Ok(Self::MIN_CLOCK_TREE_PATH),
ArcNonSequential::NON_SEQ_SETUP_RISING => Ok(Self::NON_SEQ_SETUP_RISING),
ArcNonSequential::NON_SEQ_SETUP_FALLING => Ok(Self::NON_SEQ_SETUP_FALLING),
ArcNonSequential::NON_SEQ_HOLD_RISING => Ok(Self::NON_SEQ_HOLD_RISING),
ArcNonSequential::NON_SEQ_HOLD_FALLING => Ok(Self::NON_SEQ_HOLD_FALLING),
ArcNoChange::NOCHANGE_HIGH_HIGH => Ok(Self::NOCHANGE_HIGH_HIGH),
ArcNoChange::NOCHANGE_HIGH_LOW => Ok(Self::NOCHANGE_HIGH_LOW),
ArcNoChange::NOCHANGE_LOW_HIGH => Ok(Self::NOCHANGE_LOW_HIGH),
ArcNoChange::NOCHANGE_LOW_LOW => Ok(Self::NOCHANGE_LOW_LOW),
_ => Err(fmt::Error),
}
}
}
impl fmt::Display for TimingType {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Combinational(t) => t.fmt(f),
Self::Sequential(t) => t.fmt(f),
Self::NonSequential(t) => t.fmt(f),
Self::NoChange(t) => t.fmt(f),
}
}
}
impl TimingType {
pub const COMBINATIONAL: Self =
Self::Combinational(ArcCombinational::Combinational(None));
pub const COMBINATIONAL_RISE: Self =
Self::Combinational(ArcCombinational::Combinational(Some(logic::Edge::Rise)));
pub const COMBINATIONAL_FALL: Self =
Self::Combinational(ArcCombinational::Combinational(Some(logic::Edge::Fall)));
pub const THREE_STATE_DISABLE: Self =
Self::Combinational(ArcCombinational::ThreeStateDisable(None));
pub const THREE_STATE_DISABLE_RISE: Self =
Self::Combinational(ArcCombinational::ThreeStateDisable(Some(logic::Edge::Rise)));
pub const THREE_STATE_DISABLE_FALL: Self =
Self::Combinational(ArcCombinational::ThreeStateDisable(Some(logic::Edge::Fall)));
pub const THREE_STATE_ENABLE: Self =
Self::Combinational(ArcCombinational::ThreeStateEnable(None));
pub const THREE_STATE_ENABLE_RISE: Self =
Self::Combinational(ArcCombinational::ThreeStateEnable(Some(logic::Edge::Rise)));
pub const THREE_STATE_ENABLE_FALL: Self =
Self::Combinational(ArcCombinational::ThreeStateEnable(Some(logic::Edge::Fall)));
pub const RISING_EDGE: Self = Self::Sequential(ArcSequential::Edge(logic::Edge::Rise));
pub const FALLING_EDGE: Self = Self::Sequential(ArcSequential::Edge(logic::Edge::Fall));
pub const PRESET: Self = Self::Sequential(ArcSequential::Preset);
pub const CLEAR: Self = Self::Sequential(ArcSequential::Clear);
pub const HOLD_RISING: Self = Self::Sequential(ArcSequential::Hold(logic::Edge::Rise));
pub const HOLD_FALLING: Self = Self::Sequential(ArcSequential::Hold(logic::Edge::Fall));
pub const SETUP_RISING: Self =
Self::Sequential(ArcSequential::Setup(logic::Edge::Rise));
pub const SETUP_FALLING: Self =
Self::Sequential(ArcSequential::Setup(logic::Edge::Fall));
pub const RECOVERY_RISING: Self =
Self::Sequential(ArcSequential::Recovery(logic::Edge::Rise));
pub const RECOVERY_FALLING: Self =
Self::Sequential(ArcSequential::Recovery(logic::Edge::Fall));
pub const SKEW_RISING: Self = Self::Sequential(ArcSequential::Skew(logic::Edge::Rise));
pub const SKEW_FALLING: Self = Self::Sequential(ArcSequential::Skew(logic::Edge::Fall));
pub const REMOVAL_RISING: Self =
Self::Sequential(ArcSequential::Removal(logic::Edge::Rise));
pub const REMOVAL_FALLING: Self =
Self::Sequential(ArcSequential::Removal(logic::Edge::Fall));
pub const MIN_PULSE_WIDTH: Self = Self::Sequential(ArcSequential::MinPulseWidth);
pub const MINIMUM_PERIOD: Self = Self::Sequential(ArcSequential::MinimumPeriod);
pub const MAX_CLOCK_TREE_PATH: Self =
Self::Sequential(ArcSequential::ClockTreePath(MaxMin::Max));
pub const MIN_CLOCK_TREE_PATH: Self =
Self::Sequential(ArcSequential::ClockTreePath(MaxMin::Min));
pub const NON_SEQ_SETUP_RISING: Self =
Self::NonSequential(ArcNonSequential::NonSeqSetup(logic::Edge::Rise));
pub const NON_SEQ_SETUP_FALLING: Self =
Self::NonSequential(ArcNonSequential::NonSeqSetup(logic::Edge::Fall));
pub const NON_SEQ_HOLD_RISING: Self =
Self::NonSequential(ArcNonSequential::NonSeqHold(logic::Edge::Rise));
pub const NON_SEQ_HOLD_FALLING: Self =
Self::NonSequential(ArcNonSequential::NonSeqHold(logic::Edge::Fall));
pub const NOCHANGE_HIGH_HIGH: Self =
Self::NoChange(ArcNoChange::NoChange(logic::Level::High, logic::Level::High));
pub const NOCHANGE_HIGH_LOW: Self =
Self::NoChange(ArcNoChange::NoChange(logic::Level::High, logic::Level::Low));
pub const NOCHANGE_LOW_HIGH: Self =
Self::NoChange(ArcNoChange::NoChange(logic::Level::Low, logic::Level::High));
pub const NOCHANGE_LOW_LOW: Self =
Self::NoChange(ArcNoChange::NoChange(logic::Level::Low, logic::Level::Low));
const LIST: [Self; 35] = [
Self::COMBINATIONAL,
Self::COMBINATIONAL_RISE,
Self::COMBINATIONAL_FALL,
Self::THREE_STATE_DISABLE,
Self::THREE_STATE_DISABLE_RISE,
Self::THREE_STATE_DISABLE_FALL,
Self::THREE_STATE_ENABLE,
Self::THREE_STATE_ENABLE_RISE,
Self::THREE_STATE_ENABLE_FALL,
Self::RISING_EDGE,
Self::FALLING_EDGE,
Self::PRESET,
Self::CLEAR,
Self::HOLD_RISING,
Self::HOLD_FALLING,
Self::SETUP_RISING,
Self::SETUP_FALLING,
Self::RECOVERY_RISING,
Self::RECOVERY_FALLING,
Self::SKEW_RISING,
Self::SKEW_FALLING,
Self::REMOVAL_RISING,
Self::REMOVAL_FALLING,
Self::MIN_PULSE_WIDTH,
Self::MINIMUM_PERIOD,
Self::MAX_CLOCK_TREE_PATH,
Self::MIN_CLOCK_TREE_PATH,
Self::NON_SEQ_SETUP_RISING,
Self::NON_SEQ_SETUP_FALLING,
Self::NON_SEQ_HOLD_RISING,
Self::NON_SEQ_HOLD_FALLING,
Self::NOCHANGE_HIGH_HIGH,
Self::NOCHANGE_HIGH_LOW,
Self::NOCHANGE_LOW_HIGH,
Self::NOCHANGE_LOW_LOW,
];
#[inline]
pub fn iter() -> impl Iterator<Item = Self> {
Self::LIST.iter().copied()
}
}