mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Add warning on dist in constraints (#5264)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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); }
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user