diff --git a/src/blocks.rs b/src/blocks.rs new file mode 100644 index 0000000..b543416 --- /dev/null +++ b/src/blocks.rs @@ -0,0 +1,112 @@ +use crate::identifiers::*; +use crate::utils::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub enum ActionBlock<'a> { + Statement(StatementOrNull<'a>), + Else(ActionBlockElse<'a>), +} + +#[derive(Debug)] +pub struct ActionBlockElse<'a> { + pub statement: Option>, + pub else_statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub struct SeqBlock<'a> { + pub beg_identifier: Option>, + pub declaration: Vec>, + pub statement: Vec>, + pub end_identifier: Option>, +} + +#[derive(Debug)] +pub struct ParBlock<'a> { + pub beg_identifier: Option>, + pub declaration: Vec>, + pub statement: Vec>, + pub keyword: JoinKeyword, + pub end_identifier: Option>, +} + +#[derive(Debug)] +pub enum JoinKeyword { + Join, + JoinAny, + JoinNone, +} + +// ----------------------------------------------------------------------------- + +pub fn action_block(s: &str) -> IResult<&str, ActionBlock> { + alt(( + map(statement_or_null, |x| ActionBlock::Statement(x)), + action_block_else, + ))(s) +} + +pub fn action_block_else(s: &str) -> IResult<&str, ActionBlock> { + let (s, statement) = opt(statement)(s)?; + let (s, _) = symbol("else")(s)?; + let (s, else_statement) = statement_or_null(s)?; + Ok(( + s, + ActionBlock::Else(ActionBlockElse { + statement, + else_statement, + }), + )) +} + +pub fn seq_block(s: &str) -> IResult<&str, SeqBlock> { + let (s, _) = symbol("begin")(s)?; + let (s, beg_identifier) = opt(preceded(symbol(":"), block_identifier))(s)?; + let (s, declaration) = many0(block_item_declaration)(s)?; + let (s, statement) = many0(statement_or_null)(s)?; + let (s, _) = symbol("end")(s)?; + let (s, end_identifier) = opt(preceded(symbol(":"), block_identifier))(s)?; + Ok(( + s, + SeqBlock { + beg_identifier, + declaration, + statement, + end_identifier, + }, + )) +} + +pub fn par_block(s: &str) -> IResult<&str, ParBlock> { + let (s, _) = symbol("fork")(s)?; + let (s, beg_identifier) = opt(preceded(symbol(":"), block_identifier))(s)?; + let (s, declaration) = many0(block_item_declaration)(s)?; + let (s, statement) = many0(statement_or_null)(s)?; + let (s, keyword) = join_keyword(s)?; + let (s, end_identifier) = opt(preceded(symbol(":"), block_identifier))(s)?; + Ok(( + s, + ParBlock { + beg_identifier, + declaration, + statement, + keyword, + end_identifier, + }, + )) +} + +pub fn join_keyword(s: &str) -> IResult<&str, JoinKeyword> { + alt(( + map(symbol("join_any"), |_| JoinKeyword::JoinAny), + map(symbol("join_none"), |_| JoinKeyword::JoinNone), + map(symbol("join"), |_| JoinKeyword::Join), + ))(s) +} diff --git a/src/continuous_assignments.rs b/src/continuous_assignments.rs new file mode 100644 index 0000000..9f164da --- /dev/null +++ b/src/continuous_assignments.rs @@ -0,0 +1,92 @@ +use crate::expressions::*; +use crate::lvalues::*; +use crate::proceduals::*; +use crate::utils::*; +use nom::branch::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub enum ContinuousAssign<'a> { + Net(ContinuousAssignNet<'a>), + Variable(ContinuousAssignVariable<'a>), +} + +#[derive(Debug)] +pub struct ContinuousAssignNet<'a> { + pub drive_strength: Option>, + pub delay3: Option>, + pub list: Vec>, +} + +#[derive(Debug)] +pub struct ContinuousAssignVariable<'a> { + pub delay_control: Option>, + pub list: Vec>, +} + +#[derive(Debug)] +pub struct NetAlias<'a> { + pub lvalue: NetLvalue<'a>, + pub rvalue: Vec>, +} + +#[derive(Debug)] +pub struct NetAssignment<'a> { + pub lvalue: NetLvalue<'a>, + pub rvalue: Expression<'a>, +} + +// ----------------------------------------------------------------------------- + +pub fn continuous_assign(s: &str) -> IResult<&str, ContinuousAssign> { + alt((continuous_assign_net, continuous_assign_variable))(s) +} + +pub fn continuous_assign_net(s: &str) -> IResult<&str, ContinuousAssign> { + let (s, drive_strength) = opt(drive_strength)(s)?; + let (s, delay3) = opt(delay3)(s)?; + let (s, list) = many1(net_assignment)(s)?; + + Ok(( + s, + ContinuousAssign::Net(ContinuousAssignNet { + drive_strength, + delay3, + list, + }), + )) +} + +pub fn continuous_assign_variable(s: &str) -> IResult<&str, ContinuousAssign> { + let (s, delay_control) = opt(delay_control)(s)?; + let (s, list) = many1(variable_assignment)(s)?; + + Ok(( + s, + ContinuousAssign::Variable(ContinuousAssignVariable { + delay_control, + list, + }), + )) +} + +pub fn net_alias(s: &str) -> IResult<&str, NetAlias> { + let (s, _) = symbol("alias")(s)?; + let (s, lvalue) = net_lvalue(s)?; + let (s, rvalue) = many1(preceded(symbol("="), net_lvalue))(s)?; + + Ok((s, NetAlias { lvalue, rvalue })) +} + +pub fn net_assignment(s: &str) -> IResult<&str, NetAssignment> { + let (s, lvalue) = net_lvalue(s)?; + let (s, _) = symbol("=")(s)?; + let (s, rvalue) = expression(s)?; + + Ok((s, NetAssignment { lvalue, rvalue })) +} diff --git a/src/expressions.rs b/src/expressions.rs index e61314f..a3dd69e 100644 --- a/src/expressions.rs +++ b/src/expressions.rs @@ -3,6 +3,7 @@ use crate::identifiers::*; use crate::lvalues::*; use crate::operators::*; use crate::primaries::*; +use crate::proceduals::*; use crate::utils::*; use nom::branch::*; use nom::combinator::*; @@ -604,7 +605,6 @@ pub fn genvar_expression(s: &str) -> IResult<&str, ConstantExpression> { #[cfg(test)] mod tests { - use super::*; #[test] fn test() { diff --git a/src/lib.rs b/src/lib.rs index e196c66..5f21a44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,15 @@ pub mod attributes; +pub mod blocks; pub mod comments; pub mod concatenations; +pub mod continuous_assignments; pub mod expressions; pub mod identifiers; pub mod lvalues; pub mod numbers; pub mod operators; pub mod primaries; +pub mod proceduals; pub mod strings; pub mod subroutine_calls; pub mod utils; diff --git a/src/proceduals.rs b/src/proceduals.rs new file mode 100644 index 0000000..3fd446e --- /dev/null +++ b/src/proceduals.rs @@ -0,0 +1,257 @@ +use crate::continuous_assignments::*; +use crate::expressions::*; +use crate::identifiers::*; +use crate::lvalues::*; +use crate::operators::*; +use crate::primaries::*; +use crate::utils::*; +use nom::branch::*; +use nom::combinator::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub struct InitialConstruct<'a> { + pub statement: StatementOrNull<'a>, +} + +#[derive(Debug)] +pub struct AlwaysConstruct<'a> { + pub keyword: AlwaysKeyword, + pub statement: Statement<'a>, +} + +#[derive(Debug)] +pub enum AlwaysKeyword { + Always, + AlwaysComb, + AlwaysLatch, + AlwaysFf, +} + +#[derive(Debug)] +pub struct FinalConstruct<'a> { + pub statement: FunctionStatement<'a>, +} + +#[derive(Debug)] +pub enum BlockingAssignment<'a> { + Variable(BlockingAssignmentVariable<'a>), + NonrangeVariable(BlockingAssignmentNonrangeVariable<'a>), + HierarchicalVariable(BlockingAssignmentHierarchicalVariable<'a>), + Operator(OperatorAssignment<'a>), +} + +#[derive(Debug)] +pub struct BlockingAssignmentVariable<'a> { + pub lvalue: VariableLvalue<'a>, + pub control: DelayOrEventControl<'a>, + pub rvalue: Expression<'a>, +} + +#[derive(Debug)] +pub struct BlockingAssignmentNonrangeVariable<'a> { + pub lvalue: NonrangeVariableLvalue<'a>, + pub rvalue: DynamicArrayNew<'a>, +} + +#[derive(Debug)] +pub struct BlockingAssignmentHierarchicalVariable<'a> { + pub scope: Option>, + pub lvalue: HierarchicalIdentifier<'a>, + pub select: Select<'a>, + pub rvalue: ClassNew<'a>, +} + +#[derive(Debug)] +pub struct OperatorAssignment<'a> { + pub lvalue: VariableLvalue<'a>, + pub operator: Operator<'a>, + pub rvalue: Expression<'a>, +} + +#[derive(Debug)] +pub struct NonblockingAssignment<'a> { + pub lvalue: VariableLvalue<'a>, + pub control: Option>, + pub rvalue: Expression<'a>, +} + +#[derive(Debug)] +pub enum ProcedualContinuousAssignment<'a> { + Assign(VariableAssignment<'a>), + Deassign(VariableLvalue<'a>), + ForceVariable(VariableAssignment<'a>), + ForceNet(NetAssignment<'a>), + ReleaseVariable(VariableLvalue<'a>), + ReleaseNet(NetLvalue<'a>), +} + +#[derive(Debug)] +pub struct VariableAssignment<'a> { + pub lvalue: VariableLvalue<'a>, + pub rvalue: Expression<'a>, +} + +// ----------------------------------------------------------------------------- + +pub fn initial_construct(s: &str) -> IResult<&str, InitialConstruct> { + let (s, _) = symbol("initial")(s)?; + let (s, statement) = statement_or_null(s)?; + Ok((s, InitialConstruct { statement })) +} + +pub fn always_construct(s: &str) -> IResult<&str, AlwaysConstruct> { + let (s, keyword) = always_keyword(s)?; + let (s, statement) = statement(s)?; + Ok((s, AlwaysConstruct { keyword, statement })) +} + +pub fn always_keyword(s: &str) -> IResult<&str, AlwaysKeyword> { + alt(( + map(symbol("always_comb"), |_| AlwaysKeyword::AlwaysComb), + map(symbol("always_latch"), |_| AlwaysKeyword::AlwaysLatch), + map(symbol("always_ff"), |_| AlwaysKeyword::AlwaysFf), + map(symbol("always"), |_| AlwaysKeyword::Always), + ))(s) +} + +pub fn final_construct(s: &str) -> IResult<&str, FinalConstruct> { + let (s, _) = symbol("final")(s)?; + let (s, statement) = function_statement(s)?; + Ok((s, FinalConstruct { statement })) +} + +pub fn blocking_assignment(s: &str) -> IResult<&str, BlockingAssignment> { + alt(( + blocking_assignment_variable, + blocking_assignment_nonrange_variable, + blocking_assignment_hierarchical_variable, + map(operator_assignment, |x| BlockingAssignment::Operator(x)), + ))(s) +} + +pub fn blocking_assignment_variable(s: &str) -> IResult<&str, BlockingAssignment> { + let (s, lvalue) = variable_lvalue(s)?; + let (s, _) = symbol("=")(s)?; + let (s, control) = delay_or_event_control(s)?; + let (s, rvalue) = expression(s)?; + Ok(( + s, + BlockingAssignment::Variable(BlockingAssignmentVariable { + lvalue, + control, + rvalue, + }), + )) +} + +pub fn blocking_assignment_nonrange_variable(s: &str) -> IResult<&str, BlockingAssignment> { + let (s, lvalue) = nonrange_variable_lvalue(s)?; + let (s, _) = symbol("=")(s)?; + let (s, rvalue) = dynamic_array_new(s)?; + Ok(( + s, + BlockingAssignment::NonrangeVariable(BlockingAssignmentNonrangeVariable { lvalue, rvalue }), + )) +} + +pub fn blocking_assignment_hierarchical_variable(s: &str) -> IResult<&str, BlockingAssignment> { + let (s, scope) = opt(alt(( + terminated(implicit_class_handle, symbol(".")), + class_scope, + package_scope, + )))(s)?; + let (s, lvalue) = hierarchical_variable_identifier(s)?; + let (s, select) = select(s)?; + let (s, _) = symbol("=")(s)?; + let (s, rvalue) = class_new(s)?; + Ok(( + s, + BlockingAssignment::HierarchicalVariable(BlockingAssignmentHierarchicalVariable { + scope, + lvalue, + select, + rvalue, + }), + )) +} + +pub fn operator_assignment(s: &str) -> IResult<&str, OperatorAssignment> { + let (s, lvalue) = variable_lvalue(s)?; + let (s, operator) = assignment_operator(s)?; + let (s, rvalue) = expression(s)?; + Ok(( + s, + OperatorAssignment { + lvalue, + operator, + rvalue, + }, + )) +} + +pub fn assignment_operator(s: &str) -> IResult<&str, Operator> { + alt(( + map(symbol("="), |raw| Operator { raw }), + map(symbol("+="), |raw| Operator { raw }), + map(symbol("-="), |raw| Operator { raw }), + map(symbol("*="), |raw| Operator { raw }), + map(symbol("/="), |raw| Operator { raw }), + map(symbol("%="), |raw| Operator { raw }), + map(symbol("&="), |raw| Operator { raw }), + map(symbol("|="), |raw| Operator { raw }), + map(symbol("^="), |raw| Operator { raw }), + map(symbol("<<<="), |raw| Operator { raw }), + map(symbol(">>>="), |raw| Operator { raw }), + map(symbol("<<="), |raw| Operator { raw }), + map(symbol(">>="), |raw| Operator { raw }), + ))(s) +} + +pub fn nonblocking_assignment(s: &str) -> IResult<&str, NonblockingAssignment> { + let (s, lvalue) = variable_lvalue(s)?; + let (s, _) = symbol("<=")(s)?; + let (s, control) = opt(delay_or_event_control)(s)?; + let (s, rvalue) = expression(s)?; + Ok(( + s, + NonblockingAssignment { + lvalue, + control, + rvalue, + }, + )) +} + +pub fn procedual_continuous_assignment(s: &str) -> IResult<&str, ProcedualContinuousAssignment> { + alt(( + map(preceded(symbol("assign"), variable_assignment), |x| { + ProcedualContinuousAssignment::Assign(x) + }), + map(preceded(symbol("deassign"), variable_lvalue), |x| { + ProcedualContinuousAssignment::Deassign(x) + }), + map(preceded(symbol("force"), variable_assignment), |x| { + ProcedualContinuousAssignment::ForceVariable(x) + }), + map(preceded(symbol("force"), net_assignment), |x| { + ProcedualContinuousAssignment::ForceNet(x) + }), + map(preceded(symbol("release"), variable_lvalue), |x| { + ProcedualContinuousAssignment::ReleaseVariable(x) + }), + map(preceded(symbol("release"), net_lvalue), |x| { + ProcedualContinuousAssignment::ReleaseNet(x) + }), + ))(s) +} + +pub fn variable_assignment(s: &str) -> IResult<&str, VariableAssignment> { + let (s, lvalue) = variable_lvalue(s)?; + let (s, _) = symbol("=")(s)?; + let (s, rvalue) = expression(s)?; + Ok((s, VariableAssignment { lvalue, rvalue })) +} diff --git a/src/utils.rs b/src/utils.rs index b0dc7a3..72da946 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -78,11 +78,6 @@ pub struct DataType<'a> { pub raw: Vec<&'a str>, } -#[derive(Debug)] -pub struct OperatorAssignment<'a> { - pub raw: Vec<&'a str>, -} - #[derive(Debug)] pub struct OpenRangeList<'a> { pub raw: Vec<&'a str>, @@ -103,6 +98,56 @@ pub struct SimpleType<'a> { pub raw: Vec<&'a str>, } +#[derive(Debug)] +pub struct DriveStrength<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct Delay3<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct DelayControl<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct StatementOrNull<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct Statement<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct FunctionStatement<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct DelayOrEventControl<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct DynamicArrayNew<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct ClassNew<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct BlockItemDeclaration<'a> { + pub raw: Vec<&'a str>, +} + pub fn class_scope(s: &str) -> IResult<&str, Scope> { Ok((s, Scope::ClassScope)) } @@ -157,10 +202,6 @@ pub fn data_type(s: &str) -> IResult<&str, DataType> { Ok((s, DataType { raw: vec![] })) } -pub fn operator_assignment(s: &str) -> IResult<&str, OperatorAssignment> { - Ok((s, OperatorAssignment { raw: vec![] })) -} - pub fn open_range_list(s: &str) -> IResult<&str, OpenRangeList> { Ok((s, OpenRangeList { raw: vec![] })) } @@ -184,3 +225,43 @@ pub fn identifier_list(s: &str) -> IResult<&str, Vec> { pub fn simple_type(s: &str) -> IResult<&str, SimpleType> { Ok((s, SimpleType { raw: vec![] })) } + +pub fn drive_strength(s: &str) -> IResult<&str, DriveStrength> { + Ok((s, DriveStrength { raw: vec![] })) +} + +pub fn delay3(s: &str) -> IResult<&str, Delay3> { + Ok((s, Delay3 { raw: vec![] })) +} + +pub fn delay_control(s: &str) -> IResult<&str, DelayControl> { + Ok((s, DelayControl { raw: vec![] })) +} + +pub fn statement_or_null(s: &str) -> IResult<&str, StatementOrNull> { + Ok((s, StatementOrNull { raw: vec![] })) +} + +pub fn statement(s: &str) -> IResult<&str, Statement> { + Ok((s, Statement { raw: vec![] })) +} + +pub fn function_statement(s: &str) -> IResult<&str, FunctionStatement> { + Ok((s, FunctionStatement { raw: vec![] })) +} + +pub fn delay_or_event_control(s: &str) -> IResult<&str, DelayOrEventControl> { + Ok((s, DelayOrEventControl { raw: vec![] })) +} + +pub fn dynamic_array_new(s: &str) -> IResult<&str, DynamicArrayNew> { + Ok((s, DynamicArrayNew { raw: vec![] })) +} + +pub fn class_new(s: &str) -> IResult<&str, ClassNew> { + Ok((s, ClassNew { raw: vec![] })) +} + +pub fn block_item_declaration(s: &str) -> IResult<&str, BlockItemDeclaration> { + Ok((s, BlockItemDeclaration { raw: vec![] })) +}