Skip to content

Commit 48ac02e

Browse files
authored
Merge pull request #125 from yousifBilal/type-equality
Fix type equality and inequality parsing
2 parents 2a4d5d0 + e006855 commit 48ac02e

6 files changed

Lines changed: 168 additions & 44 deletions

File tree

sv-parser-parser/src/behavioral_statements/case_statements.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,40 @@ pub(crate) fn case_statement_normal(s: Span) -> IResult<Span, CaseStatement> {
1818
let (s, a) = opt(unique_priority)(s)?;
1919
let (s, b) = case_keyword(s)?;
2020
let (s, c) = paren(case_expression)(s)?;
21-
let (s, d) = case_item(s)?;
22-
let (s, (e, f)) = many_till(case_item, keyword("endcase"))(s)?;
23-
Ok((
24-
s,
25-
CaseStatement::Normal(Box::new(CaseStatementNormal {
26-
nodes: (a, b, c, d, e, f),
27-
})),
28-
))
21+
if !matches!(
22+
c.nodes.1.nodes.0,
23+
CaseExpressionExpression::TypeReference(_)
24+
) {
25+
let (s, d) = case_item(s)?;
26+
let (s, (e, f)) = many_till(case_item, keyword("endcase"))(s)?;
27+
Ok((
28+
s,
29+
CaseStatement::Normal(Box::new(CaseStatementNormal {
30+
nodes: (a, b, c, d, e, f),
31+
})),
32+
))
33+
} else {
34+
let verify_case_item = |d: &CaseItem| {
35+
if let CaseItem::NonDefault(non_def_item) = d {
36+
matches!(
37+
non_def_item.nodes.0.nodes.0.nodes.0,
38+
CaseExpressionExpression::TypeReference(_)
39+
) && non_def_item.nodes.0.nodes.1.iter().all(|(_, cie)| {
40+
matches!(cie.nodes.0, CaseExpressionExpression::TypeReference(_))
41+
})
42+
} else {
43+
true
44+
}
45+
};
46+
let (s, d) = verify(case_item, verify_case_item)(s)?;
47+
let (s, (e, f)) = many_till(verify(case_item, verify_case_item), keyword("endcase"))(s)?;
48+
Ok((
49+
s,
50+
CaseStatement::Normal(Box::new(CaseStatementNormal {
51+
nodes: (a, b, c, d, e, f),
52+
})),
53+
))
54+
}
2955
}
3056

