Skip to content

Commit

Permalink
Add variants for range selectors
Browse files Browse the repository at this point in the history
Refactor expression
Start adding logic for non-constant selects
  • Loading branch information
jameshanlon committed Aug 29, 2023
1 parent 51b28fe commit ea6a193
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 18 deletions.
20 changes: 17 additions & 3 deletions tools/netlist/include/Netlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ struct VariableElementSelect : public VariableSelectorBase {
return otherKind == VariableSelectorKind::ElementSelect;
}

bool indexIsConstant() const {
return !index.bad();
}

int32_t getIndexInt() const {
auto intValue = index.integer().as<int32_t>();
SLANG_ASSERT(intValue && "could not convert index to int32_t");
Expand All @@ -90,14 +94,24 @@ struct VariableRangeSelect : public VariableSelectorBase {
ConstantValue leftIndex, rightIndex;
ast::RangeSelectionKind selectionKind;

VariableRangeSelect(ConstantValue leftIndex, ConstantValue rightIndex, ast::RangeSelectionKind selectionKind) :
VariableSelectorBase(VariableSelectorKind::RangeSelect), leftIndex(std::move(leftIndex)),
rightIndex(std::move(rightIndex)), selectionKind(selectionKind) {}
VariableRangeSelect(ConstantValue leftIndex, ConstantValue rightIndex,
ast::RangeSelectionKind selectionKind) :
VariableSelectorBase(VariableSelectorKind::RangeSelect),
leftIndex(std::move(leftIndex)), rightIndex(std::move(rightIndex)),
selectionKind(selectionKind) {}

static bool isKind(VariableSelectorKind otherKind) {
return otherKind == VariableSelectorKind::RangeSelect;
}

bool leftIndexIsConstant() const {
return !leftIndex.bad();
}

bool rightIndexIsConstant() const {
return !rightIndex.bad();
}

int32_t getLeftIndexInt() const {
auto intValue = leftIndex.integer().as<int32_t>();
SLANG_ASSERT(intValue && "could not convert left index to int32_t");
Expand Down
71 changes: 57 additions & 14 deletions tools/netlist/include/SplitVariables.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,13 @@ class AnalyseVariableReference {
}
}

ConstantRange handleScalarElementSelect(const slang::ast::Type &type, ConstantRange range) {
ConstantRange handleScalarElementSelect(const slang::ast::Type& type, ConstantRange range) {
const auto& elementSelector = selectorsIt->get()->as<VariableElementSelect>();
if (!elementSelector.indexIsConstant()) {
// If the selector is not a constant, then return the whole scalar as
// the range.
return {range.lower(), (int32_t) type.getBitWidth()};
}
SLANG_ASSERT(elementSelector.getIndexInt() >= range.lower());
SLANG_ASSERT(elementSelector.getIndexInt() <= range.upper());
int32_t index = range.lower() + elementSelector.getIndexInt();
Expand All @@ -99,8 +104,10 @@ class AnalyseVariableReference {

ConstantRange handleScalarRangeSelect(const slang::ast::Type &type, ConstantRange range) {
const auto& rangeSelector = selectorsIt->get()->as<VariableRangeSelect>();
int32_t leftIndex = rangeSelector.getLeftIndexInt();
int32_t rightIndex = rangeSelector.getRightIndexInt();
int32_t leftIndex = rangeSelector.getLeftIndexInt();
//if (!rangeSelector.leftIndexIsConstant()) {
//}
SLANG_ASSERT(rightIndex <= leftIndex);
SLANG_ASSERT(rightIndex >= range.lower());
SLANG_ASSERT(leftIndex <= range.upper());
Expand All @@ -114,8 +121,19 @@ class AnalyseVariableReference {
}
}

ConstantRange handleScalarRangeSelectUp(const slang::ast::Type &type, ConstantRange range) {
}

ConstantRange handleScalarRangeSelectDown(const slang::ast::Type &type, ConstantRange range) {
}

ConstantRange handleArrayElementSelect(const slang::ast::Type &type, ConstantRange range) {
const auto& elementSelector = selectorsIt->get()->as<VariableElementSelect>();
if (!elementSelector.indexIsConstant()) {
// If the selector is not a constant, then return the whole scalar as
// the range.
return {range.lower(), (int32_t) type.getBitWidth()};
}
int32_t index = elementSelector.getIndexInt();
auto arrayRange = getArrayRange(type);
SLANG_ASSERT(index >= arrayRange.lower());
Expand Down Expand Up @@ -155,6 +173,12 @@ class AnalyseVariableReference {
}
}

ConstantRange handleArrayRangeSelectUp(const slang::ast::Type &type, ConstantRange range) {
}

ConstantRange handleArrayRangeSelectDown(const slang::ast::Type &type, ConstantRange range) {
}

ConstantRange handleStructMemberAccess(const slang::ast::Type &type, ConstantRange range) {
//const auto& packedStruct = type.getCanonicalType().as<slang::ast::PackedStructType>();
//SLANG_ASSERT(selectorsIt->get()->kind == VariableSelectorKind::MemberAccess);
Expand All @@ -174,6 +198,15 @@ class AnalyseVariableReference {
return {0, 0};
}


// Multiple range selectors have only the effect of the last one.
// Eg x[3:0][2:1] <=> x[2:1] or x[2:1][2] <=> x[2].
inline bool ignoreSelector() {
return selectorsIt->get()->isRangeSelect() &&
std::next(selectorsIt) != node.selectors.end() &&
std::next(selectorsIt)->get()->isArraySelect();
}

/// Given a variable reference with zero or more selectors, determine the
/// bit range that is accessed.
ConstantRange getBitRangeImpl(const slang::ast::Type &type, ConstantRange range) {
Expand All @@ -183,39 +216,49 @@ class AnalyseVariableReference {
}
// Simple vector
if (type.isPredefinedInteger() || type.isScalar()) {
if (selectorsIt->get()->isRangeSelect() &&
std::next(selectorsIt) != node.selectors.end() &&
std::next(selectorsIt)->get()->isArraySelect()) {
// Multiple range selectors have only the effect of
// the last one. Eg x[3:0][2:1] <=> x[2:1] or x[2:1][2] <=>
// x[2].
if (ignoreSelector()) {
selectorsIt++;
return getBitRangeImpl(type, range);
}
if (selectorsIt->get()->isElementSelect()) {
return handleScalarElementSelect(type, range);
}
else if (selectorsIt->get()->isRangeSelect()) {
return handleScalarRangeSelect(type, range);
switch (selectorsIt->get()->as<VariableRangeSelect>().selectionKind) {
case ast::RangeSelectionKind::Simple:
return handleScalarRangeSelect(type, range);
case ast::RangeSelectionKind::IndexedUp:
return handleScalarRangeSelectUp(type, range);
case ast::RangeSelectionKind::IndexedDown:
return handleScalarRangeSelectDown(type, range);
default:
SLANG_UNREACHABLE;
}
}
else {
SLANG_ASSERT(0 && "unsupported scalar selector");
}
}
// Packed or unpacked array
else if (type.isArray()) {
if (selectorsIt->get()->isRangeSelect() &&
std::next(selectorsIt) != node.selectors.end() &&
std::next(selectorsIt)->get()->isArraySelect()) {
// Multiple range selectors.
if (ignoreSelector()) {
selectorsIt++;
return getBitRangeImpl(type, range);
}
if (selectorsIt->get()->isElementSelect()) {
return handleArrayElementSelect(type, range);
}
else if (selectorsIt->get()->isRangeSelect()) {
return handleArrayRangeSelect(type, range);
switch (selectorsIt->get()->as<VariableRangeSelect>().selectionKind) {
case ast::RangeSelectionKind::Simple:
return handleArrayRangeSelect(type, range);
case ast::RangeSelectionKind::IndexedUp:
return handleArrayRangeSelectUp(type, range);
case ast::RangeSelectionKind::IndexedDown:
return handleArrayRangeSelectDown(type, range);
default:
SLANG_UNREACHABLE;
}
}
else {
SLANG_ASSERT(0 && "unsupported array selector");
Expand Down
5 changes: 4 additions & 1 deletion tools/netlist/tests/VariableSelectorsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ConstantRange getBitRange(Netlist &netlist, std::string_view variableSyntax) {

TEST_CASE("Scalar element and range") {
auto tree = SyntaxTree::fromText(R"(
module m;
module m (input int a);
int foo;
always_comb begin
foo = 0;
Expand All @@ -37,6 +37,7 @@ module m;
foo[7:4][6:5] = 0;
foo[3:1][2:1][1] = 0;
foo[7:4][6:5][5] = 0;
foo[a] = 0;
end
endmodule
)");
Expand All @@ -55,6 +56,8 @@ 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));
}

TEST_CASE("Packed 1D array element and range") {
Expand Down

0 comments on commit ea6a193

Please sign in to comment.