Skip to content

Commit

Permalink
Include inline genvars in generate block array member lists
Browse files Browse the repository at this point in the history
  • Loading branch information
MikePopoloski committed Jan 12, 2025
1 parent dfed278 commit 06b1a76
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 24 deletions.
48 changes: 28 additions & 20 deletions source/ast/symbols/BlockSymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,26 +671,27 @@ static uint64_t getGenerateLoopCount(const Scope& parent) {
return count ? count : 1;
}

GenerateBlockArraySymbol& GenerateBlockArraySymbol::fromSyntax(Compilation& compilation,
GenerateBlockArraySymbol& GenerateBlockArraySymbol::fromSyntax(Compilation& comp,
const LoopGenerateSyntax& syntax,
SymbolIndex scopeIndex,
const ASTContext& context,
uint32_t constructIndex) {
auto [name, loc] = getGenerateBlockName(*syntax.block);
auto result = compilation.emplace<GenerateBlockArraySymbol>(compilation, name, loc,
constructIndex);
auto result = comp.emplace<GenerateBlockArraySymbol>(comp, name, loc, constructIndex);
result->setSyntax(syntax);
result->setAttributes(*context.scope, syntax.attributes);

auto genvar = syntax.identifier;
if (genvar.isMissing())
return *result;

auto genvarSyntax = comp.emplace<IdentifierNameSyntax>(genvar);

// Walk up the tree a bit to see if we're nested inside another generate loop.
// If we are, we'll include that parent's array size in our decision about
// wether we've looped too many times within one generate block.
const uint64_t baseCount = getGenerateLoopCount(*context.scope);
const uint64_t loopLimit = compilation.getOptions().maxGenerateSteps;
const uint64_t loopLimit = comp.getOptions().maxGenerateSteps;

// If the loop initializer has a `genvar` keyword, we can use the name directly
// Otherwise we need to do a lookup to make sure we have the actual genvar somewhere.
Expand All @@ -707,46 +708,53 @@ GenerateBlockArraySymbol& GenerateBlockArraySymbol::fromSyntax(Compilation& comp
return *result;
}

compilation.noteReference(*symbol);
comp.noteReference(*symbol);
}
else {
// Fabricate a genvar symbol to live in this array since it was declared inline.
auto genvarSymbol = comp.emplace<GenvarSymbol>(genvar.valueText(), genvar.location());
genvarSymbol->setSyntax(*genvarSyntax);
result->addMember(*genvarSymbol);
}

SmallVector<const GenerateBlockSymbol*> entries;
auto createBlock = [&, blockLoc = loc](ConstantValue value, bool isUninstantiated) {
// Spec: each generate block gets their own scope, with an implicit
// localparam of the same name as the genvar.
auto block = compilation.emplace<GenerateBlockSymbol>(compilation, "", blockLoc,
(uint32_t)entries.size(),
isUninstantiated);
auto implicitParam = compilation.emplace<ParameterSymbol>(
genvar.valueText(), genvar.location(), true /* isLocal */, false /* isPort */);
auto block = comp.emplace<GenerateBlockSymbol>(comp, "", blockLoc, (uint32_t)entries.size(),
isUninstantiated);
auto implicitParam = comp.emplace<ParameterSymbol>(genvar.valueText(), genvar.location(),
true /* isLocal */, false /* isPort */);
implicitParam->setSyntax(*genvarSyntax);
comp.noteReference(*implicitParam);

block->addMember(*implicitParam);
block->setSyntax(*syntax.block);

addBlockMembers(*block, *syntax.block);

implicitParam->setType(compilation.getIntegerType());
implicitParam->setValue(compilation, std::move(value), /* needsCoercion */ false);
implicitParam->setType(comp.getIntegerType());
implicitParam->setValue(comp, std::move(value), /* needsCoercion */ false);
implicitParam->setIsFromGenvar(true);

block->arrayIndex = &implicitParam->getValue().integer();
entries.push_back(block);
};

// Bind the initialization expression.
auto& initial = Expression::bindRValue(compilation.getIntegerType(), *syntax.initialExpr,
auto& initial = Expression::bindRValue(comp.getIntegerType(), *syntax.initialExpr,
syntax.equals.range(), context);
ConstantValue initialVal = context.eval(initial);
if (!initialVal)
return *result;

// Fabricate a local variable that will serve as the loop iteration variable.
auto& iterScope = *compilation.emplace<StatementBlockSymbol>(compilation, "", loc,
StatementBlockKind::Sequential,
VariableLifetime::Automatic);
auto& local = *compilation.emplace<VariableSymbol>(genvar.valueText(), genvar.location(),
VariableLifetime::Automatic);
local.setType(compilation.getIntegerType());
auto& iterScope = *comp.emplace<StatementBlockSymbol>(comp, "", loc,
StatementBlockKind::Sequential,
VariableLifetime::Automatic);
auto& local = *comp.emplace<VariableSymbol>(genvar.valueText(), genvar.location(),
VariableLifetime::Automatic);
local.setType(comp.getIntegerType());
local.flags |= VariableFlags::CompilerGenerated;

iterScope.setTemporaryParent(*context.scope, scopeIndex);
Expand Down Expand Up @@ -820,7 +828,7 @@ GenerateBlockArraySymbol& GenerateBlockArraySymbol::fromSyntax(Compilation& comp
createBlock(index, isUninstantiated);
}

result->entries = entries.copy(compilation);
result->entries = entries.copy(comp);
if (entries.empty()) {
createBlock(SVInt(32, 0, true), true);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/unittests/ast/HierarchyTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ endmodule
Compilation compilation;
const auto& instance = evalModule(tree, compilation).body.memberAt<GenerateBlockArraySymbol>(1);

REQUIRE(std::ranges::distance(instance.members()) == 10);
REQUIRE(std::ranges::distance(instance.members()) == 11);

for (uint32_t i = 0; i < 10; i++) {
auto& leaf = instance.memberAt<GenerateBlockSymbol>(i).memberAt<InstanceSymbol>(1).body;
auto& leaf = instance.memberAt<GenerateBlockSymbol>(i + 1).memberAt<InstanceSymbol>(1).body;
auto& foo = leaf.find<ParameterSymbol>("foo");
CHECK(foo.getValue().integer() == i);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/unittests/ast/MemberTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ endmodule

auto& foo = compilation.getRoot()
.lookupName<GenerateBlockArraySymbol>("top.m1[2][1][3].asdf")
.memberAt<GenerateBlockSymbol>(1)
.memberAt<GenerateBlockSymbol>(2)
.memberAt<GenerateBlockSymbol>(1)
.find<VariableSymbol>("foo");

Expand Down
2 changes: 1 addition & 1 deletion tests/unittests/parsing/VisitorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,5 +747,5 @@ TEST_CASE("Visit all file") {
v.visitDefault(elem);
}));

CHECK(count == 1487);
CHECK(count == 1488);
}

0 comments on commit 06b1a76

Please sign in to comment.