Skip to content

Commit

Permalink
Tests and fixes for covergroup inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
MikePopoloski committed May 17, 2024
1 parent 4922ab0 commit 972b19e
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 9 deletions.
2 changes: 1 addition & 1 deletion include/slang/parsing/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ class SLANG_EXPORT Parser : ParserBase, syntax::SyntaxFacts {
syntax::MemberSyntax* parseCoverageMember();
syntax::BlockEventExpressionSyntax& parseBlockEventExpression();
syntax::WithClauseSyntax* parseWithClause();
syntax::CovergroupDeclarationSyntax& parseCovergroupDeclaration(AttrList attributes, bool inClass);
syntax::CovergroupDeclarationSyntax& parseCovergroupDeclaration(AttrList attributes, bool inClass, bool hasBaseClass);
syntax::CoverpointSyntax* parseCoverpoint(AttrList attributes, syntax::DataTypeSyntax* type, syntax::NamedLabelSyntax* label);
syntax::CoverCrossSyntax* parseCoverCross(AttrList attributes, syntax::NamedLabelSyntax* label);
syntax::CoverageOptionSyntax* parseCoverageOption(AttrList attributes);
Expand Down
2 changes: 2 additions & 0 deletions scripts/diagnostics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ error FinalWithPure "'final' specifier cannot be used with a pure virtual member
error StaticFuncSpecifier "static members cannot have override specifiers"
error OverridingExtends "'{}' is marked 'extends' but doesn't override a base class virtual member"
error DerivedCovergroupNotInClass "covergroup inheritance can only be used inside a class"
error DerivedCovergroupNoBase "covergroup is marked 'extends' but is in a class that has no base class"
warning dpi-pure-task DPIPureTask "DPI tasks cannot be marked 'pure'"
warning nonstandard-generate NonStandardGenBlock "standalone generate block without loop or condition is not allowed in SystemVerilog"
warning empty-pattern EmptyAssignmentPattern "empty assignment patterns are disallowed by SystemVerilog"
Expand Down Expand Up @@ -524,6 +525,7 @@ error OverridingInitial "'{}' is marked 'initial' but overrides a base class mem
error OverridingFinal "'{}' overrides a base class member that is marked 'final'"
error PackageImportSelf "package cannot import itself"
error PackageExportSelf "package cannot export itself"
error UnknownCovergroupBase "'{}' is not a covergroup in '{}'"
error FatalTask "$fatal encountered{}"
error ErrorTask "$error encountered{}"
error StaticAssert "static assertion failed{}"
Expand Down
10 changes: 8 additions & 2 deletions source/ast/symbols/CoverSymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,19 @@ void CovergroupType::inheritMembers(function_ref<void(const Symbol&)> insertCB)
if (!baseClass || baseClass->kind != SymbolKind::ClassType)
return;

auto candidateBase = baseClass->as<ClassType>().find(cds.name.valueText());
auto baseName = cds.name.valueText();
auto candidateBase = baseClass->as<ClassType>().find(baseName);
if (candidateBase && candidateBase->kind == SymbolKind::ClassProperty) {
auto& ct = candidateBase->as<ClassPropertySymbol>().getType();
if (ct.kind == SymbolKind::CovergroupType)
baseGroup = &ct;
}

if (baseGroup->isError()) {
// TODO: error
if (!baseName.empty()) {
scope->addDiag(diag::UnknownCovergroupBase, cds.name.range())
<< baseName << baseClass->name;
}
return;
}

Expand Down Expand Up @@ -391,6 +395,8 @@ ConstantValue CovergroupType::getDefaultValueImpl() const {
void CovergroupType::serializeTo(ASTSerializer& serializer) const {
if (auto ev = getCoverageEvent())
serializer.write("event", *ev);
if (auto bg = getBaseGroup())
serializer.writeLink("baseGroup", *bg);
}

const Expression* CoverageBinSymbol::getIffExpr() const {
Expand Down
14 changes: 8 additions & 6 deletions source/parsing/Parser_members.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ MemberSyntax* Parser::parseMember(SyntaxKind parentKind, bool& anyLocalModules)
return &parseFunctionDeclaration(attributes, SyntaxKind::FunctionDeclaration,
TokenKind::EndFunctionKeyword, parentKind);
case TokenKind::CoverGroupKeyword:
return &parseCovergroupDeclaration(attributes, /* inClass */ false);
return &parseCovergroupDeclaration(attributes, /* inClass */ false,
/* hasBaseClass */ false);
case TokenKind::ClassKeyword:
return &parseClassDeclaration(attributes, Token());
case TokenKind::VirtualKeyword:
Expand Down Expand Up @@ -1428,7 +1429,7 @@ MemberSyntax* Parser::parseClassMember(bool isIfaceClass, bool hasBaseClass) {
return &result;
}
case TokenKind::CoverGroupKeyword: {
auto& result = parseCovergroupDeclaration(attributes, /* inClass */ true);
auto& result = parseCovergroupDeclaration(attributes, /* inClass */ true, hasBaseClass);
errorIfIface(result);
return &result;
}
Expand Down Expand Up @@ -1945,7 +1946,8 @@ MemberSyntax* Parser::parseCoverCrossMember() {
expect(TokenKind::Semicolon));
}

CovergroupDeclarationSyntax& Parser::parseCovergroupDeclaration(AttrList attributes, bool inClass) {
CovergroupDeclarationSyntax& Parser::parseCovergroupDeclaration(AttrList attributes, bool inClass,
bool hasBaseClass) {
auto keyword = consume();
auto extends = consumeIf(TokenKind::ExtendsKeyword);
auto name = expect(TokenKind::Identifier);
Expand Down Expand Up @@ -1993,13 +1995,13 @@ CovergroupDeclarationSyntax& Parser::parseCovergroupDeclaration(AttrList attribu

if (portList)
addDiag(diag::ExpectedToken, portList->getFirstToken().location()) << ";"sv;
else if (event)
if (event)
addDiag(diag::ExpectedToken, event->getFirstToken().location()) << ";"sv;

if (!inClass)
addDiag(diag::DerivedCovergroupNotInClass, extends.range());

// TODO: check no base
else if (!hasBaseClass)
addDiag(diag::DerivedCovergroupNoBase, extends.range());
}

auto semi = expect(TokenKind::Semicolon);
Expand Down
26 changes: 26 additions & 0 deletions tests/unittests/ast/CoverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,3 +654,29 @@ endclass
compilation.addSyntaxTree(tree);
NO_COMPILATION_ERRORS;
}

TEST_CASE("Covergroup missing base") {
auto options = optionsFor(LanguageVersion::v1800_2023);
auto tree = SyntaxTree::fromText(R"(
class base;
int i;
endclass
class derived extends base;
covergroup extends i;
endgroup
covergroup extends a;
endgroup
endclass
)",
options);

Compilation compilation(options);
compilation.addSyntaxTree(tree);

auto& diags = compilation.getAllDiagnostics();
REQUIRE(diags.size() == 2);
CHECK(diags[0].code == diag::UnknownCovergroupBase);
CHECK(diags[1].code == diag::UnknownCovergroupBase);
}
22 changes: 22 additions & 0 deletions tests/unittests/parsing/MemberParsingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,3 +1437,25 @@ endclass
CHECK(diagnostics[1].code == diag::FinalWithPure);
CHECK(diagnostics[2].code == diag::StaticFuncSpecifier);
}

TEST_CASE("Covergroup inheritance parsing errors") {
auto& text = R"(
class A;
covergroup extends cg(bit a) @b;
endgroup
endclass
covergroup extends foo;
endgroup
)";

parseCompilationUnit(text);

REQUIRE(diagnostics.size() == 6);
CHECK(diagnostics[0].code == diag::WrongLanguageVersion);
CHECK(diagnostics[1].code == diag::ExpectedToken);
CHECK(diagnostics[2].code == diag::ExpectedToken);
CHECK(diagnostics[3].code == diag::DerivedCovergroupNoBase);
CHECK(diagnostics[4].code == diag::WrongLanguageVersion);
CHECK(diagnostics[5].code == diag::DerivedCovergroupNotInClass);
}

0 comments on commit 972b19e

Please sign in to comment.