use crate::ast::*; use crate::parser::*; use nom::branch::*; use nom::combinator::*; use nom::sequence::*; use nom::IResult; // ----------------------------------------------------------------------------- #[derive(Debug, Node)] pub enum SystemTimingCheck<'a> { SetupTimingCheck(SetupTimingCheck<'a>), HoldTimingCheck(HoldTimingCheck<'a>), SetupholdTimingCheck(SetupholdTimingCheck<'a>), RecoveryTimingCheck(RecoveryTimingCheck<'a>), RemovalTimingCheck(RemovalTimingCheck<'a>), RecremTimingCheck(RecremTimingCheck<'a>), SkewTimingCheck(SkewTimingCheck<'a>), TimeskewTimingCheck(TimeskewTimingCheck<'a>), FullskewTimingCheck(FullskewTimingCheck<'a>), PeriodTimingCheck(PeriodTimingCheck<'a>), WidthTimingCheck(WidthTimingCheck<'a>), NochargeTimingCheck(NochargeTimingCheck<'a>), } #[derive(Debug, Node)] pub struct SetupTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( DataEvent<'a>, Symbol<'a>, ReferenceEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct HoldTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct SetupholdTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<(Symbol<'a>, Option>)>, )>, )>, )>, )>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct RecoveryTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct RemovalTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct RecremTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<(Symbol<'a>, Option>)>, )>, )>, )>, )>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct SkewTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct TimeskewTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<(Symbol<'a>, Option>)>, )>, )>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct FullskewTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<( Symbol<'a>, Option>, Option<( Symbol<'a>, Option>, Option<(Symbol<'a>, Option>)>, )>, )>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct PeriodTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ControlledReferenceEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct WidthTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ControlledReferenceEvent<'a>, Symbol<'a>, TimingCheckLimit<'a>, Symbol<'a>, Threshold<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } #[derive(Debug, Node)] pub struct NochargeTimingCheck<'a> { pub nodes: ( Symbol<'a>, Paren< 'a, ( ReferenceEvent<'a>, Symbol<'a>, DataEvent<'a>, Symbol<'a>, StartEdgeOffset<'a>, Symbol<'a>, EndEdgeOffset<'a>, Option<(Symbol<'a>, Option>)>, ), >, Symbol<'a>, ), } // ----------------------------------------------------------------------------- #[parser] pub fn system_timing_check(s: Span) -> IResult { alt(( map(setup_timing_check, |x| { SystemTimingCheck::SetupTimingCheck(x) }), map(hold_timing_check, |x| SystemTimingCheck::HoldTimingCheck(x)), map(setuphold_timing_check, |x| { SystemTimingCheck::SetupholdTimingCheck(x) }), map(recovery_timing_check, |x| { SystemTimingCheck::RecoveryTimingCheck(x) }), map(removal_timing_check, |x| { SystemTimingCheck::RemovalTimingCheck(x) }), map(recrem_timing_check, |x| { SystemTimingCheck::RecremTimingCheck(x) }), map(skew_timing_check, |x| SystemTimingCheck::SkewTimingCheck(x)), map(timeskew_timing_check, |x| { SystemTimingCheck::TimeskewTimingCheck(x) }), map(fullskew_timing_check, |x| { SystemTimingCheck::FullskewTimingCheck(x) }), map(period_timing_check, |x| { SystemTimingCheck::PeriodTimingCheck(x) }), map(width_timing_check, |x| { SystemTimingCheck::WidthTimingCheck(x) }), map(nocharge_timing_check, |x| { SystemTimingCheck::NochargeTimingCheck(x) }), ))(s) } #[parser] pub fn setup_timing_check(s: Span) -> IResult { let (s, a) = symbol("$setup")(s)?; let (s, b) = paren(tuple(( data_event, symbol(","), referecne_event, symbol(","), timing_check_limit, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, SetupTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn hold_timing_check(s: Span) -> IResult { let (s, a) = symbol("$setup")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, HoldTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn setuphold_timing_check(s: Span) -> IResult { let (s, a) = symbol("$setuphold")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, symbol(","), timing_check_limit, opt(triple( symbol(","), opt(notifier), opt(triple( symbol(","), opt(timestamp_condition), opt(triple( symbol(","), opt(timecheck_condition), opt(triple( symbol(","), opt(delayed_reference), opt(pair(symbol(","), opt(delayed_data))), )), )), )), )), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, SetupholdTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn recovery_timing_check(s: Span) -> IResult { let (s, a) = symbol("$recovery")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, RecoveryTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn removal_timing_check(s: Span) -> IResult { let (s, a) = symbol("$removal")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, RemovalTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn recrem_timing_check(s: Span) -> IResult { let (s, a) = symbol("$recrem")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, symbol(","), timing_check_limit, opt(triple( symbol(","), opt(notifier), opt(triple( symbol(","), opt(timestamp_condition), opt(triple( symbol(","), opt(timecheck_condition), opt(triple( symbol(","), opt(delayed_reference), opt(pair(symbol(","), opt(delayed_data))), )), )), )), )), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, RecremTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn skew_timing_check(s: Span) -> IResult { let (s, a) = symbol("$skew")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, SkewTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn timeskew_timing_check(s: Span) -> IResult { let (s, a) = symbol("$timeskew")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, opt(triple( symbol(","), opt(notifier), opt(triple( symbol(","), opt(event_based_flag), opt(pair(symbol(","), opt(remain_active_flag))), )), )), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, TimeskewTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn fullskew_timing_check(s: Span) -> IResult { let (s, a) = symbol("$fullskew")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), timing_check_limit, symbol(","), timing_check_limit, opt(triple( symbol(","), opt(notifier), opt(triple( symbol(","), opt(event_based_flag), opt(pair(symbol(","), opt(remain_active_flag))), )), )), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, FullskewTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn period_timing_check(s: Span) -> IResult { let (s, a) = symbol("$period")(s)?; let (s, b) = paren(tuple(( controlled_referecne_event, symbol(","), timing_check_limit, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, PeriodTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn width_timing_check(s: Span) -> IResult { let (s, a) = symbol("$width")(s)?; let (s, b) = paren(tuple(( controlled_referecne_event, symbol(","), timing_check_limit, symbol(","), threshold, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, WidthTimingCheck { nodes: (a, b, c) })) } #[parser] pub fn nocharge_timing_check(s: Span) -> IResult { let (s, a) = symbol("$nocharge")(s)?; let (s, b) = paren(tuple(( referecne_event, symbol(","), data_event, symbol(","), start_edge_offset, symbol(","), end_edge_offset, opt(pair(symbol(","), opt(notifier))), )))(s)?; let (s, c) = symbol(";")(s)?; Ok((s, NochargeTimingCheck { nodes: (a, b, c) })) }