-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[slang] Introduce net aliases bits duplication checks #1045
[slang] Introduce net aliases bits duplication checks #1045
Conversation
I think with it LRM section 10.11 is done |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1045 +/- ##
=======================================
Coverage 94.76% 94.77%
=======================================
Files 191 191
Lines 47743 47825 +82
=======================================
+ Hits 45243 45325 +82
Misses 2500 2500
Continue to review full report in Codecov by Sentry.
|
49d4723
to
16b72d5
Compare
// Store any net alias bits to check it's possible intersections. | ||
// Since alias statements can appear anywhere module instance statements can appears | ||
// good option is to store aliased bits info in the module instance scope. | ||
mutable AliasMap* aliasedBits; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems unnecessary to have an alias map allocated for every instance. The rules about net alias overlap are global, so it seems fine to have just one alias map stored in the Compilation object that all aliases can access. Then you don't need a custom allocator for it either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reimplemented all in order to last commentary
source/ast/symbols/MemberSymbols.cpp
Outdated
@@ -2196,7 +2196,6 @@ NetAliasSymbol& NetAliasSymbol::fromSyntax(const ASTContext& parentContext, | |||
if (!netType.isError()) { | |||
SmallVector<const IdentifierNameSyntax*> implicitNetNames; | |||
Expression::findPotentiallyImplicitNets(*expr, context, implicitNetNames); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random newline deletion seems unrelated to the rest of the diff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
source/ast/symbols/MemberSymbols.cpp
Outdated
if (const auto* sym = processExpr(expr)) { | ||
const auto& eSelExpr = expr.template as<ElementSelectExpression>(); | ||
// If value can't be evaluated that means it is unbounded | ||
const auto evalVal = toInt(context.tryEval(eSelExpr.selector())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct in all cases. An example is when there is multiple selections of a multi-dimensional array. It's actually pretty tricky to figure out the statically assigned bits of an arbitrary expression -- that's essentially what the ValueDriver code in ValueSymbol.cpp is doing to be able to issue multi-driven errors. It occurs to me that it may make more sense to use that code to implement the net alias check. You could add a new flag to AssignFlags that says it's a net alias and do the check for overlap there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great Idea! The solution was reimplemented according to it!
16b72d5
to
4dd5370
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok yeah, this is way better. I left some additional comments to help simplify this a bit more.
source/ast/symbols/ValueSymbol.cpp
Outdated
@@ -7,6 +7,8 @@ | |||
//------------------------------------------------------------------------------ | |||
#include "slang/ast/symbols/ValueSymbol.h" | |||
|
|||
#include <iostream> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The iostream include isn't needed right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
source/ast/ASTContext.cpp
Outdated
@@ -136,7 +136,8 @@ void ASTContext::setAttributes(const Expression& expr, | |||
|
|||
void ASTContext::addDriver(const ValueSymbol& symbol, const Expression& longestStaticPrefix, | |||
bitmask<AssignFlags> assignFlags) const { | |||
if (flags.has(ASTFlags::NotADriver) || scope->isUninstantiated()) | |||
if ((flags.has(ASTFlags::NotADriver) && !assignFlags.has(AssignFlags::NetAlias)) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can get rid of this change if you simply don't use the NotADriver flag when binding the net alias expressions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -2119,16 +2124,18 @@ std::span<const Expression* const> NetAliasSymbol::getNetReferences() const { | |||
auto syntax = getSyntax(); | |||
SLANG_ASSERT(scope && syntax); | |||
|
|||
// TODO: there should be a global check somewhere that any given bit | |||
// of a net isn't aliased to the same target signal bit multiple times. | |||
bitwidth_t bitWidth = 0; | |||
bool issuedError = false; | |||
SmallVector<const Expression*> buffer; | |||
ASTContext context(*scope, LookupLocation::after(*this), | |||
ASTFlags::NonProcedural | ASTFlags::NotADriver); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Down here, you can remove the NotADriver
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The flag is needed to skip the first alias (the leftmost one) in order to prevent FP. I left it, but remove it after the first iteration of the loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following why the first alias expression should be exempt from the duplicate checking. There isn't anything special about the first alias vs any others; you can reverse the order without changing the behavior.
I do think we need more info included in the addDriver call though, since it's only an error if the overlap occurs with the same target net? Like you can alias the same range of bits from one net to multiple different nets, it's only error if it's the same nets each time. This example from the LRM I think won't pass with the current code?
module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
alias bus16[11:0] = low12;
alias bus16[15:4] = high12;
endmodule
module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
alias bus16 = {high12, low12[3:0]};
alias high12[7:0] = low12[11:4];
endmodule
Or maybe it will, but not if you reverse the ordering in the alias statements.
source/ast/symbols/MemberSymbols.cpp
Outdated
|
||
for (auto exprSyntax : syntax->as<NetAliasSyntax>().nets) { | ||
for (auto exprSyntax : nets) { | ||
auto& netRef = Expression::bind(*exprSyntax, context); | ||
if (!netRef.requireLValue(context)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And then here pass your new AssignFlag and then you won't need the additional addDriver call below I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
54382d4
to
1ea3267
Compare
source/ast/symbols/MemberSymbols.cpp
Outdated
@@ -2144,6 +2159,21 @@ std::span<const Expression* const> NetAliasSymbol::getNetReferences() const { | |||
|
|||
netRef.visit(visitor); | |||
buffer.push_back(&netRef); | |||
|
|||
if (exprSyntax != *nets.begin()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic seems confusing to me; you really just need to check whether the same symbol appears in more than one of the net alias expressions right? The aliasedSyms
map in the NetAliasVisitor is already tracking that; instead of insert_or_assign up above you can just check whether the insertion fails because the symbol already exists, in which case you can issue the error right there. Then you don't need any of this special casing for it here and the separate map tracking the same thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
solution was reimplemented by focusing on merge net alias expressions
aliasedSyms
map logic was reduced from NetAliasVisitor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My solution no longer ignores the leftoutermost net alias expression
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To relate net alias expressions to existing alias sybmols, I used a comparison of their syntaxes
it's not a best solution but in this case it is possible, since in aliases all symbols are global nets from the point of view of the module, in the future we need to come up with a better comparator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following why the first alias expression should be exempt from the duplicate checking. There isn't anything special about the first alias vs any others; you can reverse the order without changing the behavior.
I do think we need more info included in the addDriver call though, since it's only an error if the overlap occurs with the same target net? Like you can alias the same range of bits from one net to multiple different nets, it's only error if it's the same nets each time. This example from the LRM I think won't pass with the current code?
module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
alias bus16[11:0] = low12;
alias bus16[15:4] = high12;
endmodulemodule overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
alias bus16 = {high12, low12[3:0]};
alias high12[7:0] = low12[11:4];
endmodule
Or maybe it will, but not if you reverse the ordering in the alias statements.
Provided example works correctly regardless of the alias permutations.
@@ -2119,16 +2124,18 @@ std::span<const Expression* const> NetAliasSymbol::getNetReferences() const { | |||
auto syntax = getSyntax(); | |||
SLANG_ASSERT(scope && syntax); | |||
|
|||
// TODO: there should be a global check somewhere that any given bit | |||
// of a net isn't aliased to the same target signal bit multiple times. | |||
bitwidth_t bitWidth = 0; | |||
bool issuedError = false; | |||
SmallVector<const Expression*> buffer; | |||
ASTContext context(*scope, LookupLocation::after(*this), | |||
ASTFlags::NonProcedural | ASTFlags::NotADriver); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following why the first alias expression should be exempt from the duplicate checking. There isn't anything special about the first alias vs any others; you can reverse the order without changing the behavior.
I do think we need more info included in the addDriver call though, since it's only an error if the overlap occurs with the same target net? Like you can alias the same range of bits from one net to multiple different nets, it's only error if it's the same nets each time. This example from the LRM I think won't pass with the current code?
module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
alias bus16[11:0] = low12;
alias bus16[15:4] = high12;
endmodule
module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
alias bus16 = {high12, low12[3:0]};
alias high12[7:0] = low12[11:4];
endmodule
Or maybe it will, but not if you reverse the ordering in the alias statements.
848e6c6
to
3a128e4
Compare
closes #947 |
include/slang/ast/SemanticFacts.h
Outdated
SlicedPort = 1 << 7 | ||
SlicedPort = 1 << 7, | ||
|
||
// The assignment declares net alias |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use triple comments to make it show up in documentation, like other entries above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
include/slang/ast/ASTContext.h
Outdated
@@ -298,6 +299,9 @@ class SLANG_EXPORT ASTContext { | |||
/// Various flags that control how AST creation is performed. | |||
bitmask<ASTFlags> flags; | |||
|
|||
/// Placeholder for storing currently processed net alias | |||
const NetAliasSymbol* netAlias = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to not add another member to ASTContext if we can help it, especially since net aliases are very rare. I think you should be able to reuse instanceOrProc
for this. We can rename it to something more generic like "relevantSymbol" maybe and then you can set it when you create the specialized ASTContext for checking net aliases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
source/ast/symbols/MemberSymbols.cpp
Outdated
|
||
// Preprocessing net alias expressions to relate them to existing net aliases. | ||
const NetAliasSymbol* current = this; | ||
for (auto exprSyntax : nets) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here still seems wrong. Consider this simple example:
module m;
wire [1:0] a, b, c;
alias a = b[1:0];
alias c = b[1:0];
endmodule
which results in the following error (when it should not):
source:5:15: error: it is not allowed to specify an alias from an individual signal to itself or to specify a given alias more than once
alias c = b[1:0];
^~~~~~
source:4:15: note: alias declared here
alias a = b[1:0];
^~~~~~
I don't think this mergeOrAddNetAlias idea works or is even necessary really. We don't need a compilation-wide map. Each net can already track which bits have been aliased using the driver mechanism. I think what you need to do is to do an addDriver() call across the cartesian product of the aliases in a given net alias statement. Instead of the "containing symbol" being the net alias, instead you make it the net it's being aliased to.
As an example:
alias a = b = c;
you want the following sequence of addDriver calls to be made, where the argument here is what gets set as the "containing symbol" inside ValueDriver:
a.addDriver(b);
a.addDriver(c);
b.addDriver(a);
b.addDriver(c);
c.addDriver(a);
c.addDriver(b);
And then I think the existing logic will just do the right thing without the need for a global map or comparing syntax nodes to each other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for delay
solution was reimplemented according to your suggestion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but i need to add more complex tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and fix CI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI was fixed and new tests were added
622f998
to
cd0a5d0
Compare
44d93ee
to
677fa45
Compare
8fed29e
to
6cff3b3
Compare
6cff3b3
to
bc6e58e
Compare
Introduce 2 new net alias bit checks from SystemVerilog LRM section 10.11: