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