diff --git a/README.md b/README.md index 0d34890..b13b1a3 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,9 @@ A parser library for System Verilog. | instantiations | program_instantiation | x | x | | | instantiations | checker_instantiation | x | x | | | instantiations | generated_instantiation | x | x | | -| udp_declaration_and_instantiation | udp_declaration | | | | -| udp_declaration_and_instantiation | udp_ports | | | | -| udp_declaration_and_instantiation | udp_body | | | | +| udp_declaration_and_instantiation | udp_declaration | x | x | | +| udp_declaration_and_instantiation | udp_ports | x | x | | +| udp_declaration_and_instantiation | udp_body | x | x | | | udp_declaration_and_instantiation | udp_instantiation | x | x | | | behavioral_statements | continuous_assignment_and_net_alias | x | x | | | behavioral_statements | procedural_blocks_and_assignments | x | x | | @@ -58,13 +58,13 @@ A parser library for System Verilog. | behavioral_statements | assertion_statements | x | x | | | behavioral_statements | clocking_block | x | x | | | behavioral_statements | randsequence | x | x | | -| specify_section | specify_block_declaration | | | | -| specify_section | specify_path_declarations | | | | -| specify_section | specify_block_terminals | | | | -| specify_section | specify_path_delays | | | | -| specify_section | system_timing_check_commands | | | | -| specify_section | system_timing_check_command_arguments | | | | -| specify_section | system_timing_check_event_definitions | | | | +| specify_section | specify_block_declaration | x | x | | +| specify_section | specify_path_declarations | x | x | | +| specify_section | specify_block_terminals | x | x | | +| specify_section | specify_path_delays | x | x | | +| specify_section | system_timing_check_commands | x | x | | +| specify_section | system_timing_check_command_arguments | x | x | | +| specify_section | system_timing_check_event_definitions | x | x | | | expressions | concatenations | x | x | | | expressions | subroutine_calls | x | x | | | expressions | expressions | x | x | | @@ -76,3 +76,8 @@ A parser library for System Verilog. | general | attributes | x | x | x | | general | comments | x | x | x | | general | identifiers | x | x | x | + +## TODO + +* Exclude reserved keyword from identifiers. +* Implement ambiguous_alt for varirble_port_type. diff --git a/src/parser/specify_section/mod.rs b/src/parser/specify_section/mod.rs index 4c4eb12..0921b9d 100644 --- a/src/parser/specify_section/mod.rs +++ b/src/parser/specify_section/mod.rs @@ -1,6 +1,14 @@ pub mod specify_block_declaration; pub mod specify_block_terminals; +pub mod specify_path_declarations; pub mod specify_path_delays; +pub mod system_timing_check_command_arguments; +pub mod system_timing_check_commands; +pub mod system_timing_check_event_definitions; pub use specify_block_declaration::*; pub use specify_block_terminals::*; +pub use specify_path_declarations::*; pub use specify_path_delays::*; +pub use system_timing_check_command_arguments::*; +pub use system_timing_check_commands::*; +pub use system_timing_check_event_definitions::*; diff --git a/src/parser/specify_section/specify_block_declaration.rs b/src/parser/specify_section/specify_block_declaration.rs index 810e57a..49bdcd0 100644 --- a/src/parser/specify_section/specify_block_declaration.rs +++ b/src/parser/specify_section/specify_block_declaration.rs @@ -1,20 +1,75 @@ use crate::ast::*; use crate::parser::*; -//use nom::branch::*; -//use nom::combinator::*; -use nom::error::*; -use nom::{Err, IResult}; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::IResult; // ----------------------------------------------------------------------------- #[derive(Debug, Node)] pub struct SpecifyBlock<'a> { - pub nodes: (Identifier<'a>,), + pub nodes: (Symbol<'a>, Vec>, Symbol<'a>), +} + +#[derive(Debug, Node)] +pub enum SpecifyItem<'a> { + SpecparamDeclaration(SpecparamDeclaration<'a>), + PulsestyleDeclaration(PulsestyleDeclaration<'a>), + ShowcancelledDeclaration(ShowcancelledDeclaration<'a>), + PathDeclaration(PathDeclaration<'a>), + SystemTimingCheck(SystemTimingCheck<'a>), +} + +#[derive(Debug, Node)] +pub struct PulsestyleDeclaration<'a> { + pub nodes: (Symbol<'a>, ListOfPathOutputs<'a>, Symbol<'a>), +} + +#[derive(Debug, Node)] +pub struct ShowcancelledDeclaration<'a> { + pub nodes: (Symbol<'a>, ListOfPathOutputs<'a>, Symbol<'a>), } // ----------------------------------------------------------------------------- #[parser] pub fn specify_block(s: Span) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) + let (s, a) = symbol("specify")(s)?; + let (s, b) = many0(specify_item)(s)?; + let (s, c) = symbol("endspecify")(s)?; + Ok((s, SpecifyBlock { nodes: (a, b, c) })) +} + +#[parser] +pub fn specify_item(s: Span) -> IResult { + alt(( + map(specparam_declaration, |x| { + SpecifyItem::SpecparamDeclaration(x) + }), + map(pulsestyle_declaration, |x| { + SpecifyItem::PulsestyleDeclaration(x) + }), + map(showcancelled_declaration, |x| { + SpecifyItem::ShowcancelledDeclaration(x) + }), + map(path_declaration, |x| SpecifyItem::PathDeclaration(x)), + map(system_timing_check, |x| SpecifyItem::SystemTimingCheck(x)), + ))(s) +} + +#[parser] +pub fn pulsestyle_declaration(s: Span) -> IResult { + let (s, a) = alt((symbol("pulsestyle_onevent"), symbol("pulsestyle_ondetect")))(s)?; + let (s, b) = list_of_path_outputs(s)?; + let (s, c) = symbol(";")(s)?; + Ok((s, PulsestyleDeclaration { nodes: (a, b, c) })) +} + +#[parser] +pub fn showcancelled_declaration(s: Span) -> IResult { + let (s, a) = alt((symbol("showcalcelled"), symbol("noshowcancelled")))(s)?; + let (s, b) = list_of_path_outputs(s)?; + let (s, c) = symbol(";")(s)?; + Ok((s, ShowcancelledDeclaration { nodes: (a, b, c) })) } diff --git a/src/parser/specify_section/specify_block_terminals.rs b/src/parser/specify_section/specify_block_terminals.rs index 8f0022e..9708b81 100644 --- a/src/parser/specify_section/specify_block_terminals.rs +++ b/src/parser/specify_section/specify_block_terminals.rs @@ -1,20 +1,25 @@ use crate::ast::*; use crate::parser::*; -//use nom::branch::*; -//use nom::combinator::*; -use nom::error::*; -use nom::{Err, IResult}; +use nom::branch::*; +use nom::combinator::*; +use nom::IResult; // ----------------------------------------------------------------------------- #[derive(Debug, Node)] pub struct SpecifyInputTerminalDescriptor<'a> { - pub nodes: (InputIdentifier<'a>, Option>), + pub nodes: ( + InputIdentifier<'a>, + Option>>, + ), } #[derive(Debug, Node)] pub struct SpecifyOutputTerminalDescriptor<'a> { - pub nodes: (OutputIdentifier<'a>, Option>), + pub nodes: ( + OutputIdentifier<'a>, + Option>>, + ), } #[derive(Debug, Node)] @@ -26,7 +31,7 @@ pub enum InputIdentifier<'a> { #[derive(Debug, Node)] pub struct InputIdentifierInterface<'a> { - pub nodes: (InterfaceIdentifier<'a>, PortIdentifier<'a>), + pub nodes: (InterfaceIdentifier<'a>, Symbol<'a>, PortIdentifier<'a>), } #[derive(Debug, Node)] @@ -38,29 +43,71 @@ pub enum OutputIdentifier<'a> { #[derive(Debug, Node)] pub struct OutputIdentifierInterface<'a> { - pub nodes: (InterfaceIdentifier<'a>, PortIdentifier<'a>), + pub nodes: (InterfaceIdentifier<'a>, Symbol<'a>, PortIdentifier<'a>), } // ----------------------------------------------------------------------------- #[parser] pub fn specify_input_terminal_descriptor(s: Span) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) + let (s, a) = input_identifier(s)?; + let (s, b) = opt(bracket(constant_range_expression))(s)?; + Ok((s, SpecifyInputTerminalDescriptor { nodes: (a, b) })) } #[parser] pub fn specify_output_terminal_descriptor( s: Span, ) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) + let (s, a) = output_identifier(s)?; + let (s, b) = opt(bracket(constant_range_expression))(s)?; + Ok((s, SpecifyOutputTerminalDescriptor { nodes: (a, b) })) } #[parser] pub fn input_identifier(s: Span) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) + alt(( + map(input_port_identifier, |x| { + InputIdentifier::InputPortIdentifier(x) + }), + map(inout_port_identifier, |x| { + InputIdentifier::InoutPortIdentifier(x) + }), + input_identifier_interface, + ))(s) +} + +#[parser] +pub fn input_identifier_interface(s: Span) -> IResult { + let (s, a) = interface_identifier(s)?; + let (s, b) = symbol(".")(s)?; + let (s, c) = port_identifier(s)?; + Ok(( + s, + InputIdentifier::Interface(InputIdentifierInterface { nodes: (a, b, c) }), + )) } #[parser] pub fn output_identifier(s: Span) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) + alt(( + map(output_port_identifier, |x| { + OutputIdentifier::OutputPortIdentifier(x) + }), + map(inout_port_identifier, |x| { + OutputIdentifier::InoutPortIdentifier(x) + }), + output_identifier_interface, + ))(s) +} + +#[parser] +pub fn output_identifier_interface(s: Span) -> IResult { + let (s, a) = interface_identifier(s)?; + let (s, b) = symbol(".")(s)?; + let (s, c) = port_identifier(s)?; + Ok(( + s, + OutputIdentifier::Interface(OutputIdentifierInterface { nodes: (a, b, c) }), + )) } diff --git a/src/parser/specify_section/specify_path_declarations.rs b/src/parser/specify_section/specify_path_declarations.rs new file mode 100644 index 0000000..50a8024 --- /dev/null +++ b/src/parser/specify_section/specify_path_declarations.rs @@ -0,0 +1,152 @@ +use crate::ast::*; +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug, Node)] +pub enum PathDeclaration<'a> { + SimplePathDeclaration((SimplePathDeclaration<'a>, Symbol<'a>)), + EdgeSensitivePathDeclaration((EdgeSensitivePathDeclaration<'a>, Symbol<'a>)), + StateDependentPathDeclaration((StateDependentPathDeclaration<'a>, Symbol<'a>)), +} + +#[derive(Debug, Node)] +pub enum SimplePathDeclaration<'a> { + Parallel(SimplePathDeclarationParallel<'a>), + Full(SimplePathDeclarationFull<'a>), +} + +#[derive(Debug, Node)] +pub struct SimplePathDeclarationParallel<'a> { + pub nodes: (ParallelPathDescription<'a>, Symbol<'a>, PathDelayValue<'a>), +} + +#[derive(Debug, Node)] +pub struct SimplePathDeclarationFull<'a> { + pub nodes: (FullPathDescription<'a>, Symbol<'a>, PathDelayValue<'a>), +} + +#[derive(Debug, Node)] +pub struct ParallelPathDescription<'a> { + pub nodes: ( + Paren< + 'a, + ( + SpecifyInputTerminalDescriptor<'a>, + Option>, + Symbol<'a>, + SpecifyOutputTerminalDescriptor<'a>, + ), + >, + ), +} + +#[derive(Debug, Node)] +pub struct FullPathDescription<'a> { + pub nodes: ( + Paren< + 'a, + ( + ListOfPathInputs<'a>, + Option>, + Symbol<'a>, + ListOfPathOutputs<'a>, + ), + >, + ), +} + +#[derive(Debug, Node)] +pub struct ListOfPathInputs<'a> { + pub nodes: (List, SpecifyInputTerminalDescriptor<'a>>,), +} + +#[derive(Debug, Node)] +pub struct ListOfPathOutputs<'a> { + pub nodes: (List, SpecifyOutputTerminalDescriptor<'a>>,), +} + +// ----------------------------------------------------------------------------- + +#[parser] +pub fn path_declaration(s: Span) -> IResult { + alt(( + map(pair(simple_path_declaration, symbol(";")), |x| { + PathDeclaration::SimplePathDeclaration(x) + }), + map(pair(edge_sensitive_path_declaration, symbol(";")), |x| { + PathDeclaration::EdgeSensitivePathDeclaration(x) + }), + map(pair(state_dependent_path_declaration, symbol(";")), |x| { + PathDeclaration::StateDependentPathDeclaration(x) + }), + ))(s) +} + +#[parser] +pub fn simple_path_declaration(s: Span) -> IResult { + alt(( + simple_path_declaration_parallel, + simple_path_declaration_full, + ))(s) +} + +#[parser] +pub fn simple_path_declaration_parallel(s: Span) -> IResult { + let (s, a) = parallel_path_description(s)?; + let (s, b) = symbol("=")(s)?; + let (s, c) = path_delay_value(s)?; + Ok(( + s, + SimplePathDeclaration::Parallel(SimplePathDeclarationParallel { nodes: (a, b, c) }), + )) +} + +#[parser] +pub fn simple_path_declaration_full(s: Span) -> IResult { + let (s, a) = full_path_description(s)?; + let (s, b) = symbol("=")(s)?; + let (s, c) = path_delay_value(s)?; + Ok(( + s, + SimplePathDeclaration::Full(SimplePathDeclarationFull { nodes: (a, b, c) }), + )) +} + +#[parser] +pub fn parallel_path_description(s: Span) -> IResult { + let (s, a) = paren(tuple(( + specify_input_terminal_descriptor, + opt(polarity_operator), + symbol("=>"), + specify_output_terminal_descriptor, + )))(s)?; + Ok((s, ParallelPathDescription { nodes: (a,) })) +} + +#[parser] +pub fn full_path_description(s: Span) -> IResult { + let (s, a) = paren(tuple(( + list_of_path_inputs, + opt(polarity_operator), + symbol("*>"), + list_of_path_outputs, + )))(s)?; + Ok((s, FullPathDescription { nodes: (a,) })) +} + +#[parser] +pub fn list_of_path_inputs(s: Span) -> IResult { + let (s, a) = list(symbol(","), specify_input_terminal_descriptor)(s)?; + Ok((s, ListOfPathInputs { nodes: (a,) })) +} + +#[parser] +pub fn list_of_path_outputs(s: Span) -> IResult { + let (s, a) = list(symbol(","), specify_output_terminal_descriptor)(s)?; + Ok((s, ListOfPathOutputs { nodes: (a,) })) +} diff --git a/src/parser/specify_section/specify_path_delays.rs b/src/parser/specify_section/specify_path_delays.rs index 9d3b63e..3f111e8 100644 --- a/src/parser/specify_section/specify_path_delays.rs +++ b/src/parser/specify_section/specify_path_delays.rs @@ -1,20 +1,341 @@ use crate::ast::*; use crate::parser::*; -//use nom::branch::*; -//use nom::combinator::*; -use nom::error::*; -use nom::{Err, IResult}; +use nom::branch::*; +use nom::combinator::*; +use nom::sequence::*; +use nom::IResult; // ----------------------------------------------------------------------------- #[derive(Debug, Node)] -pub struct EdgeIdentifier<'a> { - pub nodes: (Identifier<'a>,), +pub enum PathDelayValue<'a> { + ListOfPathDelayExpressions(ListOfPathDelayExpressions<'a>), + Paren(PathDelayValueParen<'a>), +} + +#[derive(Debug, Node)] +pub struct PathDelayValueParen<'a> { + pub nodes: (Paren<'a, ListOfPathDelayExpressions<'a>>,), +} + +#[derive(Debug, Node)] +pub struct ListOfPathDelayExpressions<'a> { + pub nodes: (List, TPathDelayExpression<'a>>,), +} + +#[derive(Debug, Node)] +pub struct TPathDelayExpression<'a> { + pub nodes: (PathDelayExpression<'a>,), +} +#[derive(Debug, Node)] +pub struct PathDelayExpression<'a> { + pub nodes: (ConstantMintypmaxExpression<'a>,), +} + +#[derive(Debug, Node)] +pub enum EdgeSensitivePathDeclaration<'a> { + Parallel(EdgeSensitivePathDeclarationParallel<'a>), + Full(EdgeSensitivePathDeclarationFull<'a>), +} + +#[derive(Debug, Node)] +pub struct EdgeSensitivePathDeclarationParallel<'a> { + pub nodes: ( + ParallelEdgeSensitivePathDescription<'a>, + Symbol<'a>, + PathDelayValue<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct EdgeSensitivePathDeclarationFull<'a> { + pub nodes: ( + FullEdgeSensitivePathDescription<'a>, + Symbol<'a>, + PathDelayValue<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct ParallelEdgeSensitivePathDescription<'a> { + pub nodes: ( + Paren< + 'a, + ( + Option>, + SpecifyInputTerminalDescriptor<'a>, + Option>, + Symbol<'a>, + Paren< + 'a, + ( + SpecifyOutputTerminalDescriptor<'a>, + Option>, + Symbol<'a>, + DataSourceExpression<'a>, + ), + >, + ), + >, + ), +} + +#[derive(Debug, Node)] +pub struct FullEdgeSensitivePathDescription<'a> { + pub nodes: ( + Paren< + 'a, + ( + Option>, + ListOfPathInputs<'a>, + Option>, + Symbol<'a>, + Paren< + 'a, + ( + ListOfPathOutputs<'a>, + Option>, + Symbol<'a>, + DataSourceExpression<'a>, + ), + >, + ), + >, + ), +} + +#[derive(Debug, Node)] +pub struct DataSourceExpression<'a> { + pub nodes: (Expression<'a>,), +} + +#[derive(Debug, Node)] +pub enum EdgeIdentifier<'a> { + Posedge(Symbol<'a>), + Negedge(Symbol<'a>), + Edge(Symbol<'a>), +} + +#[derive(Debug, Node)] +pub enum StateDependentPathDeclaration<'a> { + IfSimple(StateDependentPathDeclarationIfSimple<'a>), + IfEdgeSensitive(StateDependentPathDeclarationIfEdgeSensitive<'a>), + IfNone(StateDependentPathDeclarationIfNone<'a>), +} + +#[derive(Debug, Node)] +pub struct StateDependentPathDeclarationIfSimple<'a> { + pub nodes: ( + Symbol<'a>, + Paren<'a, ModulePathExpression<'a>>, + SimplePathDeclaration<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct StateDependentPathDeclarationIfEdgeSensitive<'a> { + pub nodes: ( + Symbol<'a>, + Paren<'a, ModulePathExpression<'a>>, + EdgeSensitivePathDeclaration<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct StateDependentPathDeclarationIfNone<'a> { + pub nodes: (Symbol<'a>, SimplePathDeclaration<'a>), +} + +#[derive(Debug, Node)] +pub struct PolarityOperator<'a> { + pub nodes: (Symbol<'a>,), } // ----------------------------------------------------------------------------- #[parser] -pub fn edge_identifier(s: Span) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) +pub fn path_delay_value(s: Span) -> IResult { + alt(( + map(list_of_path_delay_expressions, |x| { + PathDelayValue::ListOfPathDelayExpressions(x) + }), + path_delay_value_paren, + ))(s) +} + +#[parser] +pub fn path_delay_value_paren(s: Span) -> IResult { + let (s, a) = paren(list_of_path_delay_expressions)(s)?; + Ok(( + s, + PathDelayValue::Paren(PathDelayValueParen { nodes: (a,) }), + )) +} + +#[parser] +pub fn list_of_path_delay_expressions(s: Span) -> IResult { + let (s, a) = list(symbol(","), t_path_delay_expression)(s)?; + Ok((s, ListOfPathDelayExpressions { nodes: (a,) })) +} + +#[parser] +pub fn t_path_delay_expression(s: Span) -> IResult { + let (s, a) = path_delay_expression(s)?; + Ok((s, TPathDelayExpression { nodes: (a,) })) +} + +#[parser] +pub fn path_delay_expression(s: Span) -> IResult { + let (s, a) = constant_mintypmax_expression(s)?; + Ok((s, PathDelayExpression { nodes: (a,) })) +} + +#[parser] +pub fn edge_sensitive_path_declaration(s: Span) -> IResult { + alt(( + edge_sensitive_path_declaration_parallel, + edge_sensitive_path_declaration_full, + ))(s) +} + +#[parser] +pub fn edge_sensitive_path_declaration_parallel( + s: Span, +) -> IResult { + let (s, a) = parallel_edge_sensitive_path_description(s)?; + let (s, b) = symbol("=")(s)?; + let (s, c) = path_delay_value(s)?; + Ok(( + s, + EdgeSensitivePathDeclaration::Parallel(EdgeSensitivePathDeclarationParallel { + nodes: (a, b, c), + }), + )) +} + +#[parser] +pub fn edge_sensitive_path_declaration_full( + s: Span, +) -> IResult { + let (s, a) = full_edge_sensitive_path_description(s)?; + let (s, b) = symbol("=")(s)?; + let (s, c) = path_delay_value(s)?; + Ok(( + s, + EdgeSensitivePathDeclaration::Full(EdgeSensitivePathDeclarationFull { nodes: (a, b, c) }), + )) +} + +#[parser] +pub fn parallel_edge_sensitive_path_description( + s: Span, +) -> IResult { + let (s, a) = paren(tuple(( + opt(edge_identifier), + specify_input_terminal_descriptor, + opt(polarity_operator), + symbol("=>"), + paren(tuple(( + specify_output_terminal_descriptor, + opt(polarity_operator), + symbol(":"), + data_source_expression, + ))), + )))(s)?; + Ok((s, ParallelEdgeSensitivePathDescription { nodes: (a,) })) +} + +#[parser] +pub fn full_edge_sensitive_path_description( + s: Span, +) -> IResult { + let (s, a) = paren(tuple(( + opt(edge_identifier), + list_of_path_inputs, + opt(polarity_operator), + symbol("*>"), + paren(tuple(( + list_of_path_outputs, + opt(polarity_operator), + symbol(":"), + data_source_expression, + ))), + )))(s)?; + Ok((s, FullEdgeSensitivePathDescription { nodes: (a,) })) +} + +#[parser] +pub fn data_source_expression(s: Span) -> IResult { + let (s, a) = expression(s)?; + Ok((s, DataSourceExpression { nodes: (a,) })) +} + +#[parser] +pub fn edge_identifier(s: Span) -> IResult { + alt(( + map(symbol("posedge"), |x| EdgeIdentifier::Posedge(x)), + map(symbol("negedge"), |x| EdgeIdentifier::Negedge(x)), + map(symbol("edge"), |x| EdgeIdentifier::Edge(x)), + ))(s) +} + +#[parser] +pub fn state_dependent_path_declaration(s: Span) -> IResult { + alt(( + state_dependent_path_declaration_if_simple, + state_dependent_path_declaration_if_edge_sensitive, + state_dependent_path_declaration_if_none, + ))(s) +} + +#[parser] +pub fn state_dependent_path_declaration_if_simple( + s: Span, +) -> IResult { + let (s, a) = symbol("if")(s)?; + let (s, b) = paren(module_path_expression)(s)?; + let (s, c) = simple_path_declaration(s)?; + Ok(( + s, + StateDependentPathDeclaration::IfSimple(StateDependentPathDeclarationIfSimple { + nodes: (a, b, c), + }), + )) +} + +#[parser] +pub fn state_dependent_path_declaration_if_edge_sensitive( + s: Span, +) -> IResult { + let (s, a) = symbol("if")(s)?; + let (s, b) = paren(module_path_expression)(s)?; + let (s, c) = edge_sensitive_path_declaration(s)?; + Ok(( + s, + StateDependentPathDeclaration::IfEdgeSensitive( + StateDependentPathDeclarationIfEdgeSensitive { nodes: (a, b, c) }, + ), + )) +} + +#[parser] +pub fn state_dependent_path_declaration_if_none( + s: Span, +) -> IResult { + let (s, a) = symbol("ifnone")(s)?; + let (s, b) = simple_path_declaration(s)?; + Ok(( + s, + StateDependentPathDeclaration::IfNone(StateDependentPathDeclarationIfNone { + nodes: (a, b), + }), + )) +} + +#[parser] +pub fn polarity_operator(s: Span) -> IResult { + alt(( + map(symbol("+"), |x| PolarityOperator { nodes: (x,) }), + map(symbol("-"), |x| PolarityOperator { nodes: (x,) }), + ))(s) } diff --git a/src/parser/specify_section/system_timing_check_command_arguments.rs b/src/parser/specify_section/system_timing_check_command_arguments.rs new file mode 100644 index 0000000..4dac4e6 --- /dev/null +++ b/src/parser/specify_section/system_timing_check_command_arguments.rs @@ -0,0 +1,207 @@ +use crate::ast::*; +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug, Node)] +pub struct TimecheckCondition<'a> { + pub nodes: (MintypmaxExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct ControlledReferenceEvent<'a> { + pub nodes: (ControlledTimingCheckEvent<'a>,), +} + +#[derive(Debug, Node)] +pub struct DataEvent<'a> { + pub nodes: (TimingCheckEvent<'a>,), +} + +#[derive(Debug, Node)] +pub enum DelayedData<'a> { + TerminalIdentifier(TerminalIdentifier<'a>), + WithMintypmax(DelayedDataWithMintypmax<'a>), +} + +#[derive(Debug, Node)] +pub struct DelayedDataWithMintypmax<'a> { + pub nodes: ( + TerminalIdentifier<'a>, + Bracket<'a, ConstantMintypmaxExpression<'a>>, + ), +} + +#[derive(Debug, Node)] +pub enum DelayedReference<'a> { + TerminalIdentifier(TerminalIdentifier<'a>), + WithMintypmax(DelayedReferenceWithMintypmax<'a>), +} + +#[derive(Debug, Node)] +pub struct DelayedReferenceWithMintypmax<'a> { + pub nodes: ( + TerminalIdentifier<'a>, + Bracket<'a, ConstantMintypmaxExpression<'a>>, + ), +} + +#[derive(Debug, Node)] +pub struct EndEdgeOffset<'a> { + pub nodes: (MintypmaxExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct EventBasedFlag<'a> { + pub nodes: (ConstantExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct Notifier<'a> { + pub nodes: (VariableIdentifier<'a>,), +} + +#[derive(Debug, Node)] +pub struct ReferenceEvent<'a> { + pub nodes: (TimingCheckEvent<'a>,), +} + +#[derive(Debug, Node)] +pub struct RemainActiveFlag<'a> { + pub nodes: (ConstantMintypmaxExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct TimestampCondition<'a> { + pub nodes: (MintypmaxExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct StartEdgeOffset<'a> { + pub nodes: (MintypmaxExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct Threshold<'a> { + pub nodes: (ConstantExpression<'a>,), +} + +#[derive(Debug, Node)] +pub struct TimingCheckLimit<'a> { + pub nodes: (Expression<'a>,), +} + +// ----------------------------------------------------------------------------- + +#[parser] +pub fn timecheck_condition(s: Span) -> IResult { + let (s, a) = mintypmax_expression(s)?; + Ok((s, TimecheckCondition { nodes: (a,) })) +} + +#[parser] +pub fn controlled_referecne_event(s: Span) -> IResult { + let (s, a) = controlled_timing_check_event(s)?; + Ok((s, ControlledReferenceEvent { nodes: (a,) })) +} + +#[parser] +pub fn data_event(s: Span) -> IResult { + let (s, a) = timing_check_event(s)?; + Ok((s, DataEvent { nodes: (a,) })) +} + +#[parser] +pub fn delayed_data(s: Span) -> IResult { + alt(( + map(terminal_identifier, |x| DelayedData::TerminalIdentifier(x)), + delayed_data_with_mintypmax, + ))(s) +} + +#[parser] +pub fn delayed_data_with_mintypmax(s: Span) -> IResult { + let (s, a) = terminal_identifier(s)?; + let (s, b) = bracket(constant_mintypmax_expression)(s)?; + Ok(( + s, + DelayedData::WithMintypmax(DelayedDataWithMintypmax { nodes: (a, b) }), + )) +} + +#[parser] +pub fn delayed_reference(s: Span) -> IResult { + alt(( + map(terminal_identifier, |x| { + DelayedReference::TerminalIdentifier(x) + }), + delayed_reference_with_mintypmax, + ))(s) +} + +#[parser] +pub fn delayed_reference_with_mintypmax(s: Span) -> IResult { + let (s, a) = terminal_identifier(s)?; + let (s, b) = bracket(constant_mintypmax_expression)(s)?; + Ok(( + s, + DelayedReference::WithMintypmax(DelayedReferenceWithMintypmax { nodes: (a, b) }), + )) +} + +#[parser] +pub fn end_edge_offset(s: Span) -> IResult { + let (s, a) = mintypmax_expression(s)?; + Ok((s, EndEdgeOffset { nodes: (a,) })) +} + +#[parser] +pub fn event_based_flag(s: Span) -> IResult { + let (s, a) = constant_expression(s)?; + Ok((s, EventBasedFlag { nodes: (a,) })) +} + +#[parser] +pub fn notifier(s: Span) -> IResult { + let (s, a) = variable_identifier(s)?; + Ok((s, Notifier { nodes: (a,) })) +} + +#[parser] +pub fn referecne_event(s: Span) -> IResult { + let (s, a) = timing_check_event(s)?; + Ok((s, ReferenceEvent { nodes: (a,) })) +} + +#[parser] +pub fn remain_active_flag(s: Span) -> IResult { + let (s, a) = constant_mintypmax_expression(s)?; + Ok((s, RemainActiveFlag { nodes: (a,) })) +} + +#[parser] +pub fn timestamp_condition(s: Span) -> IResult { + let (s, a) = mintypmax_expression(s)?; + Ok((s, TimestampCondition { nodes: (a,) })) +} + +#[parser] +pub fn start_edge_offset(s: Span) -> IResult { + let (s, a) = mintypmax_expression(s)?; + Ok((s, StartEdgeOffset { nodes: (a,) })) +} + +#[parser] +pub fn threshold(s: Span) -> IResult { + let (s, a) = constant_expression(s)?; + Ok((s, Threshold { nodes: (a,) })) +} + +#[parser] +pub fn timing_check_limit(s: Span) -> IResult { + let (s, a) = expression(s)?; + Ok((s, TimingCheckLimit { nodes: (a,) })) +} diff --git a/src/parser/specify_section/system_timing_check_commands.rs b/src/parser/specify_section/system_timing_check_commands.rs new file mode 100644 index 0000000..4ecf558 --- /dev/null +++ b/src/parser/specify_section/system_timing_check_commands.rs @@ -0,0 +1,580 @@ +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) })) +} diff --git a/src/parser/specify_section/system_timing_check_event_definitions.rs b/src/parser/specify_section/system_timing_check_event_definitions.rs new file mode 100644 index 0000000..227ca16 --- /dev/null +++ b/src/parser/specify_section/system_timing_check_event_definitions.rs @@ -0,0 +1,224 @@ +use crate::ast::*; +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug, Node)] +pub struct TimingCheckEvent<'a> { + pub nodes: ( + Option>, + SpecifyTerminalDescriptor<'a>, + Option<(Symbol<'a>, TimingCheckCondition<'a>)>, + ), +} + +#[derive(Debug, Node)] +pub struct ControlledTimingCheckEvent<'a> { + pub nodes: ( + TimingCheckEventControl<'a>, + SpecifyTerminalDescriptor<'a>, + Option<(Symbol<'a>, TimingCheckCondition<'a>)>, + ), +} + +#[derive(Debug, Node)] +pub enum TimingCheckEventControl<'a> { + Posedge(Symbol<'a>), + Negedge(Symbol<'a>), + Edge(Symbol<'a>), + EdgeControlSpecifier(EdgeControlSpecifier<'a>), +} + +#[derive(Debug, Node)] +pub enum SpecifyTerminalDescriptor<'a> { + SpecifyInputTerminalDescriptor(SpecifyInputTerminalDescriptor<'a>), + SpecifyOutputTerminalDescriptor(SpecifyOutputTerminalDescriptor<'a>), +} + +#[derive(Debug, Node)] +pub struct EdgeControlSpecifier<'a> { + pub nodes: ( + Symbol<'a>, + Bracket<'a, List, EdgeDescriptor<'a>>>, + ), +} + +#[derive(Debug, Node)] +pub struct EdgeDescriptor<'a> { + pub nodes: (Symbol<'a>,), +} + +#[derive(Debug, Node)] +pub enum TimingCheckCondition<'a> { + ScalarTimingCheckCondition(ScalarTimingCheckCondition<'a>), + Paren(TimingCheckConditionParen<'a>), +} + +#[derive(Debug, Node)] +pub struct TimingCheckConditionParen<'a> { + pub nodes: (Paren<'a, ScalarTimingCheckCondition<'a>>,), +} + +#[derive(Debug, Node)] +pub enum ScalarTimingCheckCondition<'a> { + Expression(Expression<'a>), + Unary(ScalarTimingCheckConditionUnary<'a>), + Binary(ScalarTimingCheckConditionBinary<'a>), +} + +#[derive(Debug, Node)] +pub struct ScalarTimingCheckConditionUnary<'a> { + pub nodes: (Symbol<'a>, Expression<'a>), +} + +#[derive(Debug, Node)] +pub struct ScalarTimingCheckConditionBinary<'a> { + pub nodes: (Expression<'a>, Symbol<'a>, ScalarConstant<'a>), +} + +#[derive(Debug, Node)] +pub struct ScalarConstant<'a> { + pub nodes: (Symbol<'a>,), +} + +// ----------------------------------------------------------------------------- + +#[parser] +pub fn timing_check_event(s: Span) -> IResult { + let (s, a) = opt(timing_check_event_control)(s)?; + let (s, b) = specify_terminal_descriptor(s)?; + let (s, c) = opt(pair(symbol("&&&"), timing_check_condition))(s)?; + Ok((s, TimingCheckEvent { nodes: (a, b, c) })) +} + +#[parser] +pub fn controlled_timing_check_event(s: Span) -> IResult { + let (s, a) = timing_check_event_control(s)?; + let (s, b) = specify_terminal_descriptor(s)?; + let (s, c) = opt(pair(symbol("&&&"), timing_check_condition))(s)?; + Ok((s, ControlledTimingCheckEvent { nodes: (a, b, c) })) +} + +#[parser] +pub fn timing_check_event_control(s: Span) -> IResult { + alt(( + map(symbol("posedge"), |x| TimingCheckEventControl::Posedge(x)), + map(symbol("negedge"), |x| TimingCheckEventControl::Negedge(x)), + map(symbol("edge"), |x| TimingCheckEventControl::Edge(x)), + map(edge_control_specifier, |x| { + TimingCheckEventControl::EdgeControlSpecifier(x) + }), + ))(s) +} + +#[parser] +pub fn specify_terminal_descriptor(s: Span) -> IResult { + alt(( + map(specify_input_terminal_descriptor, |x| { + SpecifyTerminalDescriptor::SpecifyInputTerminalDescriptor(x) + }), + map(specify_output_terminal_descriptor, |x| { + SpecifyTerminalDescriptor::SpecifyOutputTerminalDescriptor(x) + }), + ))(s) +} + +#[parser] +pub fn edge_control_specifier(s: Span) -> IResult { + let (s, a) = symbol("edge")(s)?; + let (s, b) = bracket(list(symbol(","), edge_descriptor))(s)?; + Ok((s, EdgeControlSpecifier { nodes: (a, b) })) +} + +#[parser] +pub fn edge_descriptor(s: Span) -> IResult { + alt(( + map(symbol("01"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("10"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("x0"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("x1"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("X0"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("X1"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("z0"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("z1"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("Z0"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("Z1"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("0x"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("1x"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("0X"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("1X"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("0z"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("1z"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("0Z"), |x| EdgeDescriptor { nodes: (x,) }), + map(symbol("1Z"), |x| EdgeDescriptor { nodes: (x,) }), + ))(s) +} + +#[parser] +pub fn timing_check_condition(s: Span) -> IResult { + alt(( + map(scalar_timing_check_condition, |x| { + TimingCheckCondition::ScalarTimingCheckCondition(x) + }), + timing_check_condition_paren, + ))(s) +} + +#[parser] +pub fn timing_check_condition_paren(s: Span) -> IResult { + let (s, a) = paren(scalar_timing_check_condition)(s)?; + Ok(( + s, + TimingCheckCondition::Paren(TimingCheckConditionParen { nodes: (a,) }), + )) +} + +#[parser] +pub fn scalar_timing_check_condition(s: Span) -> IResult { + alt(( + map(expression, |x| ScalarTimingCheckCondition::Expression(x)), + scalar_timing_check_condition_unary, + scalar_timing_check_condition_binary, + ))(s) +} + +#[parser] +pub fn scalar_timing_check_condition_unary(s: Span) -> IResult { + let (s, a) = symbol("~")(s)?; + let (s, b) = expression(s)?; + Ok(( + s, + ScalarTimingCheckCondition::Unary(ScalarTimingCheckConditionUnary { nodes: (a, b) }), + )) +} + +#[parser] +pub fn scalar_timing_check_condition_binary(s: Span) -> IResult { + let (s, a) = expression(s)?; + let (s, b) = alt((symbol("==="), symbol("=="), symbol("!=="), symbol("!=")))(s)?; + let (s, c) = scalar_constant(s)?; + Ok(( + s, + ScalarTimingCheckCondition::Binary(ScalarTimingCheckConditionBinary { nodes: (a, b, c) }), + )) +} + +#[parser] +pub fn scalar_constant(s: Span) -> IResult { + alt(( + map(symbol("1'b0"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("1'b1"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("1'B0"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("1'B1"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("'b0"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("'b1"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("'B0"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("'B1"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("1"), |x| ScalarConstant { nodes: (x,) }), + map(symbol("0"), |x| ScalarConstant { nodes: (x,) }), + ))(s) +} diff --git a/src/parser/udp_declaration_and_instantiation/mod.rs b/src/parser/udp_declaration_and_instantiation/mod.rs index a55f775..8082bcf 100644 --- a/src/parser/udp_declaration_and_instantiation/mod.rs +++ b/src/parser/udp_declaration_and_instantiation/mod.rs @@ -1,4 +1,8 @@ +pub mod udp_body; pub mod udp_declaration; pub mod udp_instantiation; +pub mod udp_ports; +pub use udp_body::*; pub use udp_declaration::*; pub use udp_instantiation::*; +pub use udp_ports::*; diff --git a/src/parser/udp_declaration_and_instantiation/udp_body.rs b/src/parser/udp_declaration_and_instantiation/udp_body.rs new file mode 100644 index 0000000..4b8ca92 --- /dev/null +++ b/src/parser/udp_declaration_and_instantiation/udp_body.rs @@ -0,0 +1,315 @@ +use crate::ast::*; +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug, Node)] +pub enum UdpBody<'a> { + CombinationalBody(CombinationalBody<'a>), + SequentialBody(SequentialBody<'a>), +} + +#[derive(Debug, Node)] +pub struct CombinationalBody<'a> { + pub nodes: ( + Symbol<'a>, + CombinationalEntry<'a>, + Vec>, + Symbol<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct CombinationalEntry<'a> { + pub nodes: (LevelInputList<'a>, Symbol<'a>, OutputSymbol<'a>, Symbol<'a>), +} + +#[derive(Debug, Node)] +pub struct SequentialBody<'a> { + pub nodes: ( + Option>, + Symbol<'a>, + SequentialEntry<'a>, + Vec>, + Symbol<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpInitialStatement<'a> { + pub nodes: ( + Symbol<'a>, + OutputPortIdentifier<'a>, + Symbol<'a>, + InitVal<'a>, + Symbol<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct InitVal<'a> { + pub nodes: (Symbol<'a>,), +} + +#[derive(Debug, Node)] +pub struct SequentialEntry<'a> { + pub nodes: ( + SeqInputList<'a>, + Symbol<'a>, + CurrentState<'a>, + Symbol<'a>, + NextState<'a>, + Symbol<'a>, + ), +} + +#[derive(Debug, Node)] +pub enum SeqInputList<'a> { + LevelInputList(LevelInputList<'a>), + EdgeInputList(EdgeInputList<'a>), +} + +#[derive(Debug, Node)] +pub struct LevelInputList<'a> { + pub nodes: (LevelSymbol<'a>, Vec>), +} + +#[derive(Debug, Node)] +pub struct EdgeInputList<'a> { + pub nodes: ( + Vec>, + EdgeIndicator<'a>, + Vec>, + ), +} + +#[derive(Debug, Node)] +pub enum EdgeIndicator<'a> { + Paren(EdgeIndicatorParen<'a>), + EdgeSymbol(EdgeSymbol<'a>), +} + +#[derive(Debug, Node)] +pub struct EdgeIndicatorParen<'a> { + pub nodes: (Paren<'a, (LevelSymbol<'a>, LevelSymbol<'a>)>,), +} + +#[derive(Debug, Node)] +pub struct CurrentState<'a> { + pub nodes: (LevelSymbol<'a>,), +} + +#[derive(Debug, Node)] +pub enum NextState<'a> { + OutputSymbol(OutputSymbol<'a>), + Minus(Symbol<'a>), +} + +#[derive(Debug, Node)] +pub struct OutputSymbol<'a> { + pub nodes: (Symbol<'a>,), +} + +#[derive(Debug, Node)] +pub struct LevelSymbol<'a> { + pub nodes: (Symbol<'a>,), +} + +#[derive(Debug, Node)] +pub struct EdgeSymbol<'a> { + pub nodes: (Symbol<'a>,), +} + +// ----------------------------------------------------------------------------- + +#[parser] +pub fn udp_body(s: Span) -> IResult { + alt(( + map(combinational_body, |x| UdpBody::CombinationalBody(x)), + map(sequential_body, |x| UdpBody::SequentialBody(x)), + ))(s) +} + +#[parser] +pub fn combinational_body(s: Span) -> IResult { + let (s, a) = symbol("table")(s)?; + let (s, b) = combinational_entry(s)?; + let (s, c) = many0(combinational_entry)(s)?; + let (s, d) = symbol("endtable")(s)?; + Ok(( + s, + CombinationalBody { + nodes: (a, b, c, d), + }, + )) +} + +#[parser] +pub fn combinational_entry(s: Span) -> IResult { + let (s, a) = level_input_list(s)?; + let (s, b) = symbol(":")(s)?; + let (s, c) = output_symbol(s)?; + let (s, d) = symbol(";")(s)?; + Ok(( + s, + CombinationalEntry { + nodes: (a, b, c, d), + }, + )) +} + +#[parser] +pub fn sequential_body(s: Span) -> IResult { + let (s, a) = opt(udp_initial_statement)(s)?; + let (s, b) = symbol("table")(s)?; + let (s, c) = sequential_entry(s)?; + let (s, d) = many0(sequential_entry)(s)?; + let (s, e) = symbol("endtable")(s)?; + Ok(( + s, + SequentialBody { + nodes: (a, b, c, d, e), + }, + )) +} + +#[parser] +pub fn udp_initial_statement(s: Span) -> IResult { + let (s, a) = symbol("initial")(s)?; + let (s, b) = output_port_identifier(s)?; + let (s, c) = symbol("=")(s)?; + let (s, d) = init_val(s)?; + let (s, e) = symbol(";")(s)?; + Ok(( + s, + UdpInitialStatement { + nodes: (a, b, c, d, e), + }, + )) +} + +#[parser] +pub fn init_val(s: Span) -> IResult { + alt(( + map(symbol("1'b0"), |x| InitVal { nodes: (x,) }), + map(symbol("1'b1"), |x| InitVal { nodes: (x,) }), + map(symbol("1'bx"), |x| InitVal { nodes: (x,) }), + map(symbol("1'bX"), |x| InitVal { nodes: (x,) }), + map(symbol("1'B0"), |x| InitVal { nodes: (x,) }), + map(symbol("1'B1"), |x| InitVal { nodes: (x,) }), + map(symbol("1'Bx"), |x| InitVal { nodes: (x,) }), + map(symbol("1'BX"), |x| InitVal { nodes: (x,) }), + map(symbol("1"), |x| InitVal { nodes: (x,) }), + map(symbol("0"), |x| InitVal { nodes: (x,) }), + ))(s) +} + +#[parser] +pub fn sequential_entry(s: Span) -> IResult { + let (s, a) = seq_input_list(s)?; + let (s, b) = symbol(":")(s)?; + let (s, c) = current_state(s)?; + let (s, d) = symbol(":")(s)?; + let (s, e) = next_state(s)?; + let (s, f) = symbol(";")(s)?; + Ok(( + s, + SequentialEntry { + nodes: (a, b, c, d, e, f), + }, + )) +} + +#[parser] +pub fn seq_input_list(s: Span) -> IResult { + alt(( + map(level_input_list, |x| SeqInputList::LevelInputList(x)), + map(edge_input_list, |x| SeqInputList::EdgeInputList(x)), + ))(s) +} + +#[parser] +pub fn level_input_list(s: Span) -> IResult { + let (s, a) = level_symbol(s)?; + let (s, b) = many0(level_symbol)(s)?; + Ok((s, LevelInputList { nodes: (a, b) })) +} + +#[parser] +pub fn edge_input_list(s: Span) -> IResult { + let (s, a) = many0(level_symbol)(s)?; + let (s, b) = edge_indicator(s)?; + let (s, c) = many0(level_symbol)(s)?; + Ok((s, EdgeInputList { nodes: (a, b, c) })) +} + +#[parser] +pub fn edge_indicator(s: Span) -> IResult { + alt(( + edge_indicator_paren, + map(edge_symbol, |x| EdgeIndicator::EdgeSymbol(x)), + ))(s) +} + +#[parser] +pub fn edge_indicator_paren(s: Span) -> IResult { + let (s, a) = paren(pair(level_symbol, level_symbol))(s)?; + Ok((s, EdgeIndicator::Paren(EdgeIndicatorParen { nodes: (a,) }))) +} + +#[parser] +pub fn current_state(s: Span) -> IResult { + let (s, a) = level_symbol(s)?; + Ok((s, CurrentState { nodes: (a,) })) +} + +#[parser] +pub fn next_state(s: Span) -> IResult { + alt(( + map(output_symbol, |x| NextState::OutputSymbol(x)), + map(symbol("-"), |x| NextState::Minus(x)), + ))(s) +} + +#[parser] +pub fn output_symbol(s: Span) -> IResult { + alt(( + map(symbol("0"), |x| OutputSymbol { nodes: (x,) }), + map(symbol("1"), |x| OutputSymbol { nodes: (x,) }), + map(symbol("x"), |x| OutputSymbol { nodes: (x,) }), + map(symbol("X"), |x| OutputSymbol { nodes: (x,) }), + ))(s) +} + +#[parser] +pub fn level_symbol(s: Span) -> IResult { + alt(( + map(symbol("0"), |x| LevelSymbol { nodes: (x,) }), + map(symbol("1"), |x| LevelSymbol { nodes: (x,) }), + map(symbol("x"), |x| LevelSymbol { nodes: (x,) }), + map(symbol("X"), |x| LevelSymbol { nodes: (x,) }), + map(symbol("?"), |x| LevelSymbol { nodes: (x,) }), + map(symbol("b"), |x| LevelSymbol { nodes: (x,) }), + map(symbol("B"), |x| LevelSymbol { nodes: (x,) }), + ))(s) +} + +#[parser] +pub fn edge_symbol(s: Span) -> IResult { + alt(( + map(symbol("r"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("R"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("f"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("F"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("p"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("P"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("n"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("N"), |x| EdgeSymbol { nodes: (x,) }), + map(symbol("*"), |x| EdgeSymbol { nodes: (x,) }), + ))(s) +} diff --git a/src/parser/udp_declaration_and_instantiation/udp_declaration.rs b/src/parser/udp_declaration_and_instantiation/udp_declaration.rs index ed4ee9c..f3956bb 100644 --- a/src/parser/udp_declaration_and_instantiation/udp_declaration.rs +++ b/src/parser/udp_declaration_and_instantiation/udp_declaration.rs @@ -1,20 +1,199 @@ use crate::ast::*; use crate::parser::*; -//use nom::branch::*; -//use nom::combinator::*; -use nom::error::*; -use nom::{Err, IResult}; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; // ----------------------------------------------------------------------------- #[derive(Debug, Node)] -pub struct UdpDeclaration<'a> { - pub nodes: (Identifier<'a>,), +pub struct UdpNonansiDeclaration<'a> { + pub nodes: ( + Vec>, + Symbol<'a>, + UdpIdentifier<'a>, + Paren<'a, UdpPortList<'a>>, + Symbol<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpAnsiDeclaration<'a> { + pub nodes: ( + Vec>, + Symbol<'a>, + UdpIdentifier<'a>, + Paren<'a, UdpDeclarationPortList<'a>>, + Symbol<'a>, + ), +} + +#[derive(Debug, Node)] +pub enum UdpDeclaration<'a> { + Nonansi(UdpDeclarationNonansi<'a>), + Ansi(UdpDeclarationAnsi<'a>), + ExternNonansi(UdpDeclarationExternNonansi<'a>), + ExternAnsi(UdpDeclarationExternAnsi<'a>), + Wildcard(UdpDeclarationWildcard<'a>), +} + +#[derive(Debug, Node)] +pub struct UdpDeclarationNonansi<'a> { + pub nodes: ( + UdpNonansiDeclaration<'a>, + UdpPortDeclaration<'a>, + Vec>, + UdpBody<'a>, + Symbol<'a>, + Option<(Symbol<'a>, UdpIdentifier<'a>)>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpDeclarationAnsi<'a> { + pub nodes: ( + UdpAnsiDeclaration<'a>, + UdpBody<'a>, + Symbol<'a>, + Option<(Symbol<'a>, UdpIdentifier<'a>)>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpDeclarationExternNonansi<'a> { + pub nodes: (Symbol<'a>, UdpNonansiDeclaration<'a>), +} + +#[derive(Debug, Node)] +pub struct UdpDeclarationExternAnsi<'a> { + pub nodes: (Symbol<'a>, UdpAnsiDeclaration<'a>), +} + +#[derive(Debug, Node)] +pub struct UdpDeclarationWildcard<'a> { + pub nodes: ( + Vec>, + Symbol<'a>, + UdpIdentifier<'a>, + Paren<'a, Symbol<'a>>, + Symbol<'a>, + Vec>, + UdpBody<'a>, + Symbol<'a>, + Option<(Symbol<'a>, UdpIdentifier<'a>)>, + ), } // ----------------------------------------------------------------------------- #[parser] -pub fn udp_declaration(s: Span) -> IResult { - Err(Err::Error(make_error(s, ErrorKind::Fix))) +pub fn udp_nonansi_declaration(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("primitive")(s)?; + let (s, c) = udp_identifier(s)?; + let (s, d) = paren(udp_port_list)(s)?; + let (s, e) = symbol(";")(s)?; + Ok(( + s, + UdpNonansiDeclaration { + nodes: (a, b, c, d, e), + }, + )) +} + +#[parser] +pub fn udp_ansi_declaration(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("primitive")(s)?; + let (s, c) = udp_identifier(s)?; + let (s, d) = paren(udp_declaration_port_list)(s)?; + let (s, e) = symbol(";")(s)?; + Ok(( + s, + UdpAnsiDeclaration { + nodes: (a, b, c, d, e), + }, + )) +} + +#[parser] +pub fn udp_declaration(s: Span) -> IResult { + alt(( + udp_declaration_nonansi, + udp_declaration_ansi, + udp_declaration_extern_nonansi, + udp_declaration_extern_ansi, + udp_declaration_wildcard, + ))(s) +} + +#[parser] +pub fn udp_declaration_nonansi(s: Span) -> IResult { + let (s, a) = udp_nonansi_declaration(s)?; + let (s, b) = udp_port_declaration(s)?; + let (s, c) = many0(udp_port_declaration)(s)?; + let (s, d) = udp_body(s)?; + let (s, e) = symbol("endprimitive")(s)?; + let (s, f) = opt(pair(symbol(":"), udp_identifier))(s)?; + Ok(( + s, + UdpDeclaration::Nonansi(UdpDeclarationNonansi { + nodes: (a, b, c, d, e, f), + }), + )) +} + +#[parser] +pub fn udp_declaration_ansi(s: Span) -> IResult { + let (s, a) = udp_ansi_declaration(s)?; + let (s, b) = udp_body(s)?; + let (s, c) = symbol("endprimitive")(s)?; + let (s, d) = opt(pair(symbol(":"), udp_identifier))(s)?; + Ok(( + s, + UdpDeclaration::Ansi(UdpDeclarationAnsi { + nodes: (a, b, c, d), + }), + )) +} + +#[parser] +pub fn udp_declaration_extern_nonansi(s: Span) -> IResult { + let (s, a) = symbol("extern")(s)?; + let (s, b) = udp_nonansi_declaration(s)?; + Ok(( + s, + UdpDeclaration::ExternNonansi(UdpDeclarationExternNonansi { nodes: (a, b) }), + )) +} + +#[parser] +pub fn udp_declaration_extern_ansi(s: Span) -> IResult { + let (s, a) = symbol("extern")(s)?; + let (s, b) = udp_ansi_declaration(s)?; + Ok(( + s, + UdpDeclaration::ExternAnsi(UdpDeclarationExternAnsi { nodes: (a, b) }), + )) +} + +#[parser] +pub fn udp_declaration_wildcard(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("primitive")(s)?; + let (s, c) = udp_identifier(s)?; + let (s, d) = paren(symbol(".*"))(s)?; + let (s, e) = symbol(";")(s)?; + let (s, f) = many0(udp_port_declaration)(s)?; + let (s, g) = udp_body(s)?; + let (s, h) = symbol("endprimitive")(s)?; + let (s, i) = opt(pair(symbol(":"), udp_identifier))(s)?; + Ok(( + s, + UdpDeclaration::Wildcard(UdpDeclarationWildcard { + nodes: (a, b, c, d, e, f, g, h, i), + }), + )) } diff --git a/src/parser/udp_declaration_and_instantiation/udp_ports.rs b/src/parser/udp_declaration_and_instantiation/udp_ports.rs new file mode 100644 index 0000000..ad11bd9 --- /dev/null +++ b/src/parser/udp_declaration_and_instantiation/udp_ports.rs @@ -0,0 +1,154 @@ +use crate::ast::*; +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug, Node)] +pub struct UdpPortList<'a> { + pub nodes: ( + OutputPortIdentifier<'a>, + Symbol<'a>, + List, InputPortIdentifier<'a>>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpDeclarationPortList<'a> { + pub nodes: ( + UdpOutputDeclaration<'a>, + Symbol<'a>, + List, UdpInputDeclaration<'a>>, + ), +} + +#[derive(Debug, Node)] +pub enum UdpPortDeclaration<'a> { + UdpOutputDeclaration((UdpOutputDeclaration<'a>, Symbol<'a>)), + UdpInputDeclaration((UdpInputDeclaration<'a>, Symbol<'a>)), + UdpRegDeclaration((UdpRegDeclaration<'a>, Symbol<'a>)), +} + +#[derive(Debug, Node)] +pub enum UdpOutputDeclaration<'a> { + Nonreg(UdpOutputDeclarationNonreg<'a>), + Reg(UdpOutputDeclarationReg<'a>), +} + +#[derive(Debug, Node)] +pub struct UdpOutputDeclarationNonreg<'a> { + pub nodes: (Vec>, Symbol<'a>, PortIdentifier<'a>), +} + +#[derive(Debug, Node)] +pub struct UdpOutputDeclarationReg<'a> { + pub nodes: ( + Vec>, + Symbol<'a>, + Symbol<'a>, + PortIdentifier<'a>, + Option<(Symbol<'a>, ConstantExpression<'a>)>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpInputDeclaration<'a> { + pub nodes: ( + Vec>, + Symbol<'a>, + ListOfUdpPortIdentifiers<'a>, + ), +} + +#[derive(Debug, Node)] +pub struct UdpRegDeclaration<'a> { + pub nodes: ( + Vec>, + Symbol<'a>, + VariableIdentifier<'a>, + ), +} + +// ----------------------------------------------------------------------------- + +#[parser] +pub fn udp_port_list(s: Span) -> IResult { + let (s, a) = output_port_identifier(s)?; + let (s, b) = symbol(",")(s)?; + let (s, c) = list(symbol(","), input_port_identifier)(s)?; + Ok((s, UdpPortList { nodes: (a, b, c) })) +} + +#[parser] +pub fn udp_declaration_port_list(s: Span) -> IResult { + let (s, a) = udp_output_declaration(s)?; + let (s, b) = symbol(",")(s)?; + let (s, c) = list(symbol(","), udp_input_declaration)(s)?; + Ok((s, UdpDeclarationPortList { nodes: (a, b, c) })) +} + +#[parser] +pub fn udp_port_declaration(s: Span) -> IResult { + alt(( + map(pair(udp_output_declaration, symbol(";")), |x| { + UdpPortDeclaration::UdpOutputDeclaration(x) + }), + map(pair(udp_input_declaration, symbol(";")), |x| { + UdpPortDeclaration::UdpInputDeclaration(x) + }), + map(pair(udp_reg_declaration, symbol(";")), |x| { + UdpPortDeclaration::UdpRegDeclaration(x) + }), + ))(s) +} + +#[parser] +pub fn udp_output_declaration(s: Span) -> IResult { + alt((udp_output_declaration_nonreg, udp_output_declaration_reg))(s) +} + +#[parser] +pub fn udp_output_declaration_nonreg(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("output")(s)?; + let (s, c) = port_identifier(s)?; + Ok(( + s, + UdpOutputDeclaration::Nonreg(UdpOutputDeclarationNonreg { nodes: (a, b, c) }), + )) +} + +#[parser] +pub fn udp_output_declaration_reg(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("output")(s)?; + let (s, c) = symbol("reg")(s)?; + let (s, d) = port_identifier(s)?; + let (s, e) = opt(pair(symbol("="), constant_expression))(s)?; + Ok(( + s, + UdpOutputDeclaration::Reg(UdpOutputDeclarationReg { + nodes: (a, b, c, d, e), + }), + )) +} + +#[parser] +pub fn udp_input_declaration(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("input")(s)?; + let (s, c) = list_of_udp_port_identifiers(s)?; + Ok((s, UdpInputDeclaration { nodes: (a, b, c) })) +} + +#[parser] +pub fn udp_reg_declaration(s: Span) -> IResult { + let (s, a) = many0(attribute_instance)(s)?; + let (s, b) = symbol("reg")(s)?; + let (s, c) = variable_identifier(s)?; + Ok((s, UdpRegDeclaration { nodes: (a, b, c) })) +}