sv-parser/src/subroutine_calls.rs
2019-07-03 15:04:51 +09:00

326 lines
8.9 KiB
Rust

use crate::attributes::*;
use crate::expressions::*;
use crate::identifiers::*;
use crate::primaries::*;
use crate::util::*;
use nom::branch::*;
use nom::bytes::complete::*;
use nom::combinator::*;
use nom::multi::*;
use nom::sequence::*;
use nom::IResult;
// -----------------------------------------------------------------------------
#[derive(Debug)]
pub struct TfCall<'a> {
pub identifier: ScopedIdentifier<'a>,
pub attribute: Vec<AttributeInstance<'a>>,
pub argument: Option<ListOfArguments<'a>>,
}
#[derive(Debug)]
pub struct SystemTfCall<'a> {
pub identifier: Identifier<'a>,
pub argument: Option<ListOfArguments<'a>>,
pub data_type: Option<DataType<'a>>,
pub expression: Option<Vec<Expression<'a>>>,
pub clocking_event: Option<ClockingEvent<'a>>,
}
#[derive(Debug)]
pub enum SubroutineCall<'a> {
Tf(Box<TfCall<'a>>),
SystemTf(Box<SystemTfCall<'a>>),
Method(Box<MethodCall<'a>>),
Randomize(Box<RandomizeCall<'a>>),
StdRandomize(Box<RandomizeCall<'a>>),
}
#[derive(Debug)]
pub struct ListOfArguments<'a> {
pub unnamed: Vec<Expression<'a>>,
pub named: Vec<(Identifier<'a>, Option<Expression<'a>>)>,
}
#[derive(Debug)]
pub struct MethodCall<'a> {
pub root: MethodCallRoot<'a>,
pub body: MethodCallBody<'a>,
}
#[derive(Debug)]
pub enum MethodCallRoot<'a> {
Primary(Primary<'a>),
ImplicitClassHandle(Scope<'a>),
}
#[derive(Debug)]
pub enum MethodCallBody<'a> {
User(MethodCallBodyUser<'a>),
Array(ArrayManipulationCall<'a>),
Randomize(RandomizeCall<'a>),
}
#[derive(Debug)]
pub struct MethodCallBodyUser<'a> {
pub identifier: Identifier<'a>,
pub attribute: Vec<AttributeInstance<'a>>,
pub argument: Option<ListOfArguments<'a>>,
}
#[derive(Debug)]
pub struct ArrayManipulationCall<'a> {
pub name: ArrayMethodName<'a>,
pub attribute: Vec<AttributeInstance<'a>>,
pub argument: Option<ListOfArguments<'a>>,
pub with: Option<Expression<'a>>,
}
#[derive(Debug)]
pub struct RandomizeCall<'a> {
pub attribute: Vec<AttributeInstance<'a>>,
pub argument: Vec<Identifier<'a>>,
pub with: Vec<Identifier<'a>>,
pub constraint_block: Option<ConstraintBlock<'a>>,
}
#[derive(Debug)]
pub enum ArrayMethodName<'a> {
Identifier(Identifier<'a>),
Unique,
And,
Or,
Xor,
}
// -----------------------------------------------------------------------------
pub fn constant_function_call(s: &str) -> IResult<&str, SubroutineCall> {
function_subroutine_call(s)
}
pub fn tf_call(s: &str) -> IResult<&str, TfCall> {
let (s, identifier) = ps_or_hierarchical_tf_identifier(s)?;
let (s, attribute) = many0(sp(attribute_instance))(s)?;
let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?;
Ok((
s,
TfCall {
identifier,
attribute,
argument,
},
))
}
pub fn system_tf_call(s: &str) -> IResult<&str, SystemTfCall> {
alt((
system_tf_call_list_of_arguments,
system_tf_call_data_type,
system_tf_call_clocking_event,
))(s)
}
pub fn system_tf_call_list_of_arguments(s: &str) -> IResult<&str, SystemTfCall> {
let (s, identifier) = system_tf_identifier(s)?;
let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?;
Ok((
s,
SystemTfCall {
identifier,
argument,
data_type: None,
expression: None,
clocking_event: None,
},
))
}
pub fn system_tf_call_data_type(s: &str) -> IResult<&str, SystemTfCall> {
let (s, identifier) = system_tf_identifier(s)?;
let (s, _) = sp(tag("("))(s)?;
let (s, data_type) = sp(data_type)(s)?;
let (s, expression) = sp(preceded(sp(tag(",")), expression))(s)?;
let (s, _) = sp(tag(")"))(s)?;
let data_type = Some(data_type);
let expression = Some(vec![expression]);
Ok((
s,
SystemTfCall {
identifier,
argument: None,
data_type,
expression,
clocking_event: None,
},
))
}
pub fn system_tf_call_clocking_event(s: &str) -> IResult<&str, SystemTfCall> {
let (s, identifier) = system_tf_identifier(s)?;
let (s, _) = sp(tag("("))(s)?;
let (s, expression) = separated_nonempty_list(sp(tag(",")), sp(expression))(s)?;
let (s, clocking_event) = opt(preceded(sp(tag(",")), opt(sp(clocking_event))))(s)?;
let (s, _) = sp(tag(")"))(s)?;
let expression = Some(expression);
let clocking_event = if let Some(Some(x)) = clocking_event {
Some(x)
} else {
None
};
Ok((
s,
SystemTfCall {
identifier,
argument: None,
data_type: None,
expression,
clocking_event,
},
))
}
pub fn subroutine_call(s: &str) -> IResult<&str, SubroutineCall> {
alt((
map(tf_call, |x| SubroutineCall::Tf(Box::new(x))),
map(system_tf_call, |x| SubroutineCall::SystemTf(Box::new(x))),
map(method_call, |x| SubroutineCall::Method(Box::new(x))),
map(
tuple((tag("std"), sp(tag("::")), randomize_call)),
|(_, _, x)| SubroutineCall::StdRandomize(Box::new(x)),
),
map(randomize_call, |x| SubroutineCall::Randomize(Box::new(x))),
))(s)
}
pub fn function_subroutine_call(s: &str) -> IResult<&str, SubroutineCall> {
subroutine_call(s)
}
pub fn list_of_arguments(s: &str) -> IResult<&str, ListOfArguments> {
let (s, unnamed) = separated_list(sp(tag(",")), sp(expression))(s)?;
let (s, named) = separated_list(
sp(tag(",")),
pair(
preceded(tag("."), identifier),
delimited(sp(tag("(")), opt(sp(expression)), sp(tag(")"))),
),
)(s)?;
Ok((s, ListOfArguments { unnamed, named }))
}
pub fn method_call(s: &str) -> IResult<&str, MethodCall> {
let (s, root) = method_call_root(s)?;
let (s, _) = sp(tag("."))(s)?;
let (s, body) = method_call_body(s)?;
Ok((s, MethodCall { root, body }))
}
pub fn method_call_body(s: &str) -> IResult<&str, MethodCallBody> {
alt((method_call_body_user, built_in_method_call))(s)
}
pub fn method_call_body_user(s: &str) -> IResult<&str, MethodCallBody> {
let (s, identifier) = method_identifier(s)?;
let (s, attribute) = many0(sp(attribute_instance))(s)?;
let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?;
Ok((
s,
MethodCallBody::User(MethodCallBodyUser {
identifier,
attribute,
argument,
}),
))
}
pub fn built_in_method_call(s: &str) -> IResult<&str, MethodCallBody> {
alt((
map(array_manipulation_call, |x| MethodCallBody::Array(x)),
map(randomize_call, |x| MethodCallBody::Randomize(x)),
))(s)
}
pub fn array_manipulation_call(s: &str) -> IResult<&str, ArrayManipulationCall> {
let (s, name) = array_method_name(s)?;
let (s, attribute) = many0(sp(attribute_instance))(s)?;
let (s, argument) = opt(delimited(sp(tag("(")), sp(list_of_arguments), sp(tag(")"))))(s)?;
let (s, with) = opt(preceded(
sp(tag("with")),
delimited(sp(tag("(")), sp(expression), sp(tag(")"))),
))(s)?;
Ok((
s,
ArrayManipulationCall {
name,
attribute,
argument,
with,
},
))
}
pub fn randomize_call(s: &str) -> IResult<&str, RandomizeCall> {
let (s, _) = tag("randomize")(s)?;
let (s, attribute) = many0(sp(attribute_instance))(s)?;
let (s, argument) = opt(delimited(
sp(tag("(")),
opt(alt((
sp(variable_identifier_list),
map(sp(tag("null")), |_| vec![]),
))),
sp(tag(")")),
))(s)?;
let (s, with) = opt(tuple((
sp(tag("with")),
opt(delimited(
sp(tag("(")),
opt(sp(identifier_list)),
sp(tag(")")),
)),
constraint_block,
)))(s)?;
let argument = if let Some(Some(x)) = argument {
x
} else {
vec![]
};
let (with, constraint_block) = if let Some((_, Some(Some(x)), y)) = with {
(x, Some(y))
} else {
(vec![], None)
};
Ok((
s,
RandomizeCall {
attribute,
argument,
with,
constraint_block,
},
))
}
pub fn method_call_root(s: &str) -> IResult<&str, MethodCallRoot> {
alt((
map(primary, |x| MethodCallRoot::Primary(x)),
map(implicit_class_handle, |x| {
MethodCallRoot::ImplicitClassHandle(x)
}),
))(s)
}
pub fn array_method_name(s: &str) -> IResult<&str, ArrayMethodName> {
alt((
map(tag("unique"), |_| ArrayMethodName::Unique),
map(tag("and"), |_| ArrayMethodName::And),
map(tag("or"), |_| ArrayMethodName::Or),
map(tag("xor"), |_| ArrayMethodName::Xor),
map(method_identifier, |x| ArrayMethodName::Identifier(x)),
))(s)
}
// -----------------------------------------------------------------------------