3157
#[tracable_parser]
@@ -75,7 +101,14 @@ pub(crate) fn case_keyword(s: Span) -> IResult<Span, CaseKeyword> {
75101
#[tracable_parser]
76102
#[packrat_parser]
77103
pub(crate) fn case_expression(s: Span) -> IResult<Span, CaseExpression> {
78-
let (s, a) = expression(s)?;
104+
let (s, a) = alt((
105+
map(expression, |x| {
106+
CaseExpressionExpression::Expression(Box::new(x))
107+
}),
108+
map(type_reference, |x| {
109+
CaseExpressionExpression::TypeReference(Box::new(x))
110+
}),
111+
))(s)?;
79112
Ok((s, CaseExpression { nodes: (a,) }))
80113
}
81114

@@ -160,7 +193,14 @@ pub(crate) fn case_inside_item_nondefault(s: Span) -> IResult<Span, CaseInsideIt
160193
#[tracable_parser]
161194
#[packrat_parser]
162195
pub(crate) fn case_item_expression(s: Span) -> IResult<Span, CaseItemExpression> {
163-
let (s, a) = expression(s)?;
196+
let (s, a) = alt((
197+
map(expression, |x| {
198+
CaseExpressionExpression::Expression(Box::new(x))
199+
}),
200+
map(type_reference, |x| {
201+
CaseExpressionExpression::TypeReference(Box::new(x))
202+
}),
203+
))(s)?;
164204
Ok((s, CaseItemExpression { nodes: (a,) }))
165205
}
166206

sv-parser-parser/src/expressions/expressions.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -305,16 +305,40 @@ pub(crate) fn expression_operator_assignment(s: Span) -> IResult<Span, Expressio
305305
#[tracable_parser]
306306
#[packrat_parser]
307307
pub(crate) fn expression_binary(s: Span) -> IResult<Span, Expression> {
308-
let (s, a) = expression(s)?;
308+
let (s, a) = alt((
309+
map(expression, |x| {
310+
ExpressionBinaryOperand::Expression(Box::new(x))
311+
}),
312+
map(type_reference, |x| {
313+
ExpressionBinaryOperand::TypeReference(Box::new(x))
314+
}),
315+
))(s)?;
316+
let is_equality = peek(alt((symbol("=="), symbol("!="))))(s).is_ok();
309317
let (s, b) = binary_operator(s)?;
310318
let (s, c) = many0(attribute_instance)(s)?;
311-
let (s, d) = expression(s)?;
312-
Ok((
313-
s,
314-
Expression::Binary(Box::new(ExpressionBinary {
315-
nodes: (a, b, c, d),
316-
})),
317-
))
319+
let (s, d) = alt((
320+
map(expression, |x| {
321+
ExpressionBinaryOperand::Expression(Box::new(x))
322+
}),
323+
map(type_reference, |x| {
324+
ExpressionBinaryOperand::TypeReference(Box::new(x))
325+
}),
326+
))(s)?;
327+
328+
// Enforces Footnote (40) in IEEE STD 1800 - 2017
329+
let op1_is_type_ref = matches!(a, ExpressionBinaryOperand::TypeReference(_));
330+
let op2_is_type_ref = matches!(d, ExpressionBinaryOperand::TypeReference(_));
331+
if !(op1_is_type_ref || op2_is_type_ref) || (is_equality && op1_is_type_ref && op2_is_type_ref)
332+
{
333+
Ok((
334+
s,
335+
Expression::Binary(Box::new(ExpressionBinary {
336+
nodes: (a, b, c, d),
337+
})),
338+
))
339+
} else {
340+
Err(Err::Error(make_error(s, ErrorKind::Fail)))
341+
}
318342
}
319343

320344
#[tracable_parser]

sv-parser-parser/src/tests.rs

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ mod unit {
5454

5555
#[test]
5656
fn test_data_declaration() {
57-
// Implicit data_type is not allowed unless the `var` keyword is used.
58-
test!(data_declaration, "logic x = 0;", Ok((_, _)));
59-
test!(data_declaration, " x = 0;", Err(_));
60-
test!(data_declaration, "var logic x = 0;", Ok((_, _)));
61-
test!(data_declaration, "var x = 0;", Ok((_, _)));
62-
test!(data_declaration, "const logic x = 0;", Ok((_, _)));
63-
test!(data_declaration, "const x = 0;", Err(_));
57+
// Implicit data_type is not allowed unless the `var` keyword is used.
58+
test!(data_declaration, "logic x = 0;", Ok((_, _)));
59+
test!(data_declaration, " x = 0;", Err(_));
60+
test!(data_declaration, "var logic x = 0;", Ok((_, _)));
61+
test!(data_declaration, "var x = 0;", Ok((_, _)));
62+
test!(data_declaration, "const logic x = 0;", Ok((_, _)));
63+
test!(data_declaration, "const x = 0;", Err(_));
6464
}
6565

6666
#[test]
@@ -332,6 +332,14 @@ mod unit {
332332
test!(expression, "(!a ? 0 : !b : 1 : c ? 0 : 1)", Ok((_, _)));
333333
}
334334

335+
#[test]
336+
fn test_bin_op_expression() {
337+
test!(expression, "type(logic) == type(logic)", Ok((_, _)));
338+
test!(expression, "type(logic) != type(logic)", Ok((_, _)));
339+
test!(expression, "type(logic) + type(logic)", Err(_));
340+
test!(expression, "type(logic) == a", Err(_));
341+
}
342+
335343
#[test]
336344
fn test_text_macro_definition() {
337345
test!(text_macro_definition, r##"`define a b c"##, Ok((_, _)));
@@ -809,11 +817,7 @@ mod spec {
809817
r##"a = add (* mode = "cla" *) (b, c);"##,
810818
Ok((_, _))
811819
);
812-
test!(
813-
statement,
814-
r##"a = b ? (* no_glitch *) c : d;"##,
815-
Ok((_, _))
816-
);
820+
test!(statement, r##"a = b ? (* no_glitch *) c : d;"##, Ok((_, _)));
817821
}
818822

819823
#[test]
@@ -2685,11 +2689,7 @@ mod spec {
26852689
status = p.current_status();"##,
26862690
Ok((_, _))
26872691
);
2688-
test!(
2689-
statement,
2690-
r##"status = current_status(p);"##,
2691-
Ok((_, _))
2692-
);
2692+
test!(statement, r##"status = current_status(p);"##, Ok((_, _)));
26932693
test!(many1(module_item), r##"Packet p = new;"##, Ok((_, _)));
26942694
test!(
26952695
many1(module_item),
@@ -3512,11 +3512,7 @@ mod spec {
35123512
end"##,
35133513
Ok((_, _))
35143514
);
3515-
test!(
3516-
statement,
3517-
r##"put_ref = new(); // illegal"##,
3518-
Ok((_, _))
3519-
);
3515+
test!(statement, r##"put_ref = new(); // illegal"##, Ok((_, _)));
35203516
test!(
35213517
many1(module_item),
35223518
r##"interface class IntfBase1;
@@ -15942,6 +15938,35 @@ mod spec {
1594215938
Ok((_, _))
1594315939
);
1594415940
}
15941+
15942+
#[test]
15943+
fn test_case_statement_comparison() {
15944+
test!(
15945+
many1(case_statement),
15946+
r##"case (type(logic))
15947+
type(logic[11:0]) : ;
15948+
type(logic) : ;
15949+
default : ;
15950+
endcase"##,
15951+
Ok((_, _))
15952+
);
15953+
test!(
15954+
many1(case_statement),
15955+
r##"case (type(logic))
15956+
1 : ;
15957+
default : ;
15958+
endcase"##,
15959+
Err(_)
15960+
);
15961+
test!(
15962+
many1(case_statement),
15963+
r##"case (type(logic))
15964+
x : ;
15965+
default : ;
15966+
endcase"##,
15967+
Err(_)
15968+
);
15969+
}
1594515970
}
1594615971

1594715972
mod error {

sv-parser-syntaxtree/src/behavioral_statements/case_statements.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ pub enum CaseKeyword {
5656

5757
#[derive(Clone, Debug, PartialEq, Node)]
5858
pub struct CaseExpression {
59-
pub nodes: (Expression,),
59+
pub nodes: (CaseExpressionExpression,),
60+
}
61+
62+
#[derive(Clone, Debug, PartialEq, Node)]
63+
pub enum CaseExpressionExpression {
64+
Expression(Box<Expression>),
65+
TypeReference(Box<TypeReference>),
6066
}
6167

6268
#[derive(Clone, Debug, PartialEq, Node)]
@@ -104,7 +110,7 @@ pub struct CaseInsideItemNondefault {
104110

105111
#[derive(Clone, Debug, PartialEq, Node)]
106112
pub struct CaseItemExpression {
107-
pub nodes: (Expression,),
113+
pub nodes: (CaseExpressionExpression,),
108114
}
109115

110116
#[derive(Clone, Debug, PartialEq, Node)]

sv-parser-syntaxtree/src/expressions/expressions.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,19 @@ pub struct ExpressionOperatorAssignment {
149149
#[derive(Clone, Debug, PartialEq, Node)]
150150
pub struct ExpressionBinary {
151151
pub nodes: (
152-
Expression,
152+
ExpressionBinaryOperand,
153153
BinaryOperator,
154154
Vec<AttributeInstance>,
155-
Expression,
155+
ExpressionBinaryOperand,
156156
),
157157
}
158158

159+
#[derive(Clone, Debug, PartialEq, Node)]
160+
pub enum ExpressionBinaryOperand {
161+
Expression(Box<Expression>),
162+
TypeReference(Box<TypeReference>),
163+
}
164+
159165
#[derive(Clone, Debug, PartialEq, Node)]
160166
pub struct TaggedUnionExpression {
161167
pub nodes: (Keyword, MemberIdentifier, Option<Expression>),

sv-parser/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,4 +451,27 @@ endmodule"##;
451451
let ret = parse_sv_str(src, &path, &defines, &[""], false, false);
452452
assert!(ret.is_ok());
453453
}
454+
455+
#[test]
456+
fn test_type_equality() {
457+
let src = r##"module top #( parameter type T = type(logic[11:0]) )
458+
();
459+
initial begin
460+
case (type(T))
461+
type(logic[11:0]) : ;
462+
default : $stop;
463+
endcase
464+
if (type(T) == type(logic[12:0])) $stop;
465+
if (type(T) != type(logic[11:0])) $stop;
466+
if (type(T) === type(logic[12:0])) $stop;
467+
if (type(T) !== type(logic[11:0])) $stop;
468+
$finish;
469+
end
470+
endmodule"##;
471+
472+
let path = PathBuf::from("");
473+
let defines = HashMap::new();
474+
let ret = parse_sv_str(src, &path, &defines, &[""], false, false);
475+
assert!(ret.is_ok());
476+
}
454477
}

0 commit comments

Comments
 (0)