Skip to content

Commit

Permalink
Cleanup to make recent change a bit more clear and efficient
Browse files Browse the repository at this point in the history
  • Loading branch information
MikePopoloski committed Mar 16, 2024
1 parent 1b223c6 commit 5a120ae
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 28 deletions.
1 change: 1 addition & 0 deletions scripts/diagnostics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ error InterfacePortInvalidExpression "invalid expression for interface port conn
error AssignmentPatternLValueDynamic "lvalue assignment patterns cannot be assigned from dynamic arrays"
error SelectAfterRangeSelect "cannot chain select expressions after a range select"
error ClassPrivateMembersBitstream "cannot use class type {} as a bit-stream because it has local or protected members that are not accessible in this context"
error CannotCompareTwoInstances "cannot compare two instances to each other; at least one side must be a virtual interface"
warning ignored-slice IgnoredSlice "slice size ignored for left-to-right streaming operator"
warning unsized-concat UnsizedInConcat "unsized integer in concat; using a width of {}"
warning width-expand WidthExpand "implicit conversion expands from {} to {} bits"
Expand Down
2 changes: 1 addition & 1 deletion source/ast/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@ Expression* Expression::tryBindInterfaceRef(const ASTContext& context,
if (!result.found) {
// We didn't find the name as-is. This might be a case where the user has
// provided an explicit modport name on top of an array of interfaces,
// which we should support by looking up the name again withotu the trailing
// which we should support by looking up the name again without the trailing
// name component and taking the result if it's an iface array.
if (expr->kind == SyntaxKind::ScopedName) {
auto& scoped = expr->as<ScopedNameSyntax>();
Expand Down
55 changes: 31 additions & 24 deletions source/ast/expressions/OperatorExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,38 +592,45 @@ Expression& BinaryExpression::fromSyntax(Compilation& compilation,
flags = ASTFlags::AllowUnboundedLiteral;
}

Expression *lhs, *rhs;
auto& syntaxLeft = *syntax.left;
auto& syntaxRight = *syntax.right;

auto op = getBinaryOperator(syntax.kind);
if (op == BinaryOperator::Equality || op == BinaryOperator::Inequality ||
op == BinaryOperator::CaseEquality || op == BinaryOperator::CaseInequality) {
flags |= ASTFlags::AllowTypeReferences;
}

Expression *lhs = nullptr, *rhs = nullptr;
ExpressionSyntax* syntaxLeft = syntax.left;
ExpressionSyntax* syntaxRight = syntax.right;
bool notVirtIface = true;

// Check that there is a comparison with at least one virtual interface.
// See IEEE 1800-2017 25.9 clause.
if (op == BinaryOperator::Equality || op == BinaryOperator::Inequality) {
lhs = tryBindInterfaceRef(context, *syntaxLeft, /* isInterfacePort */ false);
if (lhs) {
rhs = &selfDetermined(compilation, *syntaxRight, context, flags);
notVirtIface = !rhs->type->isVirtualInterface();
}

if (!rhs) {
rhs = tryBindInterfaceRef(context, *syntaxRight, /* isInterfacePort */ false);
if (rhs) {
lhs = &selfDetermined(compilation, *syntaxLeft, context, flags);
notVirtIface = !lhs->type->isVirtualInterface();
// Special case to handle comparing a virtual interface with an
// actual instance. We can't normally bind to an instance from
// an expression so we need to explicitly try that separately here.
lhs = tryBindInterfaceRef(context, syntaxLeft, /* isInterfacePort */ false);
if (!lhs)
lhs = &create(compilation, syntaxLeft, context, flags);

// If we found a virtual interface on the lhs we can also try for an instance
// on the rhs. Otherwise we know we're doing normal expression binding.
if (lhs->type->isVirtualInterface()) {
rhs = tryBindInterfaceRef(context, syntaxRight, /* isInterfacePort */ false);
if (!rhs) {
rhs = &create(compilation, syntaxRight, context, flags);
}
else if (lhs->kind == ExpressionKind::ArbitrarySymbol &&
rhs->kind == ExpressionKind::ArbitrarySymbol) {
// Having an instance on both sides is not allowed. One side must be
// an actual virtual interface.
context.addDiag(diag::CannotCompareTwoInstances, syntax.operatorToken.location())
<< lhs->sourceRange << rhs->sourceRange;
return badExpr(compilation, nullptr);
}
}
else {
rhs = &create(compilation, syntaxRight, context, flags);
}
}

if (!lhs || !rhs || notVirtIface) {
lhs = &create(compilation, *syntaxLeft, context, flags);
rhs = &create(compilation, *syntaxRight, context, flags);
else {
lhs = &create(compilation, syntaxLeft, context, flags);
rhs = &create(compilation, syntaxRight, context, flags);
}

auto& result = fromComponents(*lhs, *rhs, op, syntax.operatorToken.location(),
Expand Down
5 changes: 2 additions & 3 deletions tests/unittests/ast/MemberTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2679,9 +2679,8 @@ endmodule
Compilation compilation;
compilation.addSyntaxTree(tree);
auto& diags = compilation.getAllDiagnostics();
REQUIRE(diags.size() == 2);
CHECK(diags[0].code == diag::NotAValue);
CHECK(diags[1].code == diag::NotAValue);
REQUIRE(diags.size() == 1);
CHECK(diags[0].code == diag::CannotCompareTwoInstances);
}

TEST_CASE("Virtual interfaces of different types comparison") {
Expand Down

0 comments on commit 5a120ae

Please sign in to comment.