Add parser
This commit is contained in:
parent
ecb89f691f
commit
4a2cc5416c
25
README.md
25
README.md
@ -41,9 +41,9 @@ A parser library for System Verilog.
|
|||||||
| instantiations | program_instantiation | x | x | |
|
| instantiations | program_instantiation | x | x | |
|
||||||
| instantiations | checker_instantiation | x | x | |
|
| instantiations | checker_instantiation | x | x | |
|
||||||
| instantiations | generated_instantiation | x | x | |
|
| instantiations | generated_instantiation | x | x | |
|
||||||
| udp_declaration_and_instantiation | udp_declaration | | | |
|
| udp_declaration_and_instantiation | udp_declaration | x | x | |
|
||||||
| udp_declaration_and_instantiation | udp_ports | | | |
|
| udp_declaration_and_instantiation | udp_ports | x | x | |
|
||||||
| udp_declaration_and_instantiation | udp_body | | | |
|
| udp_declaration_and_instantiation | udp_body | x | x | |
|
||||||
| udp_declaration_and_instantiation | udp_instantiation | x | x | |
|
| udp_declaration_and_instantiation | udp_instantiation | x | x | |
|
||||||
| behavioral_statements | continuous_assignment_and_net_alias | x | x | |
|
| behavioral_statements | continuous_assignment_and_net_alias | x | x | |
|
||||||
| behavioral_statements | procedural_blocks_and_assignments | 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 | assertion_statements | x | x | |
|
||||||
| behavioral_statements | clocking_block | x | x | |
|
| behavioral_statements | clocking_block | x | x | |
|
||||||
| behavioral_statements | randsequence | x | x | |
|
| behavioral_statements | randsequence | x | x | |
|
||||||
| specify_section | specify_block_declaration | | | |
|
| specify_section | specify_block_declaration | x | x | |
|
||||||
| specify_section | specify_path_declarations | | | |
|
| specify_section | specify_path_declarations | x | x | |
|
||||||
| specify_section | specify_block_terminals | | | |
|
| specify_section | specify_block_terminals | x | x | |
|
||||||
| specify_section | specify_path_delays | | | |
|
| specify_section | specify_path_delays | x | x | |
|
||||||
| specify_section | system_timing_check_commands | | | |
|
| specify_section | system_timing_check_commands | x | x | |
|
||||||
| specify_section | system_timing_check_command_arguments | | | |
|
| specify_section | system_timing_check_command_arguments | x | x | |
|
||||||
| specify_section | system_timing_check_event_definitions | | | |
|
| specify_section | system_timing_check_event_definitions | x | x | |
|
||||||
| expressions | concatenations | x | x | |
|
| expressions | concatenations | x | x | |
|
||||||
| expressions | subroutine_calls | x | x | |
|
| expressions | subroutine_calls | x | x | |
|
||||||
| expressions | expressions | x | x | |
|
| expressions | expressions | x | x | |
|
||||||
@ -76,3 +76,8 @@ A parser library for System Verilog.
|
|||||||
| general | attributes | x | x | x |
|
| general | attributes | x | x | x |
|
||||||
| general | comments | x | x | x |
|
| general | comments | x | x | x |
|
||||||
| general | identifiers | x | x | x |
|
| general | identifiers | x | x | x |
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
* Exclude reserved keyword from identifiers.
|
||||||
|
* Implement ambiguous_alt for varirble_port_type.
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
pub mod specify_block_declaration;
|
pub mod specify_block_declaration;
|
||||||
pub mod specify_block_terminals;
|
pub mod specify_block_terminals;
|
||||||
|
pub mod specify_path_declarations;
|
||||||
pub mod specify_path_delays;
|
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_declaration::*;
|
||||||
pub use specify_block_terminals::*;
|
pub use specify_block_terminals::*;
|
||||||
|
pub use specify_path_declarations::*;
|
||||||
pub use specify_path_delays::*;
|
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::*;
|
||||||
|
@ -1,20 +1,75 @@
|
|||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::parser::*;
|
use crate::parser::*;
|
||||||
//use nom::branch::*;
|
use nom::branch::*;
|
||||||
//use nom::combinator::*;
|
use nom::combinator::*;
|
||||||
use nom::error::*;
|
use nom::multi::*;
|
||||||
use nom::{Err, IResult};
|
use nom::IResult;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct SpecifyBlock<'a> {
|
pub struct SpecifyBlock<'a> {
|
||||||
pub nodes: (Identifier<'a>,),
|
pub nodes: (Symbol<'a>, Vec<SpecifyItem<'a>>, 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]
|
#[parser]
|
||||||
pub fn specify_block(s: Span) -> IResult<Span, SpecifyBlock> {
|
pub fn specify_block(s: Span) -> IResult<Span, SpecifyBlock> {
|
||||||
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<Span, SpecifyItem> {
|
||||||
|
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<Span, PulsestyleDeclaration> {
|
||||||
|
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<Span, ShowcancelledDeclaration> {
|
||||||
|
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) }))
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::parser::*;
|
use crate::parser::*;
|
||||||
//use nom::branch::*;
|
use nom::branch::*;
|
||||||
//use nom::combinator::*;
|
use nom::combinator::*;
|
||||||
use nom::error::*;
|
use nom::IResult;
|
||||||
use nom::{Err, IResult};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct SpecifyInputTerminalDescriptor<'a> {
|
pub struct SpecifyInputTerminalDescriptor<'a> {
|
||||||
pub nodes: (InputIdentifier<'a>, Option<ConstantRangeExpression<'a>>),
|
pub nodes: (
|
||||||
|
InputIdentifier<'a>,
|
||||||
|
Option<Bracket<'a, ConstantRangeExpression<'a>>>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct SpecifyOutputTerminalDescriptor<'a> {
|
pub struct SpecifyOutputTerminalDescriptor<'a> {
|
||||||
pub nodes: (OutputIdentifier<'a>, Option<ConstantRangeExpression<'a>>),
|
pub nodes: (
|
||||||
|
OutputIdentifier<'a>,
|
||||||
|
Option<Bracket<'a, ConstantRangeExpression<'a>>>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
@ -26,7 +31,7 @@ pub enum InputIdentifier<'a> {
|
|||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct InputIdentifierInterface<'a> {
|
pub struct InputIdentifierInterface<'a> {
|
||||||
pub nodes: (InterfaceIdentifier<'a>, PortIdentifier<'a>),
|
pub nodes: (InterfaceIdentifier<'a>, Symbol<'a>, PortIdentifier<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
@ -38,29 +43,71 @@ pub enum OutputIdentifier<'a> {
|
|||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct OutputIdentifierInterface<'a> {
|
pub struct OutputIdentifierInterface<'a> {
|
||||||
pub nodes: (InterfaceIdentifier<'a>, PortIdentifier<'a>),
|
pub nodes: (InterfaceIdentifier<'a>, Symbol<'a>, PortIdentifier<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[parser]
|
#[parser]
|
||||||
pub fn specify_input_terminal_descriptor(s: Span) -> IResult<Span, SpecifyInputTerminalDescriptor> {
|
pub fn specify_input_terminal_descriptor(s: Span) -> IResult<Span, SpecifyInputTerminalDescriptor> {
|
||||||
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]
|
#[parser]
|
||||||
pub fn specify_output_terminal_descriptor(
|
pub fn specify_output_terminal_descriptor(
|
||||||
s: Span,
|
s: Span,
|
||||||
) -> IResult<Span, SpecifyOutputTerminalDescriptor> {
|
) -> IResult<Span, SpecifyOutputTerminalDescriptor> {
|
||||||
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]
|
#[parser]
|
||||||
pub fn input_identifier(s: Span) -> IResult<Span, InputIdentifier> {
|
pub fn input_identifier(s: Span) -> IResult<Span, InputIdentifier> {
|
||||||
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<Span, InputIdentifier> {
|
||||||
|
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]
|
#[parser]
|
||||||
pub fn output_identifier(s: Span) -> IResult<Span, OutputIdentifier> {
|
pub fn output_identifier(s: Span) -> IResult<Span, OutputIdentifier> {
|
||||||
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<Span, OutputIdentifier> {
|
||||||
|
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) }),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
152
src/parser/specify_section/specify_path_declarations.rs
Normal file
152
src/parser/specify_section/specify_path_declarations.rs
Normal file
@ -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<PolarityOperator<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
SpecifyOutputTerminalDescriptor<'a>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct FullPathDescription<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Paren<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
ListOfPathInputs<'a>,
|
||||||
|
Option<PolarityOperator<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
ListOfPathOutputs<'a>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct ListOfPathInputs<'a> {
|
||||||
|
pub nodes: (List<Symbol<'a>, SpecifyInputTerminalDescriptor<'a>>,),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct ListOfPathOutputs<'a> {
|
||||||
|
pub nodes: (List<Symbol<'a>, SpecifyOutputTerminalDescriptor<'a>>,),
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn path_declaration(s: Span) -> IResult<Span, PathDeclaration> {
|
||||||
|
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<Span, SimplePathDeclaration> {
|
||||||
|
alt((
|
||||||
|
simple_path_declaration_parallel,
|
||||||
|
simple_path_declaration_full,
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn simple_path_declaration_parallel(s: Span) -> IResult<Span, SimplePathDeclaration> {
|
||||||
|
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<Span, SimplePathDeclaration> {
|
||||||
|
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<Span, ParallelPathDescription> {
|
||||||
|
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<Span, FullPathDescription> {
|
||||||
|
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<Span, ListOfPathInputs> {
|
||||||
|
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<Span, ListOfPathOutputs> {
|
||||||
|
let (s, a) = list(symbol(","), specify_output_terminal_descriptor)(s)?;
|
||||||
|
Ok((s, ListOfPathOutputs { nodes: (a,) }))
|
||||||
|
}
|
@ -1,20 +1,341 @@
|
|||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::parser::*;
|
use crate::parser::*;
|
||||||
//use nom::branch::*;
|
use nom::branch::*;
|
||||||
//use nom::combinator::*;
|
use nom::combinator::*;
|
||||||
use nom::error::*;
|
use nom::sequence::*;
|
||||||
use nom::{Err, IResult};
|
use nom::IResult;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct EdgeIdentifier<'a> {
|
pub enum PathDelayValue<'a> {
|
||||||
pub nodes: (Identifier<'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<Symbol<'a>, 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<EdgeIdentifier<'a>>,
|
||||||
|
SpecifyInputTerminalDescriptor<'a>,
|
||||||
|
Option<PolarityOperator<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
Paren<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
SpecifyOutputTerminalDescriptor<'a>,
|
||||||
|
Option<PolarityOperator<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
DataSourceExpression<'a>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct FullEdgeSensitivePathDescription<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Paren<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
Option<EdgeIdentifier<'a>>,
|
||||||
|
ListOfPathInputs<'a>,
|
||||||
|
Option<PolarityOperator<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
Paren<
|
||||||
|
'a,
|
||||||
|
(
|
||||||
|
ListOfPathOutputs<'a>,
|
||||||
|
Option<PolarityOperator<'a>>,
|
||||||
|
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]
|
#[parser]
|
||||||
pub fn edge_identifier(s: Span) -> IResult<Span, EdgeIdentifier> {
|
pub fn path_delay_value(s: Span) -> IResult<Span, PathDelayValue> {
|
||||||
Err(Err::Error(make_error(s, ErrorKind::Fix)))
|
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<Span, PathDelayValue> {
|
||||||
|
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<Span, ListOfPathDelayExpressions> {
|
||||||
|
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<Span, TPathDelayExpression> {
|
||||||
|
let (s, a) = path_delay_expression(s)?;
|
||||||
|
Ok((s, TPathDelayExpression { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn path_delay_expression(s: Span) -> IResult<Span, PathDelayExpression> {
|
||||||
|
let (s, a) = constant_mintypmax_expression(s)?;
|
||||||
|
Ok((s, PathDelayExpression { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn edge_sensitive_path_declaration(s: Span) -> IResult<Span, EdgeSensitivePathDeclaration> {
|
||||||
|
alt((
|
||||||
|
edge_sensitive_path_declaration_parallel,
|
||||||
|
edge_sensitive_path_declaration_full,
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn edge_sensitive_path_declaration_parallel(
|
||||||
|
s: Span,
|
||||||
|
) -> IResult<Span, EdgeSensitivePathDeclaration> {
|
||||||
|
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<Span, EdgeSensitivePathDeclaration> {
|
||||||
|
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<Span, ParallelEdgeSensitivePathDescription> {
|
||||||
|
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<Span, FullEdgeSensitivePathDescription> {
|
||||||
|
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<Span, DataSourceExpression> {
|
||||||
|
let (s, a) = expression(s)?;
|
||||||
|
Ok((s, DataSourceExpression { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn edge_identifier(s: Span) -> IResult<Span, EdgeIdentifier> {
|
||||||
|
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<Span, StateDependentPathDeclaration> {
|
||||||
|
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<Span, StateDependentPathDeclaration> {
|
||||||
|
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<Span, StateDependentPathDeclaration> {
|
||||||
|
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<Span, StateDependentPathDeclaration> {
|
||||||
|
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<Span, PolarityOperator> {
|
||||||
|
alt((
|
||||||
|
map(symbol("+"), |x| PolarityOperator { nodes: (x,) }),
|
||||||
|
map(symbol("-"), |x| PolarityOperator { nodes: (x,) }),
|
||||||
|
))(s)
|
||||||
}
|
}
|
||||||
|
@ -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<Span, TimecheckCondition> {
|
||||||
|
let (s, a) = mintypmax_expression(s)?;
|
||||||
|
Ok((s, TimecheckCondition { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn controlled_referecne_event(s: Span) -> IResult<Span, ControlledReferenceEvent> {
|
||||||
|
let (s, a) = controlled_timing_check_event(s)?;
|
||||||
|
Ok((s, ControlledReferenceEvent { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn data_event(s: Span) -> IResult<Span, DataEvent> {
|
||||||
|
let (s, a) = timing_check_event(s)?;
|
||||||
|
Ok((s, DataEvent { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn delayed_data(s: Span) -> IResult<Span, DelayedData> {
|
||||||
|
alt((
|
||||||
|
map(terminal_identifier, |x| DelayedData::TerminalIdentifier(x)),
|
||||||
|
delayed_data_with_mintypmax,
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn delayed_data_with_mintypmax(s: Span) -> IResult<Span, DelayedData> {
|
||||||
|
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<Span, DelayedReference> {
|
||||||
|
alt((
|
||||||
|
map(terminal_identifier, |x| {
|
||||||
|
DelayedReference::TerminalIdentifier(x)
|
||||||
|
}),
|
||||||
|
delayed_reference_with_mintypmax,
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn delayed_reference_with_mintypmax(s: Span) -> IResult<Span, DelayedReference> {
|
||||||
|
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<Span, EndEdgeOffset> {
|
||||||
|
let (s, a) = mintypmax_expression(s)?;
|
||||||
|
Ok((s, EndEdgeOffset { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn event_based_flag(s: Span) -> IResult<Span, EventBasedFlag> {
|
||||||
|
let (s, a) = constant_expression(s)?;
|
||||||
|
Ok((s, EventBasedFlag { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn notifier(s: Span) -> IResult<Span, Notifier> {
|
||||||
|
let (s, a) = variable_identifier(s)?;
|
||||||
|
Ok((s, Notifier { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn referecne_event(s: Span) -> IResult<Span, ReferenceEvent> {
|
||||||
|
let (s, a) = timing_check_event(s)?;
|
||||||
|
Ok((s, ReferenceEvent { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn remain_active_flag(s: Span) -> IResult<Span, RemainActiveFlag> {
|
||||||
|
let (s, a) = constant_mintypmax_expression(s)?;
|
||||||
|
Ok((s, RemainActiveFlag { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn timestamp_condition(s: Span) -> IResult<Span, TimestampCondition> {
|
||||||
|
let (s, a) = mintypmax_expression(s)?;
|
||||||
|
Ok((s, TimestampCondition { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn start_edge_offset(s: Span) -> IResult<Span, StartEdgeOffset> {
|
||||||
|
let (s, a) = mintypmax_expression(s)?;
|
||||||
|
Ok((s, StartEdgeOffset { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn threshold(s: Span) -> IResult<Span, Threshold> {
|
||||||
|
let (s, a) = constant_expression(s)?;
|
||||||
|
Ok((s, Threshold { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn timing_check_limit(s: Span) -> IResult<Span, TimingCheckLimit> {
|
||||||
|
let (s, a) = expression(s)?;
|
||||||
|
Ok((s, TimingCheckLimit { nodes: (a,) }))
|
||||||
|
}
|
580
src/parser/specify_section/system_timing_check_commands.rs
Normal file
580
src/parser/specify_section/system_timing_check_commands.rs
Normal file
@ -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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<TimestampCondition<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<TimecheckCondition<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<DelayedReference<'a>>,
|
||||||
|
Option<(Symbol<'a>, Option<DelayedData<'a>>)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<TimestampCondition<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<TimecheckCondition<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<DelayedReference<'a>>,
|
||||||
|
Option<(Symbol<'a>, Option<DelayedData<'a>>)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<EventBasedFlag<'a>>,
|
||||||
|
Option<(Symbol<'a>, Option<RemainActiveFlag<'a>>)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>,
|
||||||
|
Option<(
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<EventBasedFlag<'a>>,
|
||||||
|
Option<(Symbol<'a>, Option<RemainActiveFlag<'a>>)>,
|
||||||
|
)>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
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<Notifier<'a>>)>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
Symbol<'a>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn system_timing_check(s: Span) -> IResult<Span, SystemTimingCheck> {
|
||||||
|
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<Span, SetupTimingCheck> {
|
||||||
|
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<Span, HoldTimingCheck> {
|
||||||
|
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<Span, SetupholdTimingCheck> {
|
||||||
|
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<Span, RecoveryTimingCheck> {
|
||||||
|
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<Span, RemovalTimingCheck> {
|
||||||
|
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<Span, RecremTimingCheck> {
|
||||||
|
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<Span, SkewTimingCheck> {
|
||||||
|
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<Span, TimeskewTimingCheck> {
|
||||||
|
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<Span, FullskewTimingCheck> {
|
||||||
|
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<Span, PeriodTimingCheck> {
|
||||||
|
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<Span, WidthTimingCheck> {
|
||||||
|
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<Span, NochargeTimingCheck> {
|
||||||
|
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) }))
|
||||||
|
}
|
@ -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<TimingCheckEventControl<'a>>,
|
||||||
|
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<Symbol<'a>, 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<Span, TimingCheckEvent> {
|
||||||
|
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<Span, ControlledTimingCheckEvent> {
|
||||||
|
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<Span, TimingCheckEventControl> {
|
||||||
|
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<Span, SpecifyTerminalDescriptor> {
|
||||||
|
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<Span, EdgeControlSpecifier> {
|
||||||
|
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<Span, EdgeDescriptor> {
|
||||||
|
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<Span, TimingCheckCondition> {
|
||||||
|
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<Span, TimingCheckCondition> {
|
||||||
|
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<Span, ScalarTimingCheckCondition> {
|
||||||
|
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<Span, ScalarTimingCheckCondition> {
|
||||||
|
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<Span, ScalarTimingCheckCondition> {
|
||||||
|
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<Span, ScalarConstant> {
|
||||||
|
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)
|
||||||
|
}
|
@ -1,4 +1,8 @@
|
|||||||
|
pub mod udp_body;
|
||||||
pub mod udp_declaration;
|
pub mod udp_declaration;
|
||||||
pub mod udp_instantiation;
|
pub mod udp_instantiation;
|
||||||
|
pub mod udp_ports;
|
||||||
|
pub use udp_body::*;
|
||||||
pub use udp_declaration::*;
|
pub use udp_declaration::*;
|
||||||
pub use udp_instantiation::*;
|
pub use udp_instantiation::*;
|
||||||
|
pub use udp_ports::*;
|
||||||
|
315
src/parser/udp_declaration_and_instantiation/udp_body.rs
Normal file
315
src/parser/udp_declaration_and_instantiation/udp_body.rs
Normal file
@ -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<CombinationalEntry<'a>>,
|
||||||
|
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<UdpInitialStatement<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
SequentialEntry<'a>,
|
||||||
|
Vec<SequentialEntry<'a>>,
|
||||||
|
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<LevelSymbol<'a>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct EdgeInputList<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Vec<LevelSymbol<'a>>,
|
||||||
|
EdgeIndicator<'a>,
|
||||||
|
Vec<LevelSymbol<'a>>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<Span, UdpBody> {
|
||||||
|
alt((
|
||||||
|
map(combinational_body, |x| UdpBody::CombinationalBody(x)),
|
||||||
|
map(sequential_body, |x| UdpBody::SequentialBody(x)),
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn combinational_body(s: Span) -> IResult<Span, CombinationalBody> {
|
||||||
|
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<Span, CombinationalEntry> {
|
||||||
|
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<Span, SequentialBody> {
|
||||||
|
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<Span, UdpInitialStatement> {
|
||||||
|
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<Span, InitVal> {
|
||||||
|
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<Span, SequentialEntry> {
|
||||||
|
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<Span, SeqInputList> {
|
||||||
|
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<Span, LevelInputList> {
|
||||||
|
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<Span, EdgeInputList> {
|
||||||
|
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<Span, EdgeIndicator> {
|
||||||
|
alt((
|
||||||
|
edge_indicator_paren,
|
||||||
|
map(edge_symbol, |x| EdgeIndicator::EdgeSymbol(x)),
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn edge_indicator_paren(s: Span) -> IResult<Span, EdgeIndicator> {
|
||||||
|
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<Span, CurrentState> {
|
||||||
|
let (s, a) = level_symbol(s)?;
|
||||||
|
Ok((s, CurrentState { nodes: (a,) }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn next_state(s: Span) -> IResult<Span, NextState> {
|
||||||
|
alt((
|
||||||
|
map(output_symbol, |x| NextState::OutputSymbol(x)),
|
||||||
|
map(symbol("-"), |x| NextState::Minus(x)),
|
||||||
|
))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn output_symbol(s: Span) -> IResult<Span, OutputSymbol> {
|
||||||
|
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<Span, LevelSymbol> {
|
||||||
|
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<Span, EdgeSymbol> {
|
||||||
|
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)
|
||||||
|
}
|
@ -1,20 +1,199 @@
|
|||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::parser::*;
|
use crate::parser::*;
|
||||||
//use nom::branch::*;
|
use nom::branch::*;
|
||||||
//use nom::combinator::*;
|
use nom::combinator::*;
|
||||||
use nom::error::*;
|
use nom::multi::*;
|
||||||
use nom::{Err, IResult};
|
use nom::sequence::*;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug, Node)]
|
#[derive(Debug, Node)]
|
||||||
pub struct UdpDeclaration<'a> {
|
pub struct UdpNonansiDeclaration<'a> {
|
||||||
pub nodes: (Identifier<'a>,),
|
pub nodes: (
|
||||||
|
Vec<AttributeInstance<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
UdpIdentifier<'a>,
|
||||||
|
Paren<'a, UdpPortList<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct UdpAnsiDeclaration<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Vec<AttributeInstance<'a>>,
|
||||||
|
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<UdpPortDeclaration<'a>>,
|
||||||
|
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<AttributeInstance<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
UdpIdentifier<'a>,
|
||||||
|
Paren<'a, Symbol<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
Vec<UdpPortDeclaration<'a>>,
|
||||||
|
UdpBody<'a>,
|
||||||
|
Symbol<'a>,
|
||||||
|
Option<(Symbol<'a>, UdpIdentifier<'a>)>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[parser]
|
#[parser]
|
||||||
pub fn udp_declaration(s: Span) -> IResult<Span, UdpDeclaration> {
|
pub fn udp_nonansi_declaration(s: Span) -> IResult<Span, UdpNonansiDeclaration> {
|
||||||
Err(Err::Error(make_error(s, ErrorKind::Fix)))
|
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<Span, UdpAnsiDeclaration> {
|
||||||
|
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<Span, UdpDeclaration> {
|
||||||
|
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<Span, UdpDeclaration> {
|
||||||
|
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<Span, UdpDeclaration> {
|
||||||
|
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<Span, UdpDeclaration> {
|
||||||
|
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<Span, UdpDeclaration> {
|
||||||
|
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<Span, UdpDeclaration> {
|
||||||
|
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),
|
||||||
|
}),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
154
src/parser/udp_declaration_and_instantiation/udp_ports.rs
Normal file
154
src/parser/udp_declaration_and_instantiation/udp_ports.rs
Normal file
@ -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<Symbol<'a>, InputPortIdentifier<'a>>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct UdpDeclarationPortList<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
UdpOutputDeclaration<'a>,
|
||||||
|
Symbol<'a>,
|
||||||
|
List<Symbol<'a>, 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<AttributeInstance<'a>>, Symbol<'a>, PortIdentifier<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct UdpOutputDeclarationReg<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Vec<AttributeInstance<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
Symbol<'a>,
|
||||||
|
PortIdentifier<'a>,
|
||||||
|
Option<(Symbol<'a>, ConstantExpression<'a>)>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct UdpInputDeclaration<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Vec<AttributeInstance<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
ListOfUdpPortIdentifiers<'a>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Node)]
|
||||||
|
pub struct UdpRegDeclaration<'a> {
|
||||||
|
pub nodes: (
|
||||||
|
Vec<AttributeInstance<'a>>,
|
||||||
|
Symbol<'a>,
|
||||||
|
VariableIdentifier<'a>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn udp_port_list(s: Span) -> IResult<Span, UdpPortList> {
|
||||||
|
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<Span, UdpDeclarationPortList> {
|
||||||
|
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<Span, UdpPortDeclaration> {
|
||||||
|
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<Span, UdpOutputDeclaration> {
|
||||||
|
alt((udp_output_declaration_nonreg, udp_output_declaration_reg))(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[parser]
|
||||||
|
pub fn udp_output_declaration_nonreg(s: Span) -> IResult<Span, UdpOutputDeclaration> {
|
||||||
|
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<Span, UdpOutputDeclaration> {
|
||||||
|
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<Span, UdpInputDeclaration> {
|
||||||
|
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<Span, UdpRegDeclaration> {
|
||||||
|
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) }))
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user