324 lines
8.9 KiB
Rust
324 lines
8.9 KiB
Rust
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<Identifier<'a>>,
|
|
pub event: ClockingEvent<'a>,
|
|
pub item: Vec<ClockingItem<'a>>,
|
|
pub end_identifier: Option<Identifier<'a>>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ClockingDeclarationGlobal<'a> {
|
|
pub beg_identifier: Option<Identifier<'a>>,
|
|
pub event: ClockingEvent<'a>,
|
|
pub end_identifier: Option<Identifier<'a>>,
|
|
}
|
|
|
|
#[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<ClockingDeclAssign<'a>>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ClockingItemAssertion<'a> {
|
|
pub attribute: Vec<AttributeInstance<'a>>,
|
|
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<ClockingSkew<'a>>),
|
|
Output(Option<ClockingSkew<'a>>),
|
|
InputOutput((Option<ClockingSkew<'a>>, Option<ClockingSkew<'a>>)),
|
|
Inout,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ClockingDeclAssign<'a> {
|
|
pub identifier: Identifier<'a>,
|
|
pub expression: Option<Expression<'a>>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum ClockingSkew<'a> {
|
|
Edge((EdgeIdentifier<'a>, Option<DelayControl<'a>>)),
|
|
Delay(DelayControl<'a>),
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ClockingDrive<'a> {
|
|
pub lvalue: (HierarchicalIdentifier<'a>, Select<'a>),
|
|
pub cycle_delay: Option<CycleDelay<'a>>,
|
|
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("@"), paren(event_expression)), |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<ClockingDeclAssign>> {
|
|
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("##"), paren(expression)), |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)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|