diff --git a/tools/netlist/TODO.md b/tools/netlist/TODO.md index c9b20c348..da2bb96b9 100644 --- a/tools/netlist/TODO.md +++ b/tools/netlist/TODO.md @@ -1,6 +1,11 @@ To dos ====== +- Bug report: + + In ast::ElementSelectExpr.syntax does not correspond to selector source + range and includes entire variable reference + selectors. + - Bug report: module m; diff --git a/tools/netlist/include/Netlist.h b/tools/netlist/include/Netlist.h index 05b548596..c8b4b4436 100644 --- a/tools/netlist/include/Netlist.h +++ b/tools/netlist/include/Netlist.h @@ -67,10 +67,12 @@ struct VariableSelectorBase { /// A variable selector representing an element selector. struct VariableElementSelect : public VariableSelectorBase { + const ast::ElementSelectExpression &expr; ConstantValue index; - VariableElementSelect(ConstantValue index) : - VariableSelectorBase(VariableSelectorKind::ElementSelect), index(std::move(index)) {} + VariableElementSelect(ast::ElementSelectExpression const& expr, ConstantValue index) : + VariableSelectorBase(VariableSelectorKind::ElementSelect), expr(expr), + index(std::move(index)) {} static bool isKind(VariableSelectorKind otherKind) { return otherKind == VariableSelectorKind::ElementSelect; @@ -86,19 +88,24 @@ struct VariableElementSelect : public VariableSelectorBase { return *intValue; } - std::string toString() const override { return fmt::format("[{}]", index.toString()); } + std::string toString() const override { + if (indexIsConstant()) { + return fmt::format("[{}]", index.toString()); + } else { + return fmt::format("[{}]", expr.syntax->toString()); + } + } }; /// A variable selector representing a range selector. struct VariableRangeSelect : public VariableSelectorBase { + const ast::RangeSelectExpression &expr; ConstantValue leftIndex, rightIndex; - ast::RangeSelectionKind selectionKind; - VariableRangeSelect(ConstantValue leftIndex, ConstantValue rightIndex, - ast::RangeSelectionKind selectionKind) : + VariableRangeSelect(ast::RangeSelectExpression const& expr, ConstantValue leftIndex, + ConstantValue rightIndex) : VariableSelectorBase(VariableSelectorKind::RangeSelect), - leftIndex(std::move(leftIndex)), rightIndex(std::move(rightIndex)), - selectionKind(selectionKind) {} + expr(expr), leftIndex(std::move(leftIndex)), rightIndex(std::move(rightIndex)) {} static bool isKind(VariableSelectorKind otherKind) { return otherKind == VariableSelectorKind::RangeSelect; @@ -125,7 +132,28 @@ struct VariableRangeSelect : public VariableSelectorBase { } std::string toString() const override { - return fmt::format("[{}:{}]", leftIndex.toString(), rightIndex.toString()); + std::string left; + if (leftIndexIsConstant()) { + left = leftIndex.toString(); + } else { + left = expr.left().syntax->toString(); + } + std::string right; + if (rightIndexIsConstant()) { + right = rightIndex.toString(); + } else { + right = expr.right().syntax->toString(); + } + switch (expr.getSelectionKind()) { + case ast::RangeSelectionKind::Simple: + return fmt::format("[{}:{}]", left, right); + case ast::RangeSelectionKind::IndexedUp: + return fmt::format("[{}+:{}]", left, right); + case ast::RangeSelectionKind::IndexedDown: + return fmt::format("[{}-:{}]", left, right); + default: + SLANG_UNREACHABLE; + } } }; @@ -243,12 +271,17 @@ class NetlistVariableReference : public NetlistNode { NetlistNode(NodeKind::VariableReference, symbol), expression(expr), leftOperand(leftOperand) {} - void addElementSelect(const ConstantValue& index) { - selectors.emplace_back(std::make_unique(index)); + void addElementSelect(ast::ElementSelectExpression const &expr, const ConstantValue& index) { + selectors.emplace_back(std::make_unique(expr, index)); + //std::cout << "Add elem select "<< expr.syntax->toString() << "\n"; } - void addRangeSelect(const ConstantValue& leftIndex, const ConstantValue& rightIndex, ast::RangeSelectionKind selectionKind) { - selectors.emplace_back(std::make_unique(leftIndex, rightIndex, selectionKind)); + + void addRangeSelect(ast::RangeSelectExpression const& expr, + const ConstantValue& leftIndex, const ConstantValue& rightIndex) { + selectors.emplace_back(std::make_unique(expr, leftIndex, rightIndex)); + //std::cout << "Add range select "<< expr.left().syntax->toString() << " : " << expr.right().syntax->toString() << "\n"; } + void addMemberAccess(std::string_view name) { selectors.emplace_back(std::make_unique(name)); } diff --git a/tools/netlist/include/NetlistVisitor.h b/tools/netlist/include/NetlistVisitor.h index f74106cb6..f54dc9b43 100644 --- a/tools/netlist/include/NetlistVisitor.h +++ b/tools/netlist/include/NetlistVisitor.h @@ -76,14 +76,15 @@ class VariableReferenceVisitor : public ast::ASTVisitorkind == ast::ExpressionKind::ElementSelect) { - auto index = selector->as().selector().eval(evalCtx); - node.addElementSelect(index); + const auto& expr = selector->as(); + auto index = expr.selector().eval(evalCtx); + node.addElementSelect(expr, index); } else if (selector->kind == ast::ExpressionKind::RangeSelect) { - auto& rangeSelectExpr = selector->as(); - auto leftIndex = rangeSelectExpr.left().eval(evalCtx); - auto rightIndex = rangeSelectExpr.right().eval(evalCtx); - node.addRangeSelect(leftIndex, rightIndex, rangeSelectExpr.getSelectionKind()); + const auto& expr = selector->as(); + auto leftIndex = expr.left().eval(evalCtx); + auto rightIndex = expr.right().eval(evalCtx); + node.addRangeSelect(expr, leftIndex, rightIndex); } else if (selector->kind == ast::ExpressionKind::MemberAccess) { node.addMemberAccess(selector->as().member.name); diff --git a/tools/netlist/include/SplitVariables.h b/tools/netlist/include/SplitVariables.h index 64002baa4..29b79bcaf 100644 --- a/tools/netlist/include/SplitVariables.h +++ b/tools/netlist/include/SplitVariables.h @@ -224,7 +224,7 @@ class AnalyseVariableReference { return handleScalarElementSelect(type, range); } else if (selectorsIt->get()->isRangeSelect()) { - switch (selectorsIt->get()->as().selectionKind) { + switch (selectorsIt->get()->as().expr.getSelectionKind()) { case ast::RangeSelectionKind::Simple: return handleScalarRangeSelect(type, range); case ast::RangeSelectionKind::IndexedUp: @@ -249,7 +249,7 @@ class AnalyseVariableReference { return handleArrayElementSelect(type, range); } else if (selectorsIt->get()->isRangeSelect()) { - switch (selectorsIt->get()->as().selectionKind) { + switch (selectorsIt->get()->as().expr.getSelectionKind()) { case ast::RangeSelectionKind::Simple: return handleArrayRangeSelect(type, range); case ast::RangeSelectionKind::IndexedUp: diff --git a/tools/netlist/tests/VariableSelectorsTests.cpp b/tools/netlist/tests/VariableSelectorsTests.cpp index d068f7be4..594d1cc0d 100644 --- a/tools/netlist/tests/VariableSelectorsTests.cpp +++ b/tools/netlist/tests/VariableSelectorsTests.cpp @@ -38,6 +38,8 @@ module m (input int a); foo[3:1][2:1][1] = 0; foo[7:4][6:5][5] = 0; foo[a] = 0; + foo[a+:2][a] = 0; + foo[a+:2][a+:2][a] = 0; end endmodule )"); @@ -45,6 +47,12 @@ endmodule compilation.addSyntaxTree(tree); NO_COMPILATION_ERRORS; auto netlist = createNetlist(compilation); + //For (auto &node : netlist) { + // if (node->kind == NodeKind::VariableReference) + // { + // std::cout << "node " << node->as().toString()<<"\n"; + // } + //} CHECK(getBitRange(netlist, "foo") == ConstantRange(0, 31)); CHECK(getBitRange(netlist, "foo[0]") == ConstantRange(0, 0)); CHECK(getBitRange(netlist, "foo[1]") == ConstantRange(1, 1)); @@ -56,8 +64,7 @@ endmodule CHECK(getBitRange(netlist, "foo[7:4][6:5]") == ConstantRange(5, 6)); CHECK(getBitRange(netlist, "foo[3:1][2:1][1]") == ConstantRange(1, 1)); CHECK(getBitRange(netlist, "foo[7:4][6:5][5]") == ConstantRange(5, 5)); - // Can't lookup foo[a] in the netlist. - //CHECK(getBitRange(netlist, "foo[a]") == ConstantRange(0, 31)); + CHECK(getBitRange(netlist, "foo[a]") == ConstantRange(0, 31)); } TEST_CASE("Packed 1D array element and range") {