From 63e08c1ac407547a7c04bb549bf56d5ce344be06 Mon Sep 17 00:00:00 2001 From: Mike Popoloski Date: Tue, 24 Dec 2024 14:53:28 -0500 Subject: [PATCH] Error if virtual interface assignment has a config rule applied --- .../ast/symbols/CompilationUnitSymbols.h | 3 +++ scripts/diagnostics.txt | 1 + source/ast/Expression.cpp | 10 +++++++ source/ast/symbols/InstanceSymbols.cpp | 4 +++ tests/unittests/ast/ConfigTests.cpp | 27 +++++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/include/slang/ast/symbols/CompilationUnitSymbols.h b/include/slang/ast/symbols/CompilationUnitSymbols.h index 5b1dc721c..fe4535578 100644 --- a/include/slang/ast/symbols/CompilationUnitSymbols.h +++ b/include/slang/ast/symbols/CompilationUnitSymbols.h @@ -261,6 +261,9 @@ struct SLANG_EXPORT ResolvedConfig { /// A list of libraries to use to look up definitions. std::span liblist; + /// The original rule that led to this resolved configuration. + const ConfigRule* configRule = nullptr; + ResolvedConfig(const ConfigBlockSymbol& useConfig, const InstanceSymbol& rootInstance); }; diff --git a/scripts/diagnostics.txt b/scripts/diagnostics.txt index 7f7352d42..20142c0d9 100644 --- a/scripts/diagnostics.txt +++ b/scripts/diagnostics.txt @@ -743,6 +743,7 @@ error InvalidExtendsDefault "constructor must use 'default' in its argument list error NonblockingDynamicAssign "nonblocking assignments to elements of dynamically sized arrays are not allowed" error VoidAssignment "expression of type 'void' cannot be used in assignments" error VirtualIfaceDefparam "interface instance cannot be assigned to a virtual interface because it is the target of a defparam or bind directive" +error VirtualIfaceConfigRule "interface instance cannot be assigned to a virtual interface because it is the target of config rule" error MultipleDefaultDistWeight "'default' cannot be used more than once in dist item list" error DistRealRangeWeight "'dist' for a range of real values must include an explicit weight and must use the ':/' operator" warning ignored-slice IgnoredSlice "slice size ignored for left-to-right streaming operator" diff --git a/source/ast/Expression.cpp b/source/ast/Expression.cpp index f23e4ecec..cd8ac28f8 100644 --- a/source/ast/Expression.cpp +++ b/source/ast/Expression.cpp @@ -1459,6 +1459,16 @@ Expression* Expression::tryBindInterfaceRef(const ASTContext& context, diag.addNote(diag::NoteDeclarationHere, source->sourceRange()); } + if (iface->parentInstance && iface->parentInstance->resolvedConfig) { + auto& diag = context.addDiag(diag::VirtualIfaceConfigRule, sourceRange); + + auto rc = iface->parentInstance->resolvedConfig; + if (rc->configRule) + diag.addNote(diag::NoteConfigRule, rc->configRule->syntax->sourceRange()); + else + diag.addNote(diag::NoteConfigRule, rc->useConfig.location); + } + if (!arrayModportName.empty()) { if (modport) { // If we connected via an interface port that itself has a modport restriction, diff --git a/source/ast/symbols/InstanceSymbols.cpp b/source/ast/symbols/InstanceSymbols.cpp index b16767160..b9e19a473 100644 --- a/source/ast/symbols/InstanceSymbols.cpp +++ b/source/ast/symbols/InstanceSymbols.cpp @@ -425,6 +425,8 @@ InstanceSymbol& InstanceSymbol::createDefault(Compilation& comp, const Definitio if (configBlock) { auto rc = comp.emplace(*configBlock, result); + rc->configRule = configRule; + if (configRule) { configRule->isUsed = true; if (configRule->liblist) @@ -669,6 +671,8 @@ void InstanceSymbol::fromSyntax(Compilation& comp, const HierarchyInstantiationS if (confRule) { SLANG_ASSERT(resolvedConfig); auto rc = comp.emplace(*resolvedConfig); + rc->configRule = confRule; + confRule->isUsed = true; if (confRule->liblist) rc->liblist = *confRule->liblist; diff --git a/tests/unittests/ast/ConfigTests.cpp b/tests/unittests/ast/ConfigTests.cpp index e678d806c..28319ad2b 100644 --- a/tests/unittests/ast/ConfigTests.cpp +++ b/tests/unittests/ast/ConfigTests.cpp @@ -1243,3 +1243,30 @@ endmodule : cmp NO_COMPILATION_ERRORS; } } + +TEST_CASE("Configs with virtual interfaces") { + auto tree = SyntaxTree::fromText(R"( +config cfg1; + design top; + instance top.i use J; + cell I use J; +endconfig + +interface J; +endinterface + +module top; + I i(); + virtual I vi = i; +endmodule +)"); + CompilationOptions options; + options.topModules.emplace("cfg1"); + + Compilation compilation(options); + compilation.addSyntaxTree(tree); + + auto& diags = compilation.getAllDiagnostics(); + REQUIRE(diags.size() == 1); + CHECK(diags[0].code == diag::VirtualIfaceConfigRule); +}