Skip to content

Commit

Permalink
Make sequence no-match error be a warning instead
Browse files Browse the repository at this point in the history
  • Loading branch information
MikePopoloski committed Nov 17, 2024
1 parent bf26b09 commit 142cda7
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 78 deletions.
74 changes: 49 additions & 25 deletions include/slang/ast/expressions/AssertionExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,6 @@ class SLANG_EXPORT AssertionExpr {
/// Indicates whether the expression is invalid.
bool bad() const { return kind == AssertionExprKind::Invalid; }

/// Checks whether this assertion expression is nondegenerate or whether it has
/// properties of degeneracy (admitting empty matches or no matches at all).
bitmask<NondegeneracyStatus> checkNondegeneracy() const;

/// Computes possible clock ticks (delay) length of sequence under assertion expression.
std::optional<SequenceRange> computeSequenceLength() const;

/// Specifies binding behavior of property expressions as
/// it pertains to nondegeneracy checking.
enum class NondegeneracyRequirement {
Expand All @@ -151,6 +144,41 @@ class SLANG_EXPORT AssertionExpr {
NonOverlapOp,
};

/// A result structure for checking nondegeneracy.
struct NondegeneracyCheckResult {
/// The nondegeneracy status of the expression.
bitmask<NondegeneracyStatus> status;

/// The range of the expression that caused status
/// to contain NondegeneracyStatus::AdmitsNoMatch.
SourceRange noMatchRange;

/// Set to true if the expression is known to be always false.
bool isAlwaysFalse = false;

NondegeneracyCheckResult& operator|=(const NondegeneracyCheckResult& rhs) {
status |= rhs.status;
if (!noMatchRange.start()) {
noMatchRange = rhs.noMatchRange;
isAlwaysFalse = rhs.isAlwaysFalse;
}
return *this;
}

NondegeneracyCheckResult operator|(const NondegeneracyCheckResult& rhs) const {
auto result = *this;
result |= rhs;
return result;
}
};

/// Checks whether this assertion expression is nondegenerate or whether it has
/// properties of degeneracy (admitting empty matches or no matches at all).
NondegeneracyCheckResult checkNondegeneracy() const;

/// Computes possible clock ticks (delay) length of sequence under assertion expression.
std::optional<SequenceRange> computeSequenceLength() const;

static const AssertionExpr& bind(const syntax::SequenceExprSyntax& syntax,
const ASTContext& context, bool allowDisable = false);

Expand Down Expand Up @@ -230,9 +258,7 @@ class SLANG_EXPORT InvalidAssertionExpr : public AssertionExpr {
explicit InvalidAssertionExpr(const AssertionExpr* child) :
AssertionExpr(AssertionExprKind::Invalid), child(child) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const {
return NondegeneracyStatus::None;
}
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }

std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

Expand Down Expand Up @@ -263,7 +289,7 @@ struct SequenceRepetition {

/// Checks whether this assertion expression is nondegenerate or whether it has
/// properties of degeneracy (admitting empty matches or no matches at all).
bitmask<NondegeneracyStatus> checkNondegeneracy() const;
AssertionExpr::NondegeneracyCheckResult checkNondegeneracy() const;

/// Applies the repetition to the given range, scaling it and returning the result.
SequenceRange applyTo(SequenceRange other) const;
Expand All @@ -289,7 +315,7 @@ class SLANG_EXPORT SimpleAssertionExpr : public AssertionExpr {
isNullExpr(isNullExpr) {}

void requireSequence(const ASTContext& context, DiagCode code) const;
bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const;
NondegeneracyCheckResult checkNondegeneracyImpl() const;
std::optional<SequenceRange> computeSequenceLengthImpl() const;

static AssertionExpr& fromSyntax(const syntax::SimpleSequenceExprSyntax& syntax,
Expand Down Expand Up @@ -323,7 +349,7 @@ class SLANG_EXPORT SequenceConcatExpr : public AssertionExpr {
explicit SequenceConcatExpr(std::span<const Element> elements) :
AssertionExpr(AssertionExprKind::SequenceConcat), elements(elements) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const;
NondegeneracyCheckResult checkNondegeneracyImpl() const;
std::optional<SequenceRange> computeSequenceLengthImpl() const;

static AssertionExpr& fromSyntax(const syntax::DelayedSequenceExprSyntax& syntax,
Expand Down Expand Up @@ -358,7 +384,7 @@ class SLANG_EXPORT SequenceWithMatchExpr : public AssertionExpr {
AssertionExpr(AssertionExprKind::SequenceWithMatch), expr(expr), repetition(repetition),
matchItems(matchItems) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const;
NondegeneracyCheckResult checkNondegeneracyImpl() const;
std::optional<SequenceRange> computeSequenceLengthImpl() const;

static AssertionExpr& fromSyntax(const syntax::ParenthesizedSequenceExprSyntax& syntax,
Expand Down Expand Up @@ -394,7 +420,7 @@ class SLANG_EXPORT UnaryAssertionExpr : public AssertionExpr {
std::optional<SequenceRange> range) :
AssertionExpr(AssertionExprKind::Unary), op(op), expr(expr), range(range) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const { return {}; }
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }
std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

static AssertionExpr& fromSyntax(const syntax::UnaryPropertyExprSyntax& syntax,
Expand Down Expand Up @@ -431,7 +457,7 @@ class SLANG_EXPORT BinaryAssertionExpr : public AssertionExpr {

void requireSequence(const ASTContext& context, DiagCode code) const;

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const;
NondegeneracyCheckResult checkNondegeneracyImpl() const;
std::optional<SequenceRange> computeSequenceLengthImpl() const;

static AssertionExpr& fromSyntax(const syntax::BinarySequenceExprSyntax& syntax,
Expand Down Expand Up @@ -464,7 +490,7 @@ class SLANG_EXPORT FirstMatchAssertionExpr : public AssertionExpr {
std::span<const Expression* const> matchItems) :
AssertionExpr(AssertionExprKind::FirstMatch), seq(seq), matchItems(matchItems) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const;
NondegeneracyCheckResult checkNondegeneracyImpl() const;

std::optional<SequenceRange> computeSequenceLengthImpl() const {
return seq.computeSequenceLength();
Expand Down Expand Up @@ -497,9 +523,7 @@ class SLANG_EXPORT ClockingAssertionExpr : public AssertionExpr {
ClockingAssertionExpr(const TimingControl& clocking, const AssertionExpr& expr) :
AssertionExpr(AssertionExprKind::Clocking), clocking(clocking), expr(expr) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const {
return expr.checkNondegeneracy();
}
NondegeneracyCheckResult checkNondegeneracyImpl() const { return expr.checkNondegeneracy(); }

std::optional<SequenceRange> computeSequenceLengthImpl() const {
return expr.computeSequenceLength();
Expand Down Expand Up @@ -540,7 +564,7 @@ class SLANG_EXPORT StrongWeakAssertionExpr : public AssertionExpr {
StrongWeakAssertionExpr(const AssertionExpr& expr, Strength strength) :
AssertionExpr(AssertionExprKind::StrongWeak), expr(expr), strength(strength) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const { return {}; }
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }
std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

static AssertionExpr& fromSyntax(const syntax::StrongWeakPropertyExprSyntax& syntax,
Expand Down Expand Up @@ -576,7 +600,7 @@ class SLANG_EXPORT AbortAssertionExpr : public AssertionExpr {
AssertionExpr(AssertionExprKind::Abort), condition(condition), expr(expr), action(action),
isSync(isSync) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const { return {}; }
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }
std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

static AssertionExpr& fromSyntax(const syntax::AcceptOnPropertyExprSyntax& syntax,
Expand Down Expand Up @@ -610,7 +634,7 @@ class SLANG_EXPORT ConditionalAssertionExpr : public AssertionExpr {
AssertionExpr(AssertionExprKind::Conditional), condition(condition), ifExpr(ifExpr),
elseExpr(elseExpr) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const { return {}; }
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }
std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

static AssertionExpr& fromSyntax(const syntax::ConditionalPropertyExprSyntax& syntax,
Expand Down Expand Up @@ -655,7 +679,7 @@ class SLANG_EXPORT CaseAssertionExpr : public AssertionExpr {
AssertionExpr(AssertionExprKind::Case), expr(expr), items(items), defaultCase(defaultCase) {
}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const { return {}; }
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }
std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

static AssertionExpr& fromSyntax(const syntax::CasePropertyExprSyntax& syntax,
Expand Down Expand Up @@ -691,7 +715,7 @@ class SLANG_EXPORT DisableIffAssertionExpr : public AssertionExpr {
DisableIffAssertionExpr(const Expression& condition, const AssertionExpr& expr) :
AssertionExpr(AssertionExprKind::DisableIff), condition(condition), expr(expr) {}

bitmask<NondegeneracyStatus> checkNondegeneracyImpl() const { return {}; }
NondegeneracyCheckResult checkNondegeneracyImpl() const { return {}; }
std::optional<SequenceRange> computeSequenceLengthImpl() const { return {}; }

static AssertionExpr& fromSyntax(const syntax::DisableIffSyntax& syntax,
Expand Down
6 changes: 4 additions & 2 deletions scripts/diagnostics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -870,8 +870,8 @@ error ForkJoinAlwaysComb "fork-join is not allowed in {} procedure"
error BlockingInAlwaysFF "always_ff procedures cannot have blocking timing controls"
error AlwaysFFEventControl "always_ff procedure must have one and only one event control"
error SeqEmptyMatch "sequence must not admit an empty match"
error SeqNoMatch "sequence can never be matched"
error SeqOnlyEmpty "sequence admits only empty matches"
warning seq-no-match SeqNoMatch "sequence can never be matched"
warning event-const EventExpressionConstant "edge expression is constant"
warning empty-stmt EmptyStatement "extra ';' has no effect"
warning pointless-void-cast PointlessVoidCast "cast to void for void-returning function '{}' has no effect"
Expand All @@ -880,6 +880,7 @@ warning bad-procedural-force BadProceduralForce "lvalue of force/release must be
warning multibit-edge MultiBitEdge "edge of expression of type {} will only trigger on changes to the first bit"
note NoteWhileExpanding "while expanding {} '{}'"
note NoteExpandedHere "expanded here"
note NoteAlwaysFalse "expression is always false"

subsystem Types
error InvalidEnumBase "invalid enum base type {} (must be a single dimensional integer type)"
Expand Down Expand Up @@ -1160,7 +1161,8 @@ group default = { real-underflow real-overflow vector-overflow int-overflow unco
raw-protect-eof protected-envelope specify-param dup-timing-path invalid-pulsestyle
negative-timing-limit bad-procedural-force duplicate-defparam implicit-port-type-mismatch
split-distweight-op dpi-pure-task multibit-edge unknown-sys-name unknown-library
dup-config-rule unused-config-cell unused-config-instance specify-condition-expr }
dup-config-rule unused-config-cell unused-config-instance specify-condition-expr
seq-no-match }

group extra = { empty-member empty-stmt dup-import pointless-void-cast case-gen-none case-gen-dup
unused-result format-real ignored-slice task-ignored width-trunc dup-attr event-const
Expand Down
8 changes: 8 additions & 0 deletions scripts/warning_docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1478,3 +1478,11 @@ module m;
end
endmodule
```

-Wseq-no-match
Warns about a sequence expression that can never be matched.
```
module top;
assert property ((1'b1 ##1 1'b0) intersect (1'b1[*0] ##2 1'b1));
endmodule
```
Loading

0 comments on commit 142cda7

Please sign in to comment.