diff --git a/src/parser/behavioral_statements/assertion_statements.rs b/src/parser/behavioral_statements/assertion_statements.rs new file mode 100644 index 0000000..a755430 --- /dev/null +++ b/src/parser/behavioral_statements/assertion_statements.rs @@ -0,0 +1,282 @@ +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub enum AssertionItem<'a> { + Concurrent(ConcurrentAssertionItem<'a>), + Immediate(DeferredImmediateAssetionItem<'a>), +} + +#[derive(Debug)] +pub struct DeferredImmediateAssetionItem<'a> { + pub identifier: Option>, + pub statement: DeferredImmediateAssertionStatement<'a>, +} + +#[derive(Debug)] +pub enum ProceduralAssertionStatement<'a> { + Concurrent(ConcurrentAssertionStatement<'a>), + Immediate(ImmediateAssetionStatement<'a>), + Checker(CheckerInstantiation<'a>), +} + +#[derive(Debug)] +pub enum ImmediateAssetionStatement<'a> { + Simple(SimpleImmediateAssertionStatement<'a>), + Deferred(DeferredImmediateAssertionStatement<'a>), +} + +#[derive(Debug)] +pub enum SimpleImmediateAssertionStatement<'a> { + Assert(SimpleImmediateAssertStatement<'a>), + Assume(SimpleImmediateAssumeStatement<'a>), + Cover(SimpleImmediateCoverStatement<'a>), +} + +#[derive(Debug)] +pub struct SimpleImmediateAssertStatement<'a> { + pub expression: Expression<'a>, + pub block: ActionBlock<'a>, +} + +#[derive(Debug)] +pub struct SimpleImmediateAssumeStatement<'a> { + pub expression: Expression<'a>, + pub block: ActionBlock<'a>, +} + +#[derive(Debug)] +pub struct SimpleImmediateCoverStatement<'a> { + pub expression: Expression<'a>, + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub enum DeferredImmediateAssertionStatement<'a> { + Assert(DeferredImmediateAssertStatement<'a>), + Assume(DeferredImmediateAssumeStatement<'a>), + Cover(DeferredImmediateCoverStatement<'a>), +} + +#[derive(Debug)] +pub struct DeferredImmediateAssertStatement<'a> { + pub timing: AssertTiming, + pub expression: Expression<'a>, + pub block: ActionBlock<'a>, +} + +#[derive(Debug)] +pub struct DeferredImmediateAssumeStatement<'a> { + pub timing: AssertTiming, + pub expression: Expression<'a>, + pub block: ActionBlock<'a>, +} + +#[derive(Debug)] +pub struct DeferredImmediateCoverStatement<'a> { + pub timing: AssertTiming, + pub expression: Expression<'a>, + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub enum AssertTiming { + Zero, + Final, +} + +// ----------------------------------------------------------------------------- + +pub fn assertion_item(s: &str) -> IResult<&str, AssertionItem> { + alt(( + map(concurrent_assertion_item, |x| AssertionItem::Concurrent(x)), + map(deferred_immediate_assertion_item, |x| { + AssertionItem::Immediate(x) + }), + ))(s) +} + +pub fn deferred_immediate_assertion_item(s: &str) -> IResult<&str, DeferredImmediateAssetionItem> { + let (s, x) = opt(terminated(block_identifier, symbol(":")))(s)?; + let (s, y) = deferred_immediate_assertion_statement(s)?; + Ok(( + s, + DeferredImmediateAssetionItem { + identifier: x, + statement: y, + }, + )) +} + +pub fn procedural_assertion_statement(s: &str) -> IResult<&str, ProceduralAssertionStatement> { + alt(( + map(concurrent_assertion_statement, |x| { + ProceduralAssertionStatement::Concurrent(x) + }), + map(immediate_assertion_statement, |x| { + ProceduralAssertionStatement::Immediate(x) + }), + map(checker_instantiation, |x| { + ProceduralAssertionStatement::Checker(x) + }), + ))(s) +} + +pub fn immediate_assertion_statement(s: &str) -> IResult<&str, ImmediateAssetionStatement> { + alt(( + map(simple_immediate_assertion_statement, |x| { + ImmediateAssetionStatement::Simple(x) + }), + map(deferred_immediate_assertion_statement, |x| { + ImmediateAssetionStatement::Deferred(x) + }), + ))(s) +} + +pub fn simple_immediate_assertion_statement( + s: &str, +) -> IResult<&str, SimpleImmediateAssertionStatement> { + alt(( + map(simple_immediate_assert_statement, |x| { + SimpleImmediateAssertionStatement::Assert(x) + }), + map(simple_immediate_assume_statement, |x| { + SimpleImmediateAssertionStatement::Assume(x) + }), + map(simple_immediate_cover_statement, |x| { + SimpleImmediateAssertionStatement::Cover(x) + }), + ))(s) +} + +pub fn simple_immediate_assert_statement(s: &str) -> IResult<&str, SimpleImmediateAssertStatement> { + let (s, _) = symbol("assert")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, y) = action_block(s)?; + Ok(( + s, + SimpleImmediateAssertStatement { + expression: x, + block: y, + }, + )) +} + +pub fn simple_immediate_assume_statement(s: &str) -> IResult<&str, SimpleImmediateAssumeStatement> { + let (s, _) = symbol("assume")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, y) = action_block(s)?; + Ok(( + s, + SimpleImmediateAssumeStatement { + expression: x, + block: y, + }, + )) +} + +pub fn simple_immediate_cover_statement(s: &str) -> IResult<&str, SimpleImmediateCoverStatement> { + let (s, _) = symbol("cover")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, y) = statement_or_null(s)?; + Ok(( + s, + SimpleImmediateCoverStatement { + expression: x, + statement: y, + }, + )) +} + +pub fn deferred_immediate_assertion_statement( + s: &str, +) -> IResult<&str, DeferredImmediateAssertionStatement> { + alt(( + map(deferred_immediate_assert_statement, |x| { + DeferredImmediateAssertionStatement::Assert(x) + }), + map(deferred_immediate_assume_statement, |x| { + DeferredImmediateAssertionStatement::Assume(x) + }), + map(deferred_immediate_cover_statement, |x| { + DeferredImmediateAssertionStatement::Cover(x) + }), + ))(s) +} + +pub fn deferred_immediate_assert_statement( + s: &str, +) -> IResult<&str, DeferredImmediateAssertStatement> { + let (s, _) = symbol("assert")(s)?; + let (s, x) = assert_timing(s)?; + let (s, _) = symbol("(")(s)?; + let (s, y) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, z) = action_block(s)?; + Ok(( + s, + DeferredImmediateAssertStatement { + timing: x, + expression: y, + block: z, + }, + )) +} + +pub fn deferred_immediate_assume_statement( + s: &str, +) -> IResult<&str, DeferredImmediateAssumeStatement> { + let (s, _) = symbol("assume")(s)?; + let (s, x) = assert_timing(s)?; + let (s, _) = symbol("(")(s)?; + let (s, y) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, z) = action_block(s)?; + Ok(( + s, + DeferredImmediateAssumeStatement { + timing: x, + expression: y, + block: z, + }, + )) +} + +pub fn deferred_immediate_cover_statement( + s: &str, +) -> IResult<&str, DeferredImmediateCoverStatement> { + let (s, _) = symbol("cover")(s)?; + let (s, x) = assert_timing(s)?; + let (s, _) = symbol("(")(s)?; + let (s, y) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, z) = statement_or_null(s)?; + Ok(( + s, + DeferredImmediateCoverStatement { + timing: x, + expression: y, + statement: z, + }, + )) +} + +pub fn assert_timing(s: &str) -> IResult<&str, AssertTiming> { + alt(( + map(symbol("#0"), |_| AssertTiming::Zero), + map(symbol("final"), |_| AssertTiming::Final), + ))(s) +} + +// ----------------------------------------------------------------------------- diff --git a/src/parser/behavioral_statements/clocking_block.rs b/src/parser/behavioral_statements/clocking_block.rs new file mode 100644 index 0000000..344ae0a --- /dev/null +++ b/src/parser/behavioral_statements/clocking_block.rs @@ -0,0 +1,331 @@ +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub enum ClockingDeclaration<'a> { + Local(ClockingDeclarationLocal<'a>), + Global(ClockingDeclarationGlobal<'a>), +} + +#[derive(Debug)] +pub struct ClockingDeclarationLocal<'a> { + pub default: bool, + pub beg_identifier: Option>, + pub event: ClockingEvent<'a>, + pub item: Vec>, + pub end_identifier: Option>, +} + +#[derive(Debug)] +pub struct ClockingDeclarationGlobal<'a> { + pub beg_identifier: Option>, + pub event: ClockingEvent<'a>, + pub end_identifier: Option>, +} + +#[derive(Debug)] +pub enum ClockingEvent<'a> { + Identifier(Identifier<'a>), + Expression(EventExpression<'a>), +} + +#[derive(Debug)] +pub enum ClockingItem<'a> { + DefaultSkew(DefaultSkew<'a>), + Direction(ClockingItemDirection<'a>), + Assertion(ClockingItemAssertion<'a>), +} + +#[derive(Debug)] +pub struct ClockingItemDirection<'a> { + pub direction: ClockingDirection<'a>, + pub assign: Vec>, +} + +#[derive(Debug)] +pub struct ClockingItemAssertion<'a> { + pub attribute: Vec>, + pub declaration: AssertionItemDeclaration<'a>, +} + +#[derive(Debug)] +pub enum DefaultSkew<'a> { + Input(ClockingSkew<'a>), + Output(ClockingSkew<'a>), + InputOutput((ClockingSkew<'a>, ClockingSkew<'a>)), +} + +#[derive(Debug)] +pub enum ClockingDirection<'a> { + Input(Option>), + Output(Option>), + InputOutput((Option>, Option>)), + Inout, +} + +#[derive(Debug)] +pub struct ClockingDeclAssign<'a> { + pub identifier: Identifier<'a>, + pub expression: Option>, +} + +#[derive(Debug)] +pub enum ClockingSkew<'a> { + Edge((EdgeIdentifier<'a>, Option>)), + Delay(DelayControl<'a>), +} + +#[derive(Debug)] +pub struct ClockingDrive<'a> { + pub lvalue: (HierarchicalIdentifier<'a>, Select<'a>), + pub cycle_delay: Option>, + pub rvalue: Expression<'a>, +} + +#[derive(Debug)] +pub enum CycleDelay<'a> { + Number(Number<'a>), + Identifier(Identifier<'a>), + Expression(Expression<'a>), +} + +// ----------------------------------------------------------------------------- + +pub fn clocking_declaration(s: &str) -> IResult<&str, ClockingDeclaration> { + alt((clocking_declaration_local, clocking_declaration_global))(s) +} + +pub fn clocking_declaration_local(s: &str) -> IResult<&str, ClockingDeclaration> { + let (s, x) = opt(symbol("default"))(s)?; + let (s, _) = symbol("clocking")(s)?; + let (s, y) = opt(clocking_identifier)(s)?; + let (s, z) = clocking_event(s)?; + let (s, _) = symbol(";")(s)?; + let (s, v) = many0(clocking_item)(s)?; + let (s, _) = symbol("endclocking")(s)?; + let (s, w) = opt(preceded(symbol(":"), clocking_identifier))(s)?; + Ok(( + s, + ClockingDeclaration::Local(ClockingDeclarationLocal { + default: x.is_some(), + beg_identifier: y, + event: z, + item: v, + end_identifier: w, + }), + )) +} + +pub fn clocking_declaration_global(s: &str) -> IResult<&str, ClockingDeclaration> { + let (s, _) = opt(symbol("global"))(s)?; + let (s, _) = symbol("clocking")(s)?; + let (s, x) = opt(clocking_identifier)(s)?; + let (s, y) = clocking_event(s)?; + let (s, _) = symbol(";")(s)?; + let (s, _) = symbol("endclocking")(s)?; + let (s, z) = opt(preceded(symbol(":"), clocking_identifier))(s)?; + Ok(( + s, + ClockingDeclaration::Global(ClockingDeclarationGlobal { + beg_identifier: x, + event: y, + end_identifier: z, + }), + )) +} + +pub fn clocking_event(s: &str) -> IResult<&str, ClockingEvent> { + alt(( + map(preceded(symbol("@"), identifier), |x| { + ClockingEvent::Identifier(x) + }), + map( + preceded( + symbol("@"), + delimited(symbol("("), event_expression, symbol(")")), + ), + |x| ClockingEvent::Expression(x), + ), + ))(s) +} + +pub fn clocking_item(s: &str) -> IResult<&str, ClockingItem> { + alt(( + clocking_item_default_skew, + clocking_item_direction, + clocking_item_assertion, + ))(s) +} + +pub fn clocking_item_default_skew(s: &str) -> IResult<&str, ClockingItem> { + let (s, _) = symbol("default")(s)?; + let (s, x) = default_skew(s)?; + let (s, _) = symbol(";")(s)?; + Ok((s, ClockingItem::DefaultSkew(x))) +} + +pub fn clocking_item_direction(s: &str) -> IResult<&str, ClockingItem> { + let (s, x) = clocking_direction(s)?; + let (s, y) = list_of_clocking_decl_assign(s)?; + Ok(( + s, + ClockingItem::Direction(ClockingItemDirection { + direction: x, + assign: y, + }), + )) +} + +pub fn clocking_item_assertion(s: &str) -> IResult<&str, ClockingItem> { + let (s, x) = many0(attribute_instance)(s)?; + let (s, y) = assertion_item_declaration(s)?; + Ok(( + s, + ClockingItem::Assertion(ClockingItemAssertion { + attribute: x, + declaration: y, + }), + )) +} + +pub fn default_skew(s: &str) -> IResult<&str, DefaultSkew> { + alt(( + default_skew_input, + default_skew_output, + default_skew_input_output, + ))(s) +} + +pub fn default_skew_input(s: &str) -> IResult<&str, DefaultSkew> { + let (s, _) = symbol("input")(s)?; + let (s, x) = clocking_skew(s)?; + Ok((s, DefaultSkew::Input(x))) +} + +pub fn default_skew_output(s: &str) -> IResult<&str, DefaultSkew> { + let (s, _) = symbol("output")(s)?; + let (s, x) = clocking_skew(s)?; + Ok((s, DefaultSkew::Output(x))) +} + +pub fn default_skew_input_output(s: &str) -> IResult<&str, DefaultSkew> { + let (s, _) = symbol("input")(s)?; + let (s, x) = clocking_skew(s)?; + let (s, _) = symbol("output")(s)?; + let (s, y) = clocking_skew(s)?; + Ok((s, DefaultSkew::InputOutput((x, y)))) +} + +pub fn clocking_direction(s: &str) -> IResult<&str, ClockingDirection> { + alt(( + clocking_direction_input, + clocking_direction_output, + clocking_direction_input_output, + clocking_direction_inout, + ))(s) +} + +pub fn clocking_direction_input(s: &str) -> IResult<&str, ClockingDirection> { + let (s, _) = symbol("input")(s)?; + let (s, x) = opt(clocking_skew)(s)?; + Ok((s, ClockingDirection::Input(x))) +} + +pub fn clocking_direction_output(s: &str) -> IResult<&str, ClockingDirection> { + let (s, _) = symbol("output")(s)?; + let (s, x) = opt(clocking_skew)(s)?; + Ok((s, ClockingDirection::Output(x))) +} + +pub fn clocking_direction_input_output(s: &str) -> IResult<&str, ClockingDirection> { + let (s, _) = symbol("input")(s)?; + let (s, x) = opt(clocking_skew)(s)?; + let (s, _) = symbol("output")(s)?; + let (s, y) = opt(clocking_skew)(s)?; + Ok((s, ClockingDirection::InputOutput((x, y)))) +} + +pub fn clocking_direction_inout(s: &str) -> IResult<&str, ClockingDirection> { + let (s, _) = symbol("inout")(s)?; + Ok((s, ClockingDirection::Inout)) +} + +pub fn list_of_clocking_decl_assign(s: &str) -> IResult<&str, Vec> { + many1(clocking_decl_assign)(s) +} + +pub fn clocking_decl_assign(s: &str) -> IResult<&str, ClockingDeclAssign> { + let (s, x) = signal_identifier(s)?; + let (s, y) = opt(preceded(symbol("="), expression))(s)?; + Ok(( + s, + ClockingDeclAssign { + identifier: x, + expression: y, + }, + )) +} + +pub fn clocking_skew(s: &str) -> IResult<&str, ClockingSkew> { + alt((clocking_skew_edge, clocking_skew_delay))(s) +} + +pub fn clocking_skew_edge(s: &str) -> IResult<&str, ClockingSkew> { + let (s, x) = edge_identifier(s)?; + let (s, y) = opt(delay_control)(s)?; + Ok((s, ClockingSkew::Edge((x, y)))) +} + +pub fn clocking_skew_delay(s: &str) -> IResult<&str, ClockingSkew> { + let (s, x) = delay_control(s)?; + Ok((s, ClockingSkew::Delay(x))) +} + +pub fn clocking_drive(s: &str) -> IResult<&str, ClockingDrive> { + let (s, x) = clockvar_expression(s)?; + let (s, _) = symbol("=")(s)?; + let (s, y) = opt(cycle_delay)(s)?; + let (s, z) = expression(s)?; + Ok(( + s, + ClockingDrive { + lvalue: x, + cycle_delay: y, + rvalue: z, + }, + )) +} + +pub fn cycle_delay(s: &str) -> IResult<&str, CycleDelay> { + alt(( + map(preceded(symbol("##"), integral_number), |x| { + CycleDelay::Number(x) + }), + map(preceded(symbol("##"), identifier), |x| { + CycleDelay::Identifier(x) + }), + map( + preceded( + symbol("##"), + delimited(symbol("("), expression, symbol(")")), + ), + |x| CycleDelay::Expression(x), + ), + ))(s) +} + +pub fn clockvar(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn clockvar_expression(s: &str) -> IResult<&str, (HierarchicalIdentifier, Select)> { + pair(clockvar, select)(s) +} + +// ----------------------------------------------------------------------------- diff --git a/src/parser/behavioral_statements/continuous_assignment_and_net_alias_statements.rs b/src/parser/behavioral_statements/continuous_assignment_and_net_alias_statements.rs index cbb2876..637ad8f 100644 --- a/src/parser/behavioral_statements/continuous_assignment_and_net_alias_statements.rs +++ b/src/parser/behavioral_statements/continuous_assignment_and_net_alias_statements.rs @@ -45,9 +45,11 @@ pub fn continuous_assign(s: &str) -> IResult<&str, ContinuousAssign> { } pub fn continuous_assign_net(s: &str) -> IResult<&str, ContinuousAssign> { + let (s, _) = symbol("assign")(s)?; let (s, x) = opt(drive_strength)(s)?; let (s, y) = opt(delay3)(s)?; - let (s, z) = many1(net_assignment)(s)?; + let (s, z) = list_of_net_assignments(s)?; + let (s, _) = symbol(";")(s)?; Ok(( s, @@ -60,8 +62,10 @@ pub fn continuous_assign_net(s: &str) -> IResult<&str, ContinuousAssign> { } pub fn continuous_assign_variable(s: &str) -> IResult<&str, ContinuousAssign> { + let (s, _) = symbol("assign")(s)?; let (s, x) = opt(delay_control)(s)?; - let (s, y) = many1(variable_assignment)(s)?; + let (s, y) = list_of_variable_assignments(s)?; + let (s, _) = symbol(";")(s)?; Ok(( s, @@ -72,6 +76,14 @@ pub fn continuous_assign_variable(s: &str) -> IResult<&str, ContinuousAssign> { )) } +pub fn list_of_net_assignments(s: &str) -> IResult<&str, Vec> { + separated_nonempty_list(symbol(","), net_assignment)(s) +} + +pub fn list_of_variable_assignments(s: &str) -> IResult<&str, Vec> { + separated_nonempty_list(symbol(","), variable_assignment)(s) +} + pub fn net_alias(s: &str) -> IResult<&str, NetAlias> { let (s, _) = symbol("alias")(s)?; let (s, x) = net_lvalue(s)?; diff --git a/src/parser/behavioral_statements/looping_statements.rs b/src/parser/behavioral_statements/looping_statements.rs new file mode 100644 index 0000000..dea2462 --- /dev/null +++ b/src/parser/behavioral_statements/looping_statements.rs @@ -0,0 +1,234 @@ +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub enum LoopStatement<'a> { + Forever(LoopStatementForever<'a>), + Repeat(LoopStatementRepeat<'a>), + While(LoopStatementWhile<'a>), + For(LoopStatementFor<'a>), + DoWhile(LoopStatementDoWhile<'a>), + Foreach(LoopStatementForeach<'a>), +} + +#[derive(Debug)] +pub struct LoopStatementForever<'a> { + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub struct LoopStatementRepeat<'a> { + pub expression: Expression<'a>, + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub struct LoopStatementWhile<'a> { + pub expression: Expression<'a>, + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub struct LoopStatementFor<'a> { + pub initilization: Option>, + pub expression: Option>, + pub step: Option>>, + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub struct LoopStatementDoWhile<'a> { + pub statement: StatementOrNull<'a>, + pub expression: Expression<'a>, +} + +#[derive(Debug)] +pub struct LoopStatementForeach<'a> { + pub identifier: ScopedIdentifier<'a>, + pub variable: Vec>>, + pub statement: Statement<'a>, +} + +#[derive(Debug)] +pub enum ForInitialization<'a> { + Assignment(Vec>), + Declaration(Vec>), +} + +#[derive(Debug)] +pub struct ForVariableDeclaration<'a> { + pub var: bool, + pub r#type: DataType<'a>, + pub declaration: Vec<(Identifier<'a>, Expression<'a>)>, +} + +#[derive(Debug)] +pub enum ForStepAssignment<'a> { + Operator(OperatorAssignment<'a>), + IncOrDec(IncOrDecDeclaration<'a>), + Subroutine(SubroutineCall<'a>), +} + +// ----------------------------------------------------------------------------- + +pub fn loop_statement(s: &str) -> IResult<&str, LoopStatement> { + alt(( + loop_statement_forever, + loop_statement_repeat, + loop_statement_while, + loop_statement_for, + loop_statement_do_while, + loop_statement_foreach, + ))(s) +} + +pub fn loop_statement_forever(s: &str) -> IResult<&str, LoopStatement> { + let (s, _) = symbol("forever")(s)?; + let (s, x) = statement_or_null(s)?; + Ok(( + s, + LoopStatement::Forever(LoopStatementForever { statement: x }), + )) +} + +pub fn loop_statement_repeat(s: &str) -> IResult<&str, LoopStatement> { + let (s, _) = symbol("repeat")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, y) = statement_or_null(s)?; + Ok(( + s, + LoopStatement::Repeat(LoopStatementRepeat { + expression: x, + statement: y, + }), + )) +} + +pub fn loop_statement_while(s: &str) -> IResult<&str, LoopStatement> { + let (s, _) = symbol("while")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, y) = statement_or_null(s)?; + Ok(( + s, + LoopStatement::While(LoopStatementWhile { + expression: x, + statement: y, + }), + )) +} + +pub fn loop_statement_for(s: &str) -> IResult<&str, LoopStatement> { + let (s, _) = symbol("for")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = opt(for_initialization)(s)?; + let (s, _) = symbol(";")(s)?; + let (s, y) = opt(expression)(s)?; + let (s, _) = symbol(";")(s)?; + let (s, z) = opt(for_step)(s)?; + let (s, _) = symbol(")")(s)?; + let (s, v) = statement_or_null(s)?; + Ok(( + s, + LoopStatement::For(LoopStatementFor { + initilization: x, + expression: y, + step: z, + statement: v, + }), + )) +} + +pub fn loop_statement_do_while(s: &str) -> IResult<&str, LoopStatement> { + let (s, _) = symbol("do")(s)?; + let (s, x) = statement_or_null(s)?; + let (s, _) = symbol("while")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, y) = expression(s)?; + let (s, _) = symbol(")")(s)?; + let (s, _) = symbol(";")(s)?; + Ok(( + s, + LoopStatement::DoWhile(LoopStatementDoWhile { + statement: x, + expression: y, + }), + )) +} + +pub fn loop_statement_foreach(s: &str) -> IResult<&str, LoopStatement> { + let (s, _) = symbol("foreach")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = ps_or_hierarchical_array_identifier(s)?; + let (s, _) = symbol("[")(s)?; + let (s, y) = loop_variables(s)?; + let (s, _) = symbol("]")(s)?; + let (s, _) = symbol(")")(s)?; + let (s, z) = statement(s)?; + Ok(( + s, + LoopStatement::Foreach(LoopStatementForeach { + identifier: x, + variable: y, + statement: z, + }), + )) +} + +pub fn for_initialization(s: &str) -> IResult<&str, ForInitialization> { + alt(( + map(list_of_variable_assignments, |x| { + ForInitialization::Assignment(x) + }), + map( + separated_nonempty_list(symbol(","), for_variable_declaration), + |x| ForInitialization::Declaration(x), + ), + ))(s) +} + +pub fn for_variable_declaration(s: &str) -> IResult<&str, ForVariableDeclaration> { + let (s, x) = opt(symbol("var"))(s)?; + let (s, y) = data_type(s)?; + let (s, z) = separated_nonempty_list( + symbol(","), + pair(variable_identifier, preceded(symbol("="), expression)), + )(s)?; + Ok(( + s, + ForVariableDeclaration { + var: x.is_some(), + r#type: y, + declaration: z, + }, + )) +} + +pub fn for_step(s: &str) -> IResult<&str, Vec> { + separated_nonempty_list(symbol(","), for_step_assignment)(s) +} + +pub fn for_step_assignment(s: &str) -> IResult<&str, ForStepAssignment> { + alt(( + map(operator_assignment, |x| ForStepAssignment::Operator(x)), + map(inc_or_dec_declaration, |x| ForStepAssignment::IncOrDec(x)), + map(function_subroutine_call, |x| { + ForStepAssignment::Subroutine(x) + }), + ))(s) +} + +pub fn loop_variables(s: &str) -> IResult<&str, Vec>> { + separated_nonempty_list(symbol(","), opt(index_variable_identifier))(s) +} + +// ----------------------------------------------------------------------------- diff --git a/src/parser/behavioral_statements/mod.rs b/src/parser/behavioral_statements/mod.rs index 4f4ef5c..223aae4 100644 --- a/src/parser/behavioral_statements/mod.rs +++ b/src/parser/behavioral_statements/mod.rs @@ -1,16 +1,26 @@ +pub mod assertion_statements; pub mod case_statements; +pub mod clocking_block; pub mod conditional_statements; pub mod continuous_assignment_and_net_alias_statements; +pub mod looping_statements; pub mod parallel_and_sequential_blocks; pub mod patterns; pub mod procedural_blocks_and_assignments; +pub mod randsequence; pub mod statements; +pub mod subroutine_call_statements; pub mod timing_control_statements; +pub use assertion_statements::*; pub use case_statements::*; +pub use clocking_block::*; pub use conditional_statements::*; pub use continuous_assignment_and_net_alias_statements::*; +pub use looping_statements::*; pub use parallel_and_sequential_blocks::*; pub use patterns::*; pub use procedural_blocks_and_assignments::*; +pub use randsequence::*; pub use statements::*; +pub use subroutine_call_statements::*; pub use timing_control_statements::*; diff --git a/src/parser/behavioral_statements/randsequence.rs b/src/parser/behavioral_statements/randsequence.rs new file mode 100644 index 0000000..69bc2ae --- /dev/null +++ b/src/parser/behavioral_statements/randsequence.rs @@ -0,0 +1,293 @@ +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub struct RandsequenceStatement<'a> { + pub identifier: Option>, + pub production: Vec>, +} + +#[derive(Debug)] +pub struct Production<'a> { + pub r#type: Option>, + pub identifier: Identifier<'a>, + pub tf_port_list: Option>, + pub rs_rule: Vec>, +} + +#[derive(Debug)] +pub struct RsRule<'a> { + pub production: RsProductionList<'a>, + pub weight: Option>, + pub block: Option>, +} + +#[derive(Debug)] +pub enum RsProductionList<'a> { + Prod(Vec>), + Join((Option>, Vec>)), +} + +#[derive(Debug)] +pub enum WeightSpecification<'a> { + Number(Number<'a>), + Identifier(ScopedIdentifier<'a>), + Expression(Expression<'a>), +} + +#[derive(Debug)] +pub struct RsCodeBlock<'a> { + pub declaration: Vec>, + pub statement: Vec>, +} + +#[derive(Debug)] +pub enum RsProd<'a> { + Item(ProductionItem<'a>), + CodeBlock(RsCodeBlock<'a>), + IfElse(RsIfElse<'a>), + Repeat(RsRepeat<'a>), + Case(RsCase<'a>), +} + +#[derive(Debug)] +pub struct ProductionItem<'a> { + pub identifier: Identifier<'a>, + pub argument: Option>, +} + +#[derive(Debug)] +pub struct RsIfElse<'a> { + pub expression: Expression<'a>, + pub item: ProductionItem<'a>, + pub else_item: Option>, +} + +#[derive(Debug)] +pub struct RsRepeat<'a> { + pub expression: Expression<'a>, + pub item: ProductionItem<'a>, +} + +#[derive(Debug)] +pub struct RsCase<'a> { + pub expression: Expression<'a>, + pub item: Vec>, +} + +#[derive(Debug)] +pub enum RsCaseItem<'a> { + NonDefault(RsCaseItemNondefault<'a>), + Default(RsCaseItemDefault<'a>), +} + +#[derive(Debug)] +pub struct RsCaseItemDefault<'a> { + pub item: ProductionItem<'a>, +} + +#[derive(Debug)] +pub struct RsCaseItemNondefault<'a> { + pub expression: Vec>, + pub item: ProductionItem<'a>, +} + +// ----------------------------------------------------------------------------- + +pub fn randsequence_statement(s: &str) -> IResult<&str, RandsequenceStatement> { + let (s, _) = symbol("randsequence")(s)?; + let (s, _) = symbol("(")(s)?; + let (s, x) = opt(production_identifier)(s)?; + let (s, _) = symbol(")")(s)?; + let (s, y) = many1(production)(s)?; + let (s, _) = symbol("endsequence")(s)?; + Ok(( + s, + RandsequenceStatement { + identifier: x, + production: y, + }, + )) +} + +pub fn production(s: &str) -> IResult<&str, Production> { + let (s, x) = opt(data_type_or_void)(s)?; + let (s, y) = production_identifier(s)?; + let (s, z) = opt(delimited(symbol("("), tf_port_list, symbol(")")))(s)?; + let (s, _) = symbol(":")(s)?; + let (s, v) = separated_nonempty_list(symbol("|"), rs_rule)(s)?; + let (s, _) = symbol(";")(s)?; + Ok(( + s, + Production { + r#type: x, + identifier: y, + tf_port_list: z, + rs_rule: v, + }, + )) +} + +pub fn rs_rule(s: &str) -> IResult<&str, RsRule> { + let (s, x) = rs_production_list(s)?; + let (s, y) = opt(preceded( + symbol(":="), + pair(weight_specification, opt(rs_code_block)), + ))(s)?; + + let (y, z) = if let Some((y, z)) = y { + (Some(y), z) + } else { + (None, None) + }; + Ok(( + s, + RsRule { + production: x, + weight: y, + block: z, + }, + )) +} + +pub fn rs_production_list(s: &str) -> IResult<&str, RsProductionList> { + alt((rs_production_list_prod, rs_production_list_join))(s) +} + +pub fn rs_production_list_prod(s: &str) -> IResult<&str, RsProductionList> { + let (s, x) = many1(rs_prod)(s)?; + Ok((s, RsProductionList::Prod(x))) +} + +pub fn rs_production_list_join(s: &str) -> IResult<&str, RsProductionList> { + let (s, _) = symbol("rand")(s)?; + let (s, _) = symbol("join")(s)?; + let (s, x) = opt(delimited(symbol("("), expression, symbol(")")))(s)?; + let (s, y) = production_item(s)?; + let (s, z) = many1(production_item)(s)?; + + let mut y = vec![y]; + for z in z { + y.push(z); + } + Ok((s, RsProductionList::Join((x, y)))) +} + +pub fn weight_specification(s: &str) -> IResult<&str, WeightSpecification> { + alt(( + map(integral_number, |x| WeightSpecification::Number(x)), + map(ps_identifier, |x| WeightSpecification::Identifier(x)), + map(delimited(symbol("("), expression, symbol(")")), |x| { + WeightSpecification::Expression(x) + }), + ))(s) +} + +pub fn rs_code_block(s: &str) -> IResult<&str, RsCodeBlock> { + let (s, _) = symbol("{")(s)?; + let (s, x) = many0(data_declaration)(s)?; + let (s, y) = many0(statement_or_null)(s)?; + let (s, _) = symbol("}")(s)?; + Ok(( + s, + RsCodeBlock { + declaration: x, + statement: y, + }, + )) +} + +pub fn rs_prod(s: &str) -> IResult<&str, RsProd> { + alt(( + map(production_item, |x| RsProd::Item(x)), + map(rs_code_block, |x| RsProd::CodeBlock(x)), + map(rs_if_else, |x| RsProd::IfElse(x)), + map(rs_repeat, |x| RsProd::Repeat(x)), + map(rs_case, |x| RsProd::Case(x)), + ))(s) +} + +pub fn production_item(s: &str) -> IResult<&str, ProductionItem> { + let (s, x) = production_identifier(s)?; + let (s, y) = opt(delimited(symbol("("), list_of_arguments, symbol(")")))(s)?; + Ok(( + s, + ProductionItem { + identifier: x, + argument: y, + }, + )) +} + +pub fn rs_if_else(s: &str) -> IResult<&str, RsIfElse> { + let (s, _) = symbol("if")(s)?; + let (s, x) = delimited(symbol("("), expression, symbol(")"))(s)?; + let (s, y) = production_item(s)?; + let (s, z) = opt(preceded(symbol("else"), production_item))(s)?; + Ok(( + s, + RsIfElse { + expression: x, + item: y, + else_item: z, + }, + )) +} + +pub fn rs_repeat(s: &str) -> IResult<&str, RsRepeat> { + let (s, _) = symbol("repeat")(s)?; + let (s, x) = delimited(symbol("("), expression, symbol(")"))(s)?; + let (s, y) = production_item(s)?; + Ok(( + s, + RsRepeat { + expression: x, + item: y, + }, + )) +} + +pub fn rs_case(s: &str) -> IResult<&str, RsCase> { + let (s, _) = symbol("case")(s)?; + let (s, x) = delimited(symbol("("), case_expression, symbol(")"))(s)?; + let (s, y) = many1(rs_case_item)(s)?; + Ok(( + s, + RsCase { + expression: x, + item: y, + }, + )) +} + +pub fn rs_case_item(s: &str) -> IResult<&str, RsCaseItem> { + alt((rs_case_item_nondefault, rs_case_item_default))(s) +} + +pub fn rs_case_item_nondefault(s: &str) -> IResult<&str, RsCaseItem> { + let (s, x) = separated_nonempty_list(symbol(","), case_item_expression)(s)?; + let (s, _) = symbol(":")(s)?; + let (s, y) = production_item(s)?; + let (s, _) = symbol(";")(s)?; + Ok(( + s, + RsCaseItem::NonDefault(RsCaseItemNondefault { + expression: x, + item: y, + }), + )) +} + +pub fn rs_case_item_default(s: &str) -> IResult<&str, RsCaseItem> { + let (s, _) = symbol("default")(s)?; + let (s, _) = opt(symbol(":"))(s)?; + let (s, x) = production_item(s)?; + let (s, _) = symbol(";")(s)?; + Ok((s, RsCaseItem::Default(RsCaseItemDefault { item: x }))) +} diff --git a/src/parser/behavioral_statements/subroutine_call_statements.rs b/src/parser/behavioral_statements/subroutine_call_statements.rs new file mode 100644 index 0000000..8673549 --- /dev/null +++ b/src/parser/behavioral_statements/subroutine_call_statements.rs @@ -0,0 +1,33 @@ +use crate::parser::*; +use nom::branch::*; +use nom::combinator::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub enum SubroutineCallStatement<'a> { + SubroutineCall(SubroutineCall<'a>), + FunctionSubroutineCall(SubroutineCall<'a>), +} + +// ----------------------------------------------------------------------------- + +pub fn subroutine_call_statement(s: &str) -> IResult<&str, SubroutineCallStatement> { + alt(( + map(terminated(subroutine_call, symbol(";")), |x| { + SubroutineCallStatement::SubroutineCall(x) + }), + map( + delimited( + tuple((symbol("void"), symbol("'"), symbol("("))), + function_subroutine_call, + pair(symbol(")"), symbol(";")), + ), + |x| SubroutineCallStatement::FunctionSubroutineCall(x), + ), + ))(s) +} + +// ----------------------------------------------------------------------------- diff --git a/src/parser/utils.rs b/src/parser/utils.rs index ff6baa9..8761ac5 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -48,11 +48,6 @@ pub struct DataType<'a> { pub raw: Vec<&'a str>, } -#[derive(Debug)] -pub struct ClockingEvent<'a> { - pub raw: Vec<&'a str>, -} - #[derive(Debug)] pub struct ConstraintBlock<'a> { pub raw: Vec<&'a str>, @@ -88,31 +83,6 @@ pub struct BlockItemDeclaration<'a> { pub raw: Vec<&'a str>, } -#[derive(Debug)] -pub struct SubroutineCallStatement<'a> { - pub raw: Vec<&'a str>, -} - -#[derive(Debug)] -pub struct LoopStatement<'a> { - pub raw: Vec<&'a str>, -} - -#[derive(Debug)] -pub struct ProceduralAssertionStatement<'a> { - pub raw: Vec<&'a str>, -} - -#[derive(Debug)] -pub struct ClockingDrive<'a> { - pub raw: Vec<&'a str>, -} - -#[derive(Debug)] -pub struct RandsequenceStatement<'a> { - pub raw: Vec<&'a str>, -} - #[derive(Debug)] pub struct ExpectPropertyStatement<'a> { pub raw: Vec<&'a str>, @@ -128,11 +98,6 @@ pub struct DelayValue<'a> { pub raw: Vec<&'a str>, } -#[derive(Debug)] -pub struct CycleDelay<'a> { - pub raw: Vec<&'a str>, -} - #[derive(Debug)] pub struct EdgeIdentifier<'a> { pub raw: Vec<&'a str>, @@ -143,6 +108,46 @@ pub struct IntegerAtomType<'a> { pub raw: Vec<&'a str>, } +#[derive(Debug)] +pub struct IncOrDecDeclaration<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct ConcurrentAssertionItem<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct ConcurrentAssertionStatement<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct CheckerInstantiation<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct AssertionItemDeclaration<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct DataTypeOrVoid<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct TfPortList<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct DataDeclaration<'a> { + pub raw: Vec<&'a str>, +} + pub fn class_scope(s: &str) -> IResult<&str, Scope> { Ok((s, Scope::ClassScope)) } @@ -167,10 +172,6 @@ pub fn data_type(s: &str) -> IResult<&str, DataType> { Ok((s, DataType { raw: vec![] })) } -pub fn clocking_event(s: &str) -> IResult<&str, ClockingEvent> { - Ok((s, ClockingEvent { raw: vec![] })) -} - pub fn constraint_block(s: &str) -> IResult<&str, ConstraintBlock> { Ok((s, ConstraintBlock { raw: vec![] })) } @@ -203,26 +204,6 @@ pub fn block_item_declaration(s: &str) -> IResult<&str, BlockItemDeclaration> { Ok((s, BlockItemDeclaration { raw: vec![] })) } -pub fn subroutine_call_statement(s: &str) -> IResult<&str, SubroutineCallStatement> { - Ok((s, SubroutineCallStatement { raw: vec![] })) -} - -pub fn loop_statement(s: &str) -> IResult<&str, LoopStatement> { - Ok((s, LoopStatement { raw: vec![] })) -} - -pub fn procedural_assertion_statement(s: &str) -> IResult<&str, ProceduralAssertionStatement> { - Ok((s, ProceduralAssertionStatement { raw: vec![] })) -} - -pub fn clocking_drive(s: &str) -> IResult<&str, ClockingDrive> { - Ok((s, ClockingDrive { raw: vec![] })) -} - -pub fn randsequence_statement(s: &str) -> IResult<&str, RandsequenceStatement> { - Ok((s, RandsequenceStatement { raw: vec![] })) -} - pub fn expect_property_statement(s: &str) -> IResult<&str, ExpectPropertyStatement> { Ok((s, ExpectPropertyStatement { raw: vec![] })) } @@ -235,10 +216,6 @@ pub fn delay_value(s: &str) -> IResult<&str, DelayValue> { Ok((s, DelayValue { raw: vec![] })) } -pub fn cycle_delay(s: &str) -> IResult<&str, CycleDelay> { - Ok((s, CycleDelay { raw: vec![] })) -} - pub fn edge_identifier(s: &str) -> IResult<&str, EdgeIdentifier> { Ok((s, EdgeIdentifier { raw: vec![] })) } @@ -246,3 +223,35 @@ pub fn edge_identifier(s: &str) -> IResult<&str, EdgeIdentifier> { pub fn integer_atom_type(s: &str) -> IResult<&str, IntegerAtomType> { Ok((s, IntegerAtomType { raw: vec![] })) } + +pub fn inc_or_dec_declaration(s: &str) -> IResult<&str, IncOrDecDeclaration> { + Ok((s, IncOrDecDeclaration { raw: vec![] })) +} + +pub fn concurrent_assertion_item(s: &str) -> IResult<&str, ConcurrentAssertionItem> { + Ok((s, ConcurrentAssertionItem { raw: vec![] })) +} + +pub fn concurrent_assertion_statement(s: &str) -> IResult<&str, ConcurrentAssertionStatement> { + Ok((s, ConcurrentAssertionStatement { raw: vec![] })) +} + +pub fn checker_instantiation(s: &str) -> IResult<&str, CheckerInstantiation> { + Ok((s, CheckerInstantiation { raw: vec![] })) +} + +pub fn assertion_item_declaration(s: &str) -> IResult<&str, AssertionItemDeclaration> { + Ok((s, AssertionItemDeclaration { raw: vec![] })) +} + +pub fn data_type_or_void(s: &str) -> IResult<&str, DataTypeOrVoid> { + Ok((s, DataTypeOrVoid { raw: vec![] })) +} + +pub fn tf_port_list(s: &str) -> IResult<&str, TfPortList> { + Ok((s, TfPortList { raw: vec![] })) +} + +pub fn data_declaration(s: &str) -> IResult<&str, DataDeclaration> { + Ok((s, DataDeclaration { raw: vec![] })) +}