Support extern constraint

This commit is contained in:
Wilson Snyder 2024-12-12 08:16:19 -05:00
parent 6e204ed0dd
commit a2f327f729
17 changed files with 215 additions and 90 deletions

View File

@ -19,7 +19,7 @@ Verilator 5.031 devel
* Support parameter names in pattern initialization (#5593) (#5596). [Greg Davill]
* Support randomize size constraints with restrictions (#5582 partial) (#5611). [Ryszard Rozak, Antmicro Ltd.]
* Support `default disable iff` and `$inferred_disable` (#4016). [Srinivasan Venkataramanan]
* Support `pure constraint`.
* Support `extern constraint` and `pure constraint`.
* Add `--no-std-waiver` and default reading of standard lint waivers file (#5607).
* Add `--no-std-package` as subset-alias of `--no-std` (#5607).
* Add `lint_off --contents` in configuration files (#5606).

View File

@ -68,8 +68,6 @@ class AstNodeFTask VL_NOT_FINAL : public AstNode {
bool m_taskPublic : 1; // Public task
bool m_attrIsolateAssign : 1; // User isolate_assignments attribute
bool m_classMethod : 1; // Class method
bool m_externProto : 1; // Extern prototype
bool m_externDef : 1; // Extern definition
bool m_prototype : 1; // Just a prototype
bool m_dpiExport : 1; // DPI exported
bool m_dpiImport : 1; // DPI imported
@ -77,6 +75,8 @@ class AstNodeFTask VL_NOT_FINAL : public AstNode {
bool m_dpiOpenChild : 1; // DPI import open array child wrapper
bool m_dpiTask : 1; // DPI import task (vs. void function)
bool m_isConstructor : 1; // Class constructor
bool m_isExternProto : 1; // Extern prototype
bool m_isExternDef : 1; // Extern definition
bool m_isHideLocal : 1; // Verilog local
bool m_isHideProtected : 1; // Verilog protected
bool m_dpiPure : 1; // DPI import pure (vs. virtual pure)
@ -97,8 +97,6 @@ protected:
, m_taskPublic{false}
, m_attrIsolateAssign{false}
, m_classMethod{false}
, m_externProto{false}
, m_externDef{false}
, m_prototype{false}
, m_dpiExport{false}
, m_dpiImport{false}
@ -106,6 +104,8 @@ protected:
, m_dpiOpenChild{false}
, m_dpiTask{false}
, m_isConstructor{false}
, m_isExternProto{false}
, m_isExternDef{false}
, m_isHideLocal{false}
, m_isHideProtected{false}
, m_dpiPure{false}
@ -144,10 +144,10 @@ public:
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool classMethod() const { return m_classMethod; }
void classMethod(bool flag) { m_classMethod = flag; }
bool isExternProto() const { return m_externProto; }
void isExternProto(bool flag) { m_externProto = flag; }
bool isExternDef() const { return m_externDef; }
void isExternDef(bool flag) { m_externDef = flag; }
bool isExternProto() const { return m_isExternProto; }
void isExternProto(bool flag) { m_isExternProto = flag; }
bool isExternDef() const { return m_isExternDef; }
void isExternDef(bool flag) { m_isExternDef = flag; }
bool prototype() const { return m_prototype; }
void prototype(bool flag) { m_prototype = flag; }
bool dpiExport() const { return m_dpiExport; }
@ -1021,7 +1021,12 @@ public:
class AstConstraint final : public AstNode {
// Constraint
// @astgen op1 := itemsp : List[AstNode]
// @astgen op2 := classOrPackagep : Optional[AstNode]
string m_name; // Name of constraint
VBaseOverride m_baseOverride; // BaseOverride (inital/final/extends)
bool m_isExternDef = false; // Extern prototype definition
bool m_isExternExplicit = false; // Explicit prototype declaration (has extern)
bool m_isExternProto = false; // Prototype declaration (implicit or explicit)
bool m_isKwdPure = false; // Pure constraint
bool m_isStatic = false; // Static constraint
public:
@ -1038,6 +1043,14 @@ public:
bool isPredictOptimizable() const override { return false; }
bool maybePointedTo() const override VL_MT_SAFE { return true; }
bool sameNode(const AstNode* /*samep*/) const override { return true; }
void baseOverride(const VBaseOverride& flag) { m_baseOverride = flag; }
VBaseOverride baseOverride() const { return m_baseOverride; }
bool isExternDef() const { return m_isExternDef; }
void isExternDef(bool flag) { m_isExternDef = flag; }
void isExternExplicit(bool flag) { m_isExternExplicit = flag; }
bool isExternExplicit() const { return m_isExternExplicit; }
void isExternProto(bool flag) { m_isExternProto = flag; }
bool isExternProto() const { return m_isExternProto; }
void isKwdPure(bool flag) { m_isKwdPure = flag; }
bool isKwdPure() const { return m_isKwdPure; }
void isStatic(bool flag) { m_isStatic = flag; }

View File

@ -368,12 +368,21 @@ void AstConsQueue::dumpJson(std::ostream& str) const {
}
void AstConstraint::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isExternDef()) str << " [EXTDEF]";
if (isExternExplicit())
str << " [PROTOEXP]";
else if (isExternProto())
str << " [PROTO]";
if (isKwdPure()) str << " [KWDPURE]";
if (isStatic()) str << " [STATIC]";
}
void AstConstraint::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isExternDef);
dumpJsonBoolFunc(str, isExternExplicit);
dumpJsonBoolFunc(str, isExternProto);
dumpJsonBoolFunc(str, isKwdPure);
dumpJsonBoolFunc(str, isStatic);
if (baseOverride().isAny()) dumpJsonStr(str, "baseOverride", baseOverride().ascii());
dumpJsonGen(str);
}
void AstConstraintExpr::dump(std::ostream& str) const {
@ -1657,9 +1666,11 @@ void AstCellInlineScope::dumpJson(std::ostream& str) const {
dumpJsonGen(str);
}
bool AstClass::isCacheableChild(const AstNode* nodep) {
return (VN_IS(nodep, Var) || VN_IS(nodep, Constraint) || VN_IS(nodep, EnumItemRef)
|| (VN_IS(nodep, NodeFTask) && !VN_AS(nodep, NodeFTask)->isExternProto())
|| VN_IS(nodep, CFunc));
return VN_IS(nodep, Var)
|| (VN_IS(nodep, Constraint) && !VN_AS(nodep, Constraint)->isExternProto())
|| VN_IS(nodep, EnumItemRef)
|| (VN_IS(nodep, NodeFTask) && !VN_AS(nodep, NodeFTask)->isExternProto())
|| VN_IS(nodep, CFunc);
}
AstClass* AstClass::baseMostClassp() {
AstClass* basep = this;
@ -2652,6 +2663,8 @@ void AstNodeFTask::dump(std::ostream& str) const {
if (dpiImport()) str << " [DPII]";
if (dpiOpenChild()) str << " [DPIOPENCHILD]";
if (dpiOpenParent()) str << " [DPIOPENPARENT]";
if (isExternDef()) str << " [EXTDEF]";
if (isExternProto()) str << " [EXTPROTO]";
if (prototype()) str << " [PROTOTYPE]";
if (pureVirtual()) str << " [PUREVIRTUAL]";
if (recursive()) str << " [RECURSIVE]";
@ -2689,6 +2702,8 @@ void AstNodeFTask::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, dpiImport);
dumpJsonBoolFunc(str, dpiOpenChild);
dumpJsonBoolFunc(str, dpiOpenParent);
dumpJsonBoolFunc(str, isExternDef);
dumpJsonBoolFunc(str, isExternProto);
dumpJsonBoolFunc(str, prototype);
dumpJsonBoolFunc(str, recursive);
dumpJsonBoolFunc(str, taskPublic);

View File

@ -1207,8 +1207,7 @@ class LinkDotFindVisitor final : public VNVisitor {
m_classOrPackagep = VN_AS(m_curSymp->nodep(), Class);
}
// Create symbol table for the task's vars
const string name
= std::string{nodep->isExternProto() ? "extern " : ""} + nodep->name();
const string name = (nodep->isExternProto() ? "extern "s : ""s) + nodep->name();
m_curSymp = m_statep->insertBlock(m_curSymp, name, nodep, m_classOrPackagep);
m_curSymp->fallbackp(upSymp);
// Convert the func's range to the output variable
@ -1299,7 +1298,35 @@ class LinkDotFindVisitor final : public VNVisitor {
}
void visit(AstConstraint* nodep) override {
VL_RESTORER(m_curSymp);
m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
// Change to appropriate package if extern declaration (vs definition)
VSymEnt* upSymp = m_curSymp;
if (nodep->classOrPackagep()) {
AstClassOrPackageRef* const cpackagerefp
= VN_CAST(nodep->classOrPackagep(), ClassOrPackageRef);
if (!cpackagerefp) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: extern constraint definition with class-in-class");
} else {
if (!cpackagerefp->classOrPackageSkipp()) {
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false,
"External definition :: reference");
}
AstClass* const classp = VN_CAST(cpackagerefp->classOrPackageSkipp(), Class);
if (!classp) {
nodep->v3error("Extern declaration's scope is not a defined class");
} else {
m_curSymp = m_statep->getNodeSym(classp);
upSymp = m_curSymp;
// Move it to proper spot under the target class
nodep->unlinkFrBack();
classp->addStmtsp(nodep);
nodep->classOrPackagep()->unlinkFrBack()->deleteTree();
}
}
}
// Set the class as package for iteration
const string name = (nodep->isExternProto() ? "extern "s : ""s) + nodep->name();
m_curSymp = m_statep->insertBlock(upSymp, name, nodep, m_classOrPackagep);
iterateChildren(nodep);
}
void visit(AstVar* nodep) override {
@ -3287,6 +3314,31 @@ class LinkDotResolveVisitor final : public VNVisitor {
UINFO(9, indent() << "set sym " << m_ds.ascii() << endl);
}
}
void visit(AstConstraint* nodep) override {
LINKDOT_VISIT_START();
UINFO(5, indent() << "visit " << nodep << endl);
checkNoDot(nodep);
if (nodep->isExternDef()) {
if (const VSymEnt* const foundp
= m_curSymp->findIdFallback("extern " + nodep->name())) {
const AstConstraint* const protop = VN_AS(foundp->nodep(), Constraint);
// Copy specifiers.
// External definition cannot have any specifiers, so no value will be overwritten.
nodep->isStatic(protop->isStatic());
} else {
nodep->v3error("extern not found that declares " + nodep->prettyNameQ());
}
}
if (nodep->isExternProto()) {
if (!m_curSymp->findIdFallback(nodep->name()) && !nodep->isExternExplicit()) {
nodep->v3error("Definition not found for extern " + nodep->prettyNameQ());
}
}
VL_RESTORER(m_curSymp);
VL_RESTORER(m_ds);
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
iterateChildren(nodep);
}
void visit(AstConstraintRef* nodep) override {
if (nodep->user3SetOnce()) return;
LINKDOT_VISIT_START();
@ -3819,14 +3871,14 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (nodep->isExternDef()) {
if (const VSymEnt* const foundp
= m_curSymp->findIdFallback("extern " + nodep->name())) {
const AstNodeFTask* const funcProtop = VN_AS(foundp->nodep(), NodeFTask);
const AstNodeFTask* const protop = VN_AS(foundp->nodep(), NodeFTask);
// Copy specifiers.
// External definition cannot have any specifiers, so no value will be overwritten.
nodep->isHideLocal(funcProtop->isHideLocal());
nodep->isHideProtected(funcProtop->isHideProtected());
nodep->isStatic(funcProtop->isStatic());
nodep->isVirtual(funcProtop->isVirtual());
nodep->lifetime(funcProtop->lifetime());
nodep->isHideLocal(protop->isHideLocal());
nodep->isHideProtected(protop->isHideProtected());
nodep->isStatic(protop->isStatic());
nodep->isVirtual(protop->isVirtual());
nodep->lifetime(protop->lifetime());
} else {
nodep->v3error("extern not found that declares " + nodep->prettyNameQ());
}

View File

@ -72,6 +72,16 @@ class LinkResolveVisitor final : public VNVisitor {
m_classp = nodep;
iterateChildren(nodep);
}
void visit(AstConstraint* nodep) override {
// V3LinkDot moved the isExternDef into the class, the extern proto was
// checked to exist, and now isn't needed
nodep->isExternDef(false);
if (nodep->isExternProto()) {
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
iterateChildren(nodep);
}
void visit(AstInitialAutomatic* nodep) override {
iterateChildren(nodep);
// Initial assignments under function/tasks can just be simple

View File

@ -4181,7 +4181,6 @@ function_subroutine_callNoMethod<nodeExprp>: // IEEE: function_subroutine
// // We implement randomize as a normal funcRef, since randomize isn't a keyword
// // Note yNULL is already part of expressions, so they come for free
| funcRef yWITH__CUR constraint_block { $$ = new AstWithParse{$2, $1, $3}; }
| funcRef yWITH__CUR '{' '}' { $$ = new AstWithParse{$2, $1, nullptr}; }
;
system_t_call<nodeStmtp>: // IEEE: system_tf_call (as task)
@ -7418,17 +7417,16 @@ memberQualOne<qualifiers>: // IEEE: property_qualifier + me
class_constraint<constraintp>: // ==IEEE: class_constraint
// // IEEE: constraint_declaration
constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew constraint_block
{ $$ = $4; $$->isStatic($1); $$->addItemsp($5); SYMP->popScope($$); }
| constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew '{' '}'
{ $$ = $4; $$->isStatic($1); SYMP->popScope($$); }
{ $$ = $4; $$->isStatic($1); $$->baseOverride($3); $$->addItemsp($5); SYMP->popScope($$); }
// // IEEE: constraint_prototype + constraint_prototype_qualifier
| constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew ';'
{ $$ = $4; $$->isStatic($1); SYMP->popScope($$); }
| yEXTERN constraintStaticE yCONSTRAINT constraintIdNew ';'
{ $$ = $4; $$->isStatic($1); SYMP->popScope($4);
BBUNSUP($1, "Unsupported: extern constraint"); }
{ $$ = $4; $$->isStatic($1); $$->baseOverride($3);
$$->isExternProto(true); SYMP->popScope($$); }
| yEXTERN constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew ';'
{ $$ = $5; $$->isStatic($2); $$->baseOverride($4);
$$->isExternProto(true); $$->isExternExplicit(true); SYMP->popScope($$); }
| yPURE constraintStaticE yCONSTRAINT constraintIdNew ';'
{ $$ = $4; $$->isKwdPure($1); $$->isStatic($1); SYMP->popScope($4); }
{ $$ = $4; $$->isKwdPure($1); $$->isStatic($2); SYMP->popScope($4); }
;
constraintIdNew<constraintp>: // IEEE: id part of class_constraint
@ -7438,7 +7436,8 @@ constraintIdNew<constraintp>: // IEEE: id part of class_constraint
;
constraint_block<nodep>: // ==IEEE: constraint_block
'{' constraint_block_itemList '}' { $$ = $2; }
'{' '}' { $$ = nullptr; }
| '{' constraint_block_itemList '}' { $$ = $2; }
//
| '{' error '}' { $$ = nullptr; }
| '{' constraint_block_itemList error '}' { $$ = $2; }
@ -7529,9 +7528,10 @@ dist_item<distItemp>: // ==IEEE: dist_item + dist_weight
$$ = nullptr; }
;
extern_constraint_declaration<nodep>: // ==IEEE: extern_constraint_declaration
constraintStaticE yCONSTRAINT dynamic_override_specifiersE packageClassScopeE idAny constraint_block
{ $$ = nullptr; BBUNSUP($<fl>2, "Unsupported: extern constraint"); }
extern_constraint_declaration<constraintp>: // ==IEEE: extern_constraint_declaration
constraintStaticE yCONSTRAINT dynamic_override_specifiersE packageClassScopeE constraintIdNew constraint_block
{ $$ = $5; $$->isStatic($1); $$->isExternDef(true);
$$->baseOverride($3); $$->classOrPackagep($4); $$->addItemsp($6); SYMP->popScope($5); }
;
constraintStaticE<cbool>: // IEEE: part of extern_constraint_declaration

View File

@ -9,6 +9,8 @@ class Packet;
constraint a { one > 0 && one < 2; }
constraint empty { }
endclass
module t (/*AUTOARG*/);

View File

@ -0,0 +1,21 @@
#!/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('simulator')
if not test.have_solver:
test.skip("No constraint solver installed")
test.compile(verilator_flags2=['-Wno-CONSTRAINTIGN'])
test.execute()
test.passes()

View File

@ -0,0 +1,41 @@
// 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 Packet;
rand int one;
rand int two;
extern function void f();
constraint cone;
extern constraint ctwo;
extern constraint cmissing; // Ok per IEEE 1800-2023 18.5.1
endclass
constraint Packet::cone { one > 0 && one < 2; }
constraint Packet::ctwo { two > 1 && two < 3; }
function void Packet::f();
endfunction
module t (/*AUTOARG*/);
Packet p;
int v;
initial begin
p = new;
v = p.randomize();
if (v != 1) $stop;
if (p.one != 1) $stop;
if (p.two != 2) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,7 @@
%Error: t/t_constraint_extern_bad.v:8:15: Definition not found for extern 'missing_bad'
8 | constraint missing_bad;
| ^~~~~~~~~~~
%Error: t/t_constraint_extern_bad.v:11:20: extern not found that declares 'missing_extern'
11 | constraint Packet::missing_extern { }
| ^~~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -9,8 +9,8 @@
import vltest_bootstrap
test.scenarios('vlt')
test.scenarios('linter')
test.lint(fails=True, expect_filename=test.golden_filename)
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 Packet;
constraint missing_bad;
endclass
constraint Packet::missing_extern { }
module t (/*AUTOARG*/);
endmodule

View File

@ -27,7 +27,7 @@
{"type":"VAR","name":"if_state_ok","addr":"(W)","loc":"d,13:13,13:24","dtypep":"(U)","origName":"if_state_ok","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"bit","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"array","addr":"(X)","loc":"d,15:13,15:18","dtypep":"(Y)","origName":"array","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"state","addr":"(Z)","loc":"d,17:11,17:16","dtypep":"(M)","origName":"state","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"string","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"FUNC","name":"strings_equal","addr":"(AB)","loc":"d,61:17,61:30","dtypep":"(U)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"strings_equal",
{"type":"FUNC","name":"strings_equal","addr":"(AB)","loc":"d,61:17,61:30","dtypep":"(U)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"isExternDef":false,"isExternProto":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"strings_equal",
"fvarp": [
{"type":"VAR","name":"strings_equal","addr":"(BB)","loc":"d,61:17,61:30","dtypep":"(U)","origName":"strings_equal","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":true,"isFuncLocal":true,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"bit","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
],"classOrPackagep": [],
@ -48,7 +48,7 @@
{"type":"VARREF","name":"strings_equal","addr":"(JB)","loc":"d,62:7,62:13","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []}
],"scopeNamep": []},
{"type":"FUNC","name":"new","addr":"(KB)","loc":"d,7:1,7:6","dtypep":"(LB)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []},
{"type":"FUNC","name":"new","addr":"(KB)","loc":"d,7:1,7:6","dtypep":"(LB)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"isExternDef":false,"isExternProto":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []},
{"type":"VAR","name":"constraint","addr":"(MB)","loc":"d,7:1,7:6","dtypep":"(NB)","origName":"constraint","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"MEMBER","dtypeName":"VlRandomizer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
],"activesp": [],"extendsp": []}
],"activesp": []}

View File

@ -3,5 +3,5 @@ Process::open: execvp(someimaginarysolver): No such file or directory
%Warning: Unable to communicate with SAT solver, please check its installation or specify a different one in VERILATOR_SOLVER environment variable.
... Tried: $ someimaginarysolver
%Error: t/t_constraint.v:23: Verilog $stop
%Error: t/t_constraint.v:25: Verilog $stop
Aborting...

View File

@ -17,7 +17,7 @@
"lhsp": [
{"type":"VARREF","name":"dotted","addr":"(X)","loc":"d,33:16,33:22","dtypep":"(S)","access":"WR","varp":"(R)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []},
{"type":"FUNC","name":"f","addr":"(Y)","loc":"d,35:13,35:14","dtypep":"(G)","method":false,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"f",
{"type":"FUNC","name":"f","addr":"(Y)","loc":"d,35:13,35:14","dtypep":"(G)","method":false,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"isExternDef":false,"isExternProto":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"f",
"fvarp": [
{"type":"VAR","name":"f","addr":"(Z)","loc":"d,35:13,35:14","dtypep":"(G)","origName":"f","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":true,"isFuncLocal":true,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"VAR","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
],"classOrPackagep": [],

View File

@ -1,8 +0,0 @@
%Error-UNSUPPORTED: t/t_randomize_extern.v:17:4: Unsupported: extern constraint
17 | extern constraint ex;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_randomize_extern.v:21:1: Unsupported: extern constraint
21 | constraint Packet::ex { header == 2; }
| ^~~~~~~~~~
%Error: Exiting due to

View File

@ -1,42 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
class Base;
pure constraint pur;
endclass
class Packet extends Base;
rand int header;
rand int length;
constraint pur { length == 3; }
extern constraint ex;
endclass
constraint Packet::ex { header == 2; }
module t (/*AUTOARG*/);
Packet p;
initial begin
int v;
v = p.randomize();
if (v != 1) $stop;
if (p.header != 2) $stop;
if (p.length != 3) $stop;
v = p.randomize(1);
if (v != 1) $stop;
if (p.header != 2) $stop;
if (p.length != 3) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule