Add warning on dist in constraints (#5264)

This commit is contained in:
Arkadiusz Kozdra
2024-07-15 21:01:33 -04:00
committed by GitHub
parent 34e37d7bd0
commit 0a9b31bb30
8 changed files with 99 additions and 32 deletions
+33
View File
@@ -1142,6 +1142,39 @@ public:
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
};
class AstDist final : public AstNodeExpr {
// @astgen op1 := exprp : AstNodeExpr
// @astgen op2 := itemsp : List[AstDistItem]
public:
AstDist(FileLine* fl, AstNodeExpr* exprp, AstDistItem* itemsp)
: ASTGEN_SUPER_Inside(fl) {
this->exprp(exprp);
this->addItemsp(itemsp);
dtypeSetBit();
}
ASTGEN_MEMBERS_AstDist;
string emitVerilog() override { return "%l dist { %r }"; }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return false; } // NA
};
class AstDistItem final : public AstNodeExpr {
// Constraint distribution item
// @astgen op1 := rangep : AstNodeExpr
// @astgen op2 := weightp : AstNodeExpr
bool m_isWhole = false; // True for weight ':/', false for ':='
public:
AstDistItem(FileLine* fl, AstNodeExpr* rangep, AstNodeExpr* weightp)
: ASTGEN_SUPER_DistItem(fl) {
this->rangep(rangep);
this->weightp(weightp);
}
ASTGEN_MEMBERS_AstDistItem;
string emitVerilog() override { return "%l "s + (m_isWhole ? ":/" : ":=") + " %r"; }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return false; } // NA
void isWhole(bool flag) { m_isWhole = flag; }
bool isWhole() const { return m_isWhole; }
};
class AstDot final : public AstNodeExpr {
// A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
// These are eliminated in the link stage
-18
View File
@@ -1064,24 +1064,6 @@ public:
bool same(const AstNode*) const override { return true; }
string path() const { return m_path; }
};
class AstDistItem final : public AstNode {
// Constraint distribution item
// @astgen op1 := rangep : AstNodeExpr
// @astgen op2 := weightp : AstNodeExpr
bool m_isWhole = false; // True for weight ':/', false for ':='
public:
AstDistItem(FileLine* fl, AstNodeExpr* rangep, AstNodeExpr* weightp)
: ASTGEN_SUPER_DistItem(fl) {
this->rangep(rangep);
this->weightp(weightp);
}
ASTGEN_MEMBERS_AstDistItem;
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool same(const AstNode* /*samep*/) const override { return true; }
void isWhole(bool flag) { m_isWhole = flag; }
bool isWhole() const { return m_isWhole; }
};
class AstDpiExport final : public AstNode {
// We could put an AstNodeFTaskRef instead of the verilog function name,
// however we're not *calling* it, so that seems somehow wrong.
+5
View File
@@ -328,6 +328,11 @@ class ConstraintExprVisitor final : public VNVisitor {
// Fall back to "(ite cond then else)"
visit(static_cast<AstNodeTriop*>(nodep));
}
void visit(AstDist* nodep) override {
nodep->v3warn(CONSTRAINTIGN, "Constraint expression ignored (unsupported)");
nodep->replaceWith(new AstSFormatF{nodep->fileline(), "true", false, nullptr});
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void visit(AstReplicate* nodep) override {
// Biop, but RHS is harmful
if (editFormat(nodep)) return;
+45 -2
View File
@@ -2150,8 +2150,11 @@ class WidthVisitor final : public VNVisitor {
userIterateAndNext(nodep->rangesp(), WidthVP{SELF, BOTH}.p());
}
void visit(AstDistItem* nodep) override {
userIterate(nodep->rangep(), WidthVP{SELF, BOTH}.p());
userIterate(nodep->weightp(), WidthVP{SELF, BOTH}.p());
userIterate(nodep->rangep(), m_vup);
if (m_vup->prelim()) { // First stage evaluation
userIterate(nodep->weightp(), WidthVP{SELF, BOTH}.p());
}
nodep->dtypep(nodep->rangep()->dtypep());
}
void visit(AstVar* nodep) override {
// if (debug()) nodep->dumpTree("- InitPre: ");
@@ -2574,6 +2577,46 @@ class WidthVisitor final : public VNVisitor {
}
}
}
void visit(AstDist* nodep) override {
userIterateAndNext(nodep->exprp(), WidthVP{CONTEXT_DET, PRELIM}.p());
for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) {
nextip = itemp->nextp(); // iterate may cause the node to get replaced
VL_DO_DANGLING(userIterate(itemp, WidthVP{CONTEXT_DET, PRELIM}.p()), itemp);
}
AstBasicDType* dtype = VN_CAST(nodep->exprp()->dtypep(), BasicDType);
AstNodeDType* subDTypep = nullptr;
nodep->dtypeSetBit();
if (dtype && dtype->isString()) {
nodep->dtypeSetString();
subDTypep = nodep->findStringDType();
} else if (dtype && dtype->isDouble()) {
nodep->dtypeSetDouble();
subDTypep = nodep->findDoubleDType();
} else {
// Take width as maximum across all items
int width = nodep->exprp()->width();
int mwidth = nodep->exprp()->widthMin();
for (const AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) {
width = std::max(width, itemp->width());
mwidth = std::max(mwidth, itemp->widthMin());
}
subDTypep = nodep->findLogicDType(width, mwidth, nodep->exprp()->dtypep()->numeric());
}
iterateCheck(nodep, "Dist expression", nodep->exprp(), CONTEXT_DET, FINAL, subDTypep,
EXTEND_EXP);
for (AstDistItem *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) {
nextip
= VN_AS(itemp->nextp(), DistItem); // iterate may cause the node to get replaced
iterateCheck(nodep, "Dist Item", itemp, CONTEXT_DET, FINAL, subDTypep, EXTEND_EXP);
}
if (debug() >= 9) nodep->dumpTree("- dist-out: ");
nodep->dtypep(subDTypep);
}
void visit(AstInside* nodep) override {
userIterateAndNext(nodep->exprp(), WidthVP{CONTEXT_DET, PRELIM}.p());
for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) {
+2 -2
View File
@@ -5057,7 +5057,7 @@ expr<nodeExprp>: // IEEE: part of expression/constant_expression/
//
// // IEEE: expression_or_dist - here to avoid reduce problems
// // "expr yDIST '{' dist_list '}'"
| ~l~expr yDIST '{' dist_list '}' { $$ = $1; $4->deleteTree(); }
| ~l~expr yDIST '{' dist_list '}' { $$ = new AstDist{$2, $1, $4}; }
;
fexpr<nodeExprp>: // For use as first part of statement (disambiguates <=)
@@ -7383,7 +7383,7 @@ constraint_set<nodep>: // ==IEEE: constraint_set
| '{' constraint_expressionList '}' { $$ = $2; }
;
dist_list<nodep>: // ==IEEE: dist_list
dist_list<distItemp>: // ==IEEE: dist_list
dist_item { $$ = $1; }
| dist_list ',' dist_item { $$ = addNextNull($1, $3); }
;