Add error on soft constraints of randc

This commit is contained in:
Wilson Snyder 2024-11-09 12:45:55 -05:00
parent d230ccd716
commit 4969125e5a
8 changed files with 75 additions and 19 deletions

View File

@ -20,7 +20,7 @@ Verilator 5.031 devel
* Add error on `wait` with missing `.triggered` (#4457).
* Add error when improperly storing to parameter (#5147). [Gökçe Aydos]
* Add coverage point hierarchy to coverage reports (#5575) (#5576). [Andrew Nolte]
* Add error on `solve before` of `randc` variable.
* Add error on `solve before` or soft constraints of `randc` variable.
* Fix can't locate scope error in interface task delayed assignment (#5462) (#5568). [Zhou Shen]
* Fix BLKANDNBLK for for VARXREFs (#5569). [Todd Strader]
* Fix VPI error instead of fatal for vpi_get_value() on large signals (#5571). [Todd Strader]

View File

@ -2763,14 +2763,16 @@ public:
class AstConstraintExpr final : public AstNodeStmt {
// Constraint expression
// @astgen op1 := exprp : AstNodeExpr
bool m_isSoft = false; // Soft constraint expression
bool m_isDisableSoft = false; // Disable soft constraint expression
bool m_isSoft = false; // Soft constraint expression
public:
AstConstraintExpr(FileLine* fl, AstNodeExpr* exprp)
: ASTGEN_SUPER_ConstraintExpr(fl) {
this->exprp(exprp);
}
ASTGEN_MEMBERS_AstConstraintExpr;
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool same(const AstNode* /*samep*/) const override { return true; }

View File

@ -376,6 +376,16 @@ void AstConstraint::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isStatic);
dumpJsonGen(str);
}
void AstConstraintExpr::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isDisableSoft()) str << " [DISSOFT]";
if (isSoft()) str << " [SOFT]";
}
void AstConstraintExpr::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isDisableSoft);
dumpJsonBoolFunc(str, isSoft);
dumpJsonGen(str);
}
AstConst* AstConst::parseParamLiteral(FileLine* fl, const string& literal) {
bool success = false;
if (literal[0] == '"') {

View File

@ -131,7 +131,9 @@ class RandomizeMarkVisitor final : public VNVisitor {
BaseToDerivedMap m_baseToDerivedMap; // Mapping from base classes to classes that extend them
AstClass* m_classp = nullptr; // Current class
AstNode* m_constraintExprp = nullptr; // Current constraint expression
AstConstraintBefore* m_constraintBeforep = nullptr; // Current before constraint
AstConstraintExpr* m_constraintExprp = nullptr; // Current constraint expression
AstNode* m_constraintExprGenp = nullptr; // Current constraint or constraint if expression
AstNodeModule* m_modp; // Current module
AstNodeStmt* m_stmtp = nullptr; // Current statement
std::set<AstNodeVarRef*> m_staticRefs; // References to static variables under `with` clauses
@ -402,50 +404,57 @@ class RandomizeMarkVisitor final : public VNVisitor {
}
}
void visit(AstConstraintBefore* nodep) override {
nodep->foreach([&](AstVarRef* const refp) {
if (refp->varp() && refp->varp()->isRandC()) {
nodep->v3error(
"Randc variables not allowed in 'solve before' (IEEE 1800-2023 18.5.9)");
}
});
VL_RESTORER(m_constraintBeforep);
m_constraintBeforep = nodep;
iterateChildrenConst(nodep);
}
void visit(AstConstraintExpr* nodep) override {
VL_RESTORER(m_constraintExprp);
m_constraintExprp = nodep;
VL_RESTORER(m_constraintExprGenp);
m_constraintExprGenp = nodep;
iterateChildrenConst(nodep);
}
void visit(AstConstraintIf* nodep) override {
{
VL_RESTORER(m_constraintExprp);
m_constraintExprp = nodep;
VL_RESTORER(m_constraintExprGenp);
m_constraintExprGenp = nodep;
iterateConst(nodep->condp());
}
iterateAndNextConstNull(nodep->thensp());
iterateAndNextConstNull(nodep->elsesp());
}
void visit(AstNodeVarRef* nodep) override {
if (!m_constraintExprp) return;
if (nodep->varp()->isRandC()) {
if (m_constraintExprp && m_constraintExprp->isSoft()) {
nodep->v3error(
"Randc variables not allowed in 'constraint soft' (IEEE 1800-2023 18.5.13.1)");
} else if (m_constraintBeforep) {
nodep->v3error(
"Randc variables not allowed in 'solve before' (IEEE 1800-2023 18.5.9)");
}
}
if (!m_constraintExprGenp) return;
if (nodep->varp()->lifetime().isStatic()) m_staticRefs.emplace(nodep);
if (!nodep->varp()->rand().isRandomizable()) return;
for (AstNode* backp = nodep; backp != m_constraintExprp && !backp->user1();
for (AstNode* backp = nodep; backp != m_constraintExprGenp && !backp->user1();
backp = backp->backp())
backp->user1(true);
}
void visit(AstMemberSel* nodep) override {
if (!m_constraintExprp) return;
if (!m_constraintExprGenp) return;
if (VN_IS(nodep->fromp(), LambdaArgRef)) {
if (!nodep->varp()->rand().isRandomizable()) return;
for (AstNode* backp = nodep; backp != m_constraintExprp && !backp->user1();
for (AstNode* backp = nodep; backp != m_constraintExprGenp && !backp->user1();
backp = backp->backp())
backp->user1(true);
}
}
void visit(AstArraySel* nodep) override {
if (!m_constraintExprp) return;
for (AstNode* backp = nodep; backp != m_constraintExprp && !backp->user1();
if (!m_constraintExprGenp) return;
for (AstNode* backp = nodep; backp != m_constraintExprGenp && !backp->user1();
backp = backp->backp())
backp->user1(true);
iterateChildrenConst(nodep);

View File

@ -1,5 +1,5 @@
%Error: t/t_randomize_before_randc_bad.v:11:29: Randc variables not allowed in 'solve before' (IEEE 1800-2023 18.5.9)
%Error: t/t_randomize_before_randc_bad.v:11:45: Randc variables not allowed in 'solve before' (IEEE 1800-2023 18.5.9)
: ... note: In instance 't'
11 | constraint raint2_bad { solve b1 before b2; }
| ^~~~~
| ^~
%Error: Exiting due to

View File

@ -0,0 +1,5 @@
%Error: t/t_randomize_soft_randc_bad.v:10:28: Randc variables not allowed in 'constraint soft' (IEEE 1800-2023 18.5.13.1)
: ... note: In instance 't'
10 | constraint c_bad { soft rc > 4; }
| ^~
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('linter')
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,14 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
class Cls1;
randc int rc;
constraint c_bad { soft rc > 4; } // Bad, no soft on randc
endclass
module t (/*AUTOARG*/);
endmodule