Support randomize() class method and rand

This commit is contained in:
Krzysztof Bieganski 2020-12-07 23:55:22 +01:00 committed by GitHub
parent cd248f6bd7
commit cf7ea06b5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 646 additions and 6 deletions

View File

@ -228,6 +228,7 @@ RAW_OBJS = \
V3PreShell.o \
V3Premit.o \
V3ProtectLib.o \
V3Randomize.o \
V3Reloop.o \
V3Scope.o \
V3Scoreboard.o \

View File

@ -1484,6 +1484,11 @@ public:
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
int itemCount() const {
size_t count = 0;
for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++;
return count;
}
};
class AstParseTypeDType final : public AstNodeDType {
@ -1892,6 +1897,7 @@ private:
bool m_attrSFormat : 1; // User sformat attribute
bool m_attrSplitVar : 1; // declared with split_var metacomment
bool m_fileDescr : 1; // File descriptor
bool m_isRand : 1; // Random variable
bool m_isConst : 1; // Table contains constant data
bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic)
bool m_isPulldown : 1; // Tri0
@ -2081,6 +2087,7 @@ public:
void sc(bool flag) { m_sc = flag; }
void scSensitive(bool flag) { m_scSensitive = flag; }
void primaryIO(bool flag) { m_primaryIO = flag; }
void isRand(bool flag) { m_isRand = flag; }
void isConst(bool flag) { m_isConst = flag; }
void isStatic(bool flag) { m_isStatic = flag; }
void isIfaceParent(bool flag) { m_isIfaceParent = flag; }
@ -2149,6 +2156,7 @@ public:
bool isSigUserRdPublic() const { return m_sigUserRdPublic; }
bool isSigUserRWPublic() const { return m_sigUserRWPublic; }
bool isTrace() const { return m_trace; }
bool isRand() const { return m_isRand; }
bool isConst() const { return m_isConst; }
bool isStatic() const { return m_isStatic; }
bool isFuncLocal() const { return m_funcLocal; }
@ -5450,9 +5458,9 @@ public:
: (m_urandom ? "%f$urandom()" : "%f$random()");
}
virtual string emitC() override {
return m_reset
? "VL_RAND_RESET_%nq(%nw, %P)"
: seedp() ? "VL_RANDOM_SEEDED_%nq%lq(%nw, %P, %li)" : "VL_RANDOM_%nq(%nw, %P)";
return m_reset ? "VL_RAND_RESET_%nq(%nw, %P)"
: seedp() ? "VL_RANDOM_SEEDED_%nq%lq(%nw, %P, %li)"
: "VL_RANDOM_%nq(%nw, %P)";
}
virtual bool cleanOut() const override { return true; }
virtual bool isGateOptimizable() const override { return false; }

View File

@ -101,6 +101,7 @@ class V3Global final {
bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols
bool m_dpi = false; // Need __Dpi include files
bool m_useParallelBuild = false; // Use parallel build for model
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
// Memory address to short string mapping (for debug)
typedef std::unordered_map<const void*, std::string> PtrToIdMap; // The map type
@ -158,6 +159,8 @@ public:
}
void useParallelBuild(bool flag) { m_useParallelBuild = flag; }
bool useParallelBuild() const { return m_useParallelBuild; }
void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; }
bool useRandomizeMethods() const { return m_useRandomizeMethods; }
const std::string& ptrToId(const void* p);
};

View File

@ -112,7 +112,16 @@ private:
virtual void visit(AstNodeFTask* nodep) override {
// NodeTask: Remember its name for later resolution
// Remember the existing symbol table scope
if (m_classp) nodep->classMethod(true);
if (m_classp) {
if (nodep->name() == "pre_randomize" || nodep->name() == "post_randomize") {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: " << nodep->prettyNameQ());
} else if (nodep->name() == "randomize") {
nodep->v3error(nodep->prettyNameQ()
<< " is a predefined class method; redefinition not allowed (IEEE "
"1800-2017 18.6.3)");
}
nodep->classMethod(true);
}
// V3LinkDot moved the isExternDef into the class, the extern proto was
// checked to exist, and now isn't needed
nodep->isExternDef(false);

View File

@ -50,7 +50,7 @@ struct VMemberQualifiers {
struct {
uint32_t m_local : 1; // Local class item (ignored until warning implemented)
uint32_t m_protected : 1; // Protected class item (ignored until warning implemented)
uint32_t m_rand : 1; // Rand property/member qualifier (ignored until supported)
uint32_t m_rand : 1; // Rand property/member qualifier
uint32_t m_randc : 1; // Randc property/member qualifier (ignored until supported)
uint32_t m_virtual : 1; // Virtual property/method qualifier
uint32_t m_automatic : 1; // Automatic property/method qualifier
@ -83,8 +83,8 @@ struct VMemberQualifiers {
}
void applyToNodes(AstVar* nodesp) const {
for (AstVar* nodep = nodesp; nodep; nodep = VN_CAST(nodep->nextp(), Var)) {
// Ignored for now: m_rand
// Ignored for now: m_randc
if (m_rand) nodep->isRand(true);
if (m_local) nodep->isHideLocal(true);
if (m_protected) nodep->isHideProtected(true);
if (m_automatic) nodep->lifetime(VLifetime::AUTOMATIC);

273
src/V3Randomize.cpp Normal file
View File

@ -0,0 +1,273 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Expression width calculations
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2020 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
//
//*************************************************************************
// V3Randomize's Transformations:
//
// Each randomize() method call:
// Mark class of object on which randomize() is called
// Mark all classes that inherit from previously marked classed
// Mark all classes whose instances are randomized member variables of marked classes
// Each marked class:
// define a virtual randomize() method that randomizes its random variables
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include "V3Randomize.h"
//######################################################################
// Visitor that marks classes needing a randomize() method
class RandomizeMarkVisitor final : public AstNVisitor {
private:
// NODE STATE
// Cleared on Netlist
// AstClass::user1() -> bool. Set true to indicate needs randomize processing
AstUser1InUse m_inuser1;
typedef std::unordered_set<AstClass*> DerivedSet;
typedef std::unordered_map<AstClass*, DerivedSet> BaseToDerivedMap;
BaseToDerivedMap m_baseToDerivedMap; // Mapping from base classes to classes that extend them
// METHODS
VL_DEBUG_FUNC;
void markMembers(AstClass* nodep) {
for (auto* classp = nodep; classp;
classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) {
for (auto* memberp = classp->stmtsp(); memberp; memberp = memberp->nextp()) {
// If member is rand and of class type, mark its class
if (VN_IS(memberp, Var) && VN_CAST(memberp, Var)->isRand()) {
if (auto* classRefp = VN_CAST(memberp->dtypep(), ClassRefDType)) {
auto* classp = classRefp->classp();
markMembers(classp);
markDerived(classp);
classRefp->classp()->user1(true);
}
}
}
}
}
void markDerived(AstClass* nodep) {
const auto it = m_baseToDerivedMap.find(nodep);
if (it != m_baseToDerivedMap.end()) {
for (auto* classp : it->second) {
classp->user1(true);
markMembers(classp);
markDerived(classp);
}
}
}
void markAllDerived() {
for (auto p : m_baseToDerivedMap) {
if (p.first->user1()) markDerived(p.first);
}
}
// VISITORS
virtual void visit(AstClass* nodep) override {
iterateChildren(nodep);
if (nodep->extendsp()) {
// Save pointer to derived class
auto* basep = nodep->extendsp()->classp();
m_baseToDerivedMap[basep].insert(nodep);
}
}
virtual void visit(AstMethodCall* nodep) override {
iterateChildren(nodep);
if (nodep->name() != "randomize") return;
if (AstClassRefDType* classRefp = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType)) {
auto* classp = classRefp->classp();
classp->user1(true);
markMembers(classp);
}
}
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
public:
// CONSTRUCTORS
explicit RandomizeMarkVisitor(AstNetlist* nodep) {
iterate(nodep);
markAllDerived();
}
virtual ~RandomizeMarkVisitor() override = default;
};
//######################################################################
// Visitor that defines a randomize method where needed
class RandomizeVisitor final : public AstNVisitor {
private:
// NODE STATE
// Cleared on Netlist
// AstClass::user1() -> bool. Set true to indicate needs randomize processing
// AstEnumDType::user2() -> AstVar*. Pointer to table with enum values
// AstUser1InUse m_inuser1; (Allocated for use in RandomizeMarkVisitor)
AstUser2InUse m_inuser2;
// STATE
size_t m_enumValueTabCount = 0; // Number of tables with enum values created
// METHODS
VL_DEBUG_FUNC;
AstVar* enumValueTabp(AstEnumDType* nodep) {
if (nodep->user2p()) return VN_CAST(nodep->user2p(), Var);
UINFO(9, "Construct Venumvaltab " << nodep << endl);
AstNodeArrayDType* vardtypep
= new AstUnpackArrayDType(nodep->fileline(), nodep->dtypep(),
new AstRange(nodep->fileline(), nodep->itemCount(), 0));
AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, nullptr);
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP,
"__Venumvaltab_" + cvtToStr(m_enumValueTabCount++), vardtypep);
varp->isConst(true);
varp->isStatic(true);
varp->valuep(initp);
// Add to root, as don't know module we are in, and aids later structure sharing
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
UASSERT_OBJ(nodep->itemsp(), nodep, "Enum without items");
for (AstEnumItem* itemp = nodep->itemsp(); itemp;
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
AstConst* vconstp = VN_CAST(itemp->valuep(), Const);
UASSERT_OBJ(vconstp, nodep, "Enum item without constified value");
initp->addValuep(vconstp->cloneTree(false));
}
nodep->user2p(varp);
return varp;
}
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeVarRef* varrefp, int offset = 0,
AstMemberDType* memberp = nullptr) {
if (auto* structDtp
= VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : varrefp->dtypep()->skipRefp(),
StructDType)) {
AstNodeStmt* stmtsp = nullptr;
offset += memberp ? memberp->lsb() : 0;
for (auto* memberp = structDtp->membersp(); memberp;
memberp = VN_CAST(memberp->nextp(), MemberDType)) {
auto* randp = newRandStmtsp(fl, stmtsp ? varrefp->cloneTree(false) : varrefp,
offset, memberp);
if (stmtsp) {
stmtsp->addNext(randp);
} else {
stmtsp = randp;
}
}
return stmtsp;
} else {
AstNodeMath* valp;
if (auto* enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
: varrefp->dtypep()->subDTypep(),
EnumDType)) {
AstVarRef* tabRefp = new AstVarRef(fl, enumValueTabp(enumDtp), VAccess::READ);
tabRefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
auto* randp = new AstRand(fl, nullptr, false);
auto* moddivp = new AstModDiv(fl, randp, new AstConst(fl, enumDtp->itemCount()));
randp->dtypep(varrefp->findBasicDType(AstBasicDTypeKwd::UINT32));
moddivp->dtypep(enumDtp);
valp = new AstArraySel(fl, tabRefp, moddivp);
} else {
valp = new AstRand(fl, nullptr, false);
valp->dtypep(memberp ? memberp->dtypep() : varrefp->varp()->dtypep());
}
return new AstAssign(fl,
new AstSel(fl, varrefp, offset + (memberp ? memberp->lsb() : 0),
memberp ? memberp->width() : varrefp->width()),
valp);
}
}
// VISITORS
virtual void visit(AstClass* nodep) override {
iterateChildren(nodep);
if (!nodep->user1()) return; // Doesn't need randomize, or already processed
UINFO(9, "Define randomize() for " << nodep << endl);
auto* funcp = V3Randomize::newRandomizeFunc(nodep);
auto* fvarp = VN_CAST(funcp->fvarp(), Var);
funcp->addStmtsp(new AstAssign(
nodep->fileline(), new AstVarRef(nodep->fileline(), fvarp, VAccess::WRITE),
new AstConst(nodep->fileline(), AstConst::WidthedValue(), 32, 1)));
for (auto* classp = nodep; classp;
classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) {
for (auto* memberp = classp->stmtsp(); memberp; memberp = memberp->nextp()) {
auto* memberVarp = VN_CAST(memberp, Var);
if (!memberVarp || !memberVarp->isRand()) continue;
auto* dtypep = memberp->dtypep()->skipRefp();
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)) {
auto* refp = new AstVarRef(nodep->fileline(), memberVarp, VAccess::WRITE);
auto* stmtp = newRandStmtsp(nodep->fileline(), refp);
funcp->addStmtsp(stmtp);
} else if (auto* classRefp = VN_CAST(dtypep, ClassRefDType)) {
auto* refp = new AstVarRef(nodep->fileline(), memberVarp, VAccess::WRITE);
auto* memberFuncp = V3Randomize::newRandomizeFunc(classRefp->classp());
auto* callp = new AstMethodCall(nodep->fileline(), refp, "randomize", nullptr);
callp->taskp(memberFuncp);
callp->dtypeFrom(memberFuncp);
funcp->addStmtsp(new AstAssign(
nodep->fileline(), new AstVarRef(nodep->fileline(), fvarp, VAccess::WRITE),
new AstAnd(nodep->fileline(),
new AstVarRef(nodep->fileline(), fvarp, VAccess::READ),
callp)));
} else {
memberp->v3warn(E_UNSUPPORTED,
"Unsupported: random member variables with type "
<< memberp->dtypep()->prettyDTypeNameQ());
}
}
}
nodep->user1(false);
}
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
public:
// CONSTRUCTORS
explicit RandomizeVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~RandomizeVisitor() override = default;
};
//######################################################################
// Randomize method class functions
void V3Randomize::randomizeNetlist(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl);
{
RandomizeMarkVisitor markVisitor(nodep);
RandomizeVisitor visitor(nodep);
}
V3Global::dumpCheckGlobalTree("randomize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
AstFunc* V3Randomize::newRandomizeFunc(AstClass* nodep) {
auto* funcp = VN_CAST(nodep->findMember("randomize"), Func);
if (!funcp) {
auto* dtypep
= nodep->findBitDType(32, 32, VSigning::SIGNED); // IEEE says int return of 0/1
auto* fvarp = new AstVar(nodep->fileline(), AstVarType::MEMBER, "randomize", dtypep);
fvarp->lifetime(VLifetime::AUTOMATIC);
fvarp->funcLocal(true);
fvarp->funcReturn(true);
fvarp->direction(VDirection::OUTPUT);
funcp = new AstFunc(nodep->fileline(), "randomize", nullptr, fvarp);
funcp->dtypep(dtypep);
funcp->classMethod(true);
funcp->isVirtual(nodep->isExtended());
nodep->addMembersp(funcp);
nodep->repairCache();
}
return funcp;
}

32
src/V3Randomize.h Normal file
View File

@ -0,0 +1,32 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Node attributes/ expression widths
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2020 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
//
//*************************************************************************
#ifndef _V3RANDOMIZE_METHOD_H_
#define _V3RANDOMIZE_METHOD_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Ast.h"
class V3Randomize final {
public:
static void randomizeNetlist(AstNetlist* nodep);
static AstFunc* newRandomizeFunc(AstClass* nodep);
};
#endif // Guard

View File

@ -70,6 +70,7 @@
#include "V3Width.h"
#include "V3Number.h"
#include "V3Const.h"
#include "V3Randomize.h"
#include "V3String.h"
#include "V3Task.h"
@ -2937,6 +2938,10 @@ private:
void methodCallClass(AstMethodCall* nodep, AstClassRefDType* adtypep) {
// No need to width-resolve the class, as it was done when we did the child
AstClass* first_classp = adtypep->classp();
if (nodep->name() == "randomize") {
v3Global.useRandomizeMethods(true);
V3Randomize::newRandomizeFunc(first_classp);
}
UASSERT_OBJ(first_classp, nodep, "Unlinked");
for (AstClass* classp = first_classp; classp;) {
if (AstNodeFTask* ftaskp = VN_CAST(classp->findMember(nodep->name()), NodeFTask)) {

View File

@ -75,6 +75,7 @@
#include "V3PreShell.h"
#include "V3Premit.h"
#include "V3ProtectLib.h"
#include "V3Randomize.h"
#include "V3Reloop.h"
#include "V3Scope.h"
#include "V3Scoreboard.h"
@ -179,6 +180,9 @@ static void process() {
// Before we do dead code elimination and inlining, or we'll lose it.
if (v3Global.opt.coverage()) V3Coverage::coverage(v3Global.rootp());
// Add randomize() class methods if they are used by the design
if (v3Global.useRandomizeMethods()) V3Randomize::randomizeNetlist(v3Global.rootp());
// Push constants, but only true constants preserving liveness
// so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..."
V3Const::constifyAllLive(v3Global.rootp());

View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 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
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,136 @@
// 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
typedef enum bit[15:0] {
ONE = 3,
TWO = 5,
THREE = 8,
FOUR = 13
} Enum;
typedef struct packed {
int a;
bit b;
Enum c;
} StructInner;
typedef struct packed {
bit x;
StructInner s;
Enum y;
longint z;
} StructOuter;
class BaseCls;
endclass
class Inner;
rand logic[7:0] a;
rand logic[15:0] b;
rand logic[3:0] c;
rand logic[11:0] d;
int e;
function new;
a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
endfunction
endclass
class DerivedCls extends BaseCls;
rand Inner i;
rand int j;
int k;
rand Enum l;
function new;
i = new;
j = 0;
k = 0;
l = ONE;
endfunction
endclass
class OtherCls;
logic[63:0] v;
rand logic[63:0] w;
rand logic[47:0] x;
rand logic[31:0] y;
rand logic[23:0] z;
rand StructOuter str;
function new;
v = 0;
w = 0;
x = 0;
y = 0;
z = 0;
str = '{x: 1'b0, y: ONE, z: 64'd0, s: '{a: 32'd0, b: 1'b0, c: ONE}};
endfunction
endclass
module t (/*AUTOARG*/);
bit ok = 0;
longint checksum;
task checksum_next(longint x);
checksum = x ^ {checksum[62:0],checksum[63]^checksum[2]^checksum[0]};
endtask;
DerivedCls derived;
OtherCls other;
BaseCls base;
initial begin
int rand_result;
longint prev_checksum;
for (int i = 0; i < 10; i++) begin
derived = new;
other = new;
base = derived;
rand_result = base.randomize();
rand_result = other.randomize();
if (!(derived.l inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.s.c inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.y inside {ONE, TWO, THREE, FOUR})) $stop;
if (derived.i.e != 0) $stop;
if (derived.k != 0) $stop;
if (other.v != 0) $stop;
checksum = 0;
checksum_next(longint'(derived.i.a));
checksum_next(longint'(derived.i.b));
checksum_next(longint'(derived.i.c));
checksum_next(longint'(derived.j));
checksum_next(longint'(derived.l));
checksum_next(longint'(other.w));
checksum_next(longint'(other.x));
checksum_next(longint'(other.y));
checksum_next(longint'(other.z));
checksum_next(longint'(other.str.x));
checksum_next(longint'(other.str.y));
checksum_next(longint'(other.str.z));
checksum_next(longint'(other.str.s.a));
checksum_next(longint'(other.str.s.b));
checksum_next(longint'(other.str.s.c));
$write("checksum: %d\n", checksum);
if (i > 0 && checksum != prev_checksum) begin
ok = 1;
end
prev_checksum = checksum;
end
if (ok) begin
$write("*-* All Finished *-*\n");
$finish;
end
else $stop;
end
endmodule

View File

@ -0,0 +1,7 @@
%Error: t/t_randomize_method_bad.v:8:17: 'randomize' is a predefined class method; redefinition not allowed (IEEE 1800-2017 18.6.3)
8 | function int randomize;
| ^~~~~~~~~
%Error: t/t_randomize_method_bad.v:14:18: 'randomize' is a predefined class method; redefinition not allowed (IEEE 1800-2017 18.6.3)
14 | function void randomize(int x);
| ^~~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 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
scenarios(simulator => 1);
compile(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,19 @@
// 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 Cls1;
function int randomize;
return 1;
endfunction
endclass
class Cls2;
function void randomize(int x);
endfunction
endclass
module t (/*AUTOARG*/);
endmodule

View File

@ -0,0 +1,17 @@
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variables with type 'int[string]'
: ... In instance t
12 | rand int assocarr[string];
| ^~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:13:13: Unsupported: random member variables with type 'int[]'
: ... In instance t
13 | rand int dynarr[];
| ^~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:14:13: Unsupported: random member variables with type 'int$[0:4]'
: ... In instance t
14 | rand int unpackarr[5];
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variables with type '__024unit::Union'
: ... In instance t
15 | rand Union uni;
| ^~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 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
scenarios(simulator => 1);
compile(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,25 @@
// 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
typedef union packed {
int x;
} Union;
class Cls;
rand int assocarr[string];
rand int dynarr[];
rand int unpackarr[5];
rand Union uni;
endclass
module t (/*AUTOARG*/);
Cls obj;
initial begin
obj = new;
obj.randomize();
end
endmodule

View File

@ -0,0 +1,7 @@
%Error-UNSUPPORTED: t/t_randomize_method_unsup.v:8:18: Unsupported: 'pre_randomize'
8 | function void pre_randomize;
| ^~~~~~~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_unsup.v:11:18: Unsupported: 'post_randomize'
11 | function void post_randomize;
| ^~~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 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
scenarios(simulator => 1);
compile(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,16 @@
// 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 Cls;
function void pre_randomize;
endfunction;
function void post_randomize;
endfunction;
endclass
module t (/*AUTOARG*/);
endmodule