Support probablity distribution functions.

This commit is contained in:
Wilson Snyder 2022-12-04 17:30:51 -05:00
parent 84c7368621
commit ea1b141d13
17 changed files with 486 additions and 29 deletions

View File

@ -2155,6 +2155,17 @@ extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE;
extern IData VL_FGETS_NI(std::string& dest, IData fpi);
//======================================================================
// Dist functions
extern IData VL_DIST_CHI_SQUARE(IData& seedr, IData udeg_of_free) VL_MT_SAFE;
extern IData VL_DIST_ERLANG(IData& seedr, IData uk, IData umean) VL_MT_SAFE;
extern IData VL_DIST_EXPONENTIAL(IData& seedr, IData umean) VL_MT_SAFE;
extern IData VL_DIST_NORMAL(IData& seedr, IData umean, IData udeviation) VL_MT_SAFE;
extern IData VL_DIST_POISSON(IData& seedr, IData umean) VL_MT_SAFE;
extern IData VL_DIST_T(IData& seedr, IData udeg_of_free) VL_MT_SAFE;
extern IData VL_DIST_UNIFORM(IData& seedr, IData ustart, IData uend) VL_MT_SAFE;
//======================================================================
// Conversion functions

View File

@ -0,0 +1,240 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Code available from: https://verilator.org
//
// Copyright 2003-2022 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
//
//=========================================================================
///
/// \file
/// \brief Verilated probability distribution implementation code
///
/// Verilator always adds this file to the Makefile for the linker.
///
/// Those macro/function/variable starting or ending in _ are internal,
/// however many of the other function/macros here are also internal.
///
//=========================================================================
#include "verilated_config.h"
#include "verilatedos.h"
#include "verilated.h"
//===========================================================================
// Dist
static double _vl_dbase_uniform(IData& seedr, int32_t start, int32_t end) VL_MT_SAFE {
union u_s {
float s;
unsigned stemp;
} u;
const double d = 0.00000011920928955078125;
if (VL_UNLIKELY(seedr == 0)) seedr = 259341593;
double a;
double b;
if (VL_UNCOVERABLE(start >= end)) { // With current usage shound't occur
a = 0.0; // LCOV_EXCL_LINE
b = 2147483647.0; // LCOV_EXCL_LINE
} else {
a = static_cast<double>(start);
b = static_cast<double>(end);
}
seedr = 69069 * seedr + 1;
u.stemp = seedr;
u.stemp = (u.stemp >> 9) | 0x3f800000;
double c = static_cast<double>(u.s);
c = c + (c * d);
c = ((b - a) * (c - 1.0)) + a;
return c;
}
static double _vl_dbase_normal(IData& seedr, int32_t mean, int32_t deviation) VL_MT_SAFE {
double v1 = 0.0;
double v2 = 0.0;
double s = 1.0;
while ((s >= 1.0) || (s == 0.0)) {
v1 = _vl_dbase_uniform(seedr, -1, 1);
v2 = _vl_dbase_uniform(seedr, -1, 1);
s = v1 * v1 + v2 * v2;
}
s = v1 * std::sqrt(-2.0 * log(s) / s);
v1 = static_cast<double>(deviation);
v2 = static_cast<double>(mean);
return (s * v1 + v2);
}
static double _vl_dbase_exponential(IData& seedr, int32_t mean) VL_MT_SAFE {
double n = _vl_dbase_uniform(seedr, 0, 1);
if (n != 0) n = -log(n) * mean;
return n;
}
static double _vl_dbase_chi_square(IData& seedr, int32_t deg_of_free) VL_MT_SAFE {
double x;
if (deg_of_free % 2) {
x = _vl_dbase_normal(seedr, 0, 1);
x = x * x;
} else {
x = 0.0;
}
for (int32_t k = 2; k <= deg_of_free; k += 2) x = x + 2 * _vl_dbase_exponential(seedr, 1);
return x;
}
IData VL_DIST_CHI_SQUARE(IData& seedr, IData udf) VL_MT_SAFE {
const int32_t df = static_cast<int32_t>(udf);
if (VL_UNLIKELY(df <= 0)) {
// Chi_square distribution must have positive degree of freedom
return 0;
}
double r = _vl_dbase_chi_square(seedr, df);
int32_t i;
if (r >= 0) {
i = static_cast<int32_t>(r + 0.5);
} else {
r = -r; // LCOV_EXCL_LINE
i = static_cast<int32_t>(r + 0.5); // LCOV_EXCL_LINE
i = -i; // LCOV_EXCL_LINE
}
return static_cast<IData>(i);
}
IData VL_DIST_ERLANG(IData& seedr, IData uk, IData umean) VL_MT_SAFE {
const int32_t k = static_cast<int32_t>(uk);
const int32_t mean = static_cast<int32_t>(umean);
if (VL_UNLIKELY(k <= 0)) {
// k-stage erlangian distribution must have positive k
return 0;
}
double x = 1.0;
for (int32_t i = 1; i <= k; i++) { x = x * _vl_dbase_uniform(seedr, 0, 1); }
const double a = static_cast<double>(mean);
const double b = static_cast<double>(k);
double r = -a * log(x) / b;
int32_t i;
if (r >= 0) {
i = static_cast<int32_t>(r + 0.5);
} else {
r = -r;
i = static_cast<int32_t>(r + 0.5);
i = -i;
}
return static_cast<IData>(i);
}
IData VL_DIST_EXPONENTIAL(IData& seedr, IData umean) VL_MT_SAFE {
const int32_t mean = static_cast<int32_t>(umean);
if (VL_UNLIKELY(mean <= 0)) {
// Exponential distribution must have a positive mean
return 0;
}
int32_t i;
double r = _vl_dbase_exponential(seedr, mean);
if (r >= 0) {
i = static_cast<int32_t>(r + 0.5);
} else {
r = -r; // LCOV_EXCL_LINE
i = static_cast<int32_t>(r + 0.5); // LCOV_EXCL_LINE
i = -i; // LCOV_EXCL_LINE
}
return static_cast<IData>(i);
}
IData VL_DIST_NORMAL(IData& seedr, IData umean, IData usd) VL_MT_SAFE {
const int32_t mean = static_cast<int32_t>(umean);
const int32_t sd = static_cast<int32_t>(usd);
double r = _vl_dbase_normal(seedr, mean, sd);
int32_t i;
if (r >= 0) {
i = static_cast<int32_t>(r + 0.5);
} else {
r = -r;
i = static_cast<int32_t>(r + 0.5);
i = -i;
}
return static_cast<IData>(i);
}
IData VL_DIST_POISSON(IData& seedr, IData umean) VL_MT_SAFE {
const int32_t mean = static_cast<int32_t>(umean);
if (VL_UNLIKELY(mean <= 0)) {
// Poisson distribution must have a positive mean
return 0;
}
int32_t i = 0;
double q = -static_cast<double>(mean);
double p = exp(q);
q = _vl_dbase_uniform(seedr, 0, 1);
while (p < q) {
++i;
q = _vl_dbase_uniform(seedr, 0, 1) * q;
}
return static_cast<IData>(i);
}
IData VL_DIST_T(IData& seedr, IData udf) VL_MT_SAFE {
const int32_t df = static_cast<int32_t>(udf);
if (VL_UNLIKELY(df <= 0)) {
// t distribution must have positive degree of freedom
return 0;
}
const double chi2 = _vl_dbase_chi_square(seedr, df);
const double div = chi2 / static_cast<double>(df);
const double root = std::sqrt(div);
double r = _vl_dbase_normal(seedr, 0, 1) / root;
int32_t i;
if (r >= 0) {
i = static_cast<int32_t>(r + 0.5);
} else {
r = -r;
i = static_cast<int32_t>(r + 0.5);
i = -i;
}
return static_cast<IData>(i);
}
IData VL_DIST_UNIFORM(IData& seedr, IData ustart, IData uend) VL_MT_SAFE {
int32_t start = static_cast<int32_t>(ustart);
int32_t end = static_cast<int32_t>(uend);
if (VL_UNLIKELY(start >= end)) return start;
int32_t i;
if (end != std::numeric_limits<int32_t>::max()) {
++end;
const double r = _vl_dbase_uniform(seedr, start, end);
if (r >= 0) {
i = static_cast<int32_t>(r);
} else {
i = static_cast<int32_t>(r - 1);
}
if (i < start) i = start;
if (i >= end) i = end - 1;
} else if (start != std::numeric_limits<int32_t>::min()) {
--start;
const double r = _vl_dbase_uniform(seedr, start, end) + 1.0;
if (r >= 0) {
i = static_cast<int32_t>(r);
} else {
i = static_cast<int32_t>(r - 1); // LCOV_EXCL_LINE
}
if (i <= start) i = start + 1;
if (i > end) i = end;
} else {
double r = (_vl_dbase_uniform(seedr, start, end) + 2147483648.0) / 4294967295.0;
r = r * 4294967296.0 - 2147483648.0;
if (r >= 0) {
i = static_cast<int32_t>(r);
} else {
i = static_cast<int32_t>(r - 1);
}
}
return static_cast<IData>(i);
}

View File

@ -112,6 +112,27 @@ protected:
public:
ASTGEN_MEMBERS_AstNodeBiComAsv;
};
class AstNodeDistBiop VL_NOT_FINAL : public AstNodeBiop {
public:
AstNodeDistBiop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: AstNodeBiop{t, fl, lhsp, rhsp} {
dtypeSetSigned32();
}
ASTGEN_MEMBERS_AstNodeDistBiop;
bool cleanOut() const override { return false; }
bool cleanLhs() const override { return false; }
bool cleanRhs() const override { return false; }
bool sizeMattersLhs() const override { return false; }
bool sizeMattersRhs() const override { return false; }
int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
AstNodeExpr* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
V3ERROR_NA;
return nullptr;
}
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
V3ERROR_NA;
}
};
class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
// Single bit range extraction, perhaps with non-constant selection or array selection
// @astgen alias op1 := fromp // Expression we are indexing into
@ -363,6 +384,27 @@ public:
int instrCount() const override { return INSTR_COUNT_BRANCH; }
virtual AstNodeExpr* cloneType(AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep) = 0;
};
class AstNodeDistTriop VL_NOT_FINAL : public AstNodeTriop {
public:
AstNodeDistTriop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
AstNodeExpr* thsp)
: AstNodeTriop{t, fl, lhsp, rhsp, thsp} {
dtypeSetSigned32();
}
ASTGEN_MEMBERS_AstNodeDistTriop;
bool cleanOut() const override { return false; }
bool cleanLhs() const override { return false; }
bool cleanRhs() const override { return false; }
bool cleanThs() const override { return false; }
bool sizeMattersLhs() const override { return false; }
bool sizeMattersRhs() const override { return false; }
bool sizeMattersThs() const override { return false; }
int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
const V3Number& ths) override {
V3ERROR_NA;
}
};
class AstNodeUniop VL_NOT_FINAL : public AstNodeExpr {
// Unary expression
// @astgen op1 := lhsp : AstNodeExpr
@ -3532,6 +3574,40 @@ public:
bool sizeMattersRhs() const override { return false; }
};
// === AstNodeDistBiop ===
class AstDistChiSquare final : public AstNodeDistBiop {
public:
AstDistChiSquare(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_DistChiSquare(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstDistChiSquare;
string emitVerilog() override { return "%f$dist_chi_square(%l, %r)"; }
string emitC() override { return "VL_DIST_CHI_SQUARE(%li, %ri)"; }
};
class AstDistExponential final : public AstNodeDistBiop {
public:
AstDistExponential(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_DistExponential(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstDistExponential;
string emitVerilog() override { return "%f$dist_exponential(%l, %r)"; }
string emitC() override { return "VL_DIST_EXPONENTIAL(%li, %ri)"; }
};
class AstDistPoisson final : public AstNodeDistBiop {
public:
AstDistPoisson(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_DistPoisson(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstDistPoisson;
string emitVerilog() override { return "%f$dist_poisson(%l, %r)"; }
string emitC() override { return "VL_DIST_POISSON(%li, %ri)"; }
};
class AstDistT final : public AstNodeDistBiop {
public:
AstDistT(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_DistT(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstDistT;
string emitVerilog() override { return "%f$dist_t(%l, %r)"; }
string emitC() override { return "VL_DIST_T(%li, %ri)"; }
};
// === AstNodeSel ===
class AstArraySel final : public AstNodeSel {
void init(AstNode* fromp) {
@ -4198,6 +4274,32 @@ public:
}
};
// === AstNodeDistTriop ===
class AstDistErlang final : public AstNodeDistTriop {
public:
AstDistErlang(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
: ASTGEN_SUPER_DistErlang(fl, lhsp, rhsp, thsp) {}
ASTGEN_MEMBERS_AstDistErlang;
string emitVerilog() override { return "%f$dist_erlang(%l, %r, %t)"; }
string emitC() override { return "VL_DIST_ERLANG(%li, %ri, %ti)"; }
};
class AstDistNormal final : public AstNodeDistTriop {
public:
AstDistNormal(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
: ASTGEN_SUPER_DistNormal(fl, lhsp, rhsp, thsp) {}
ASTGEN_MEMBERS_AstDistNormal;
string emitVerilog() override { return "%f$dist_normal(%l, %r, %t)"; }
string emitC() override { return "VL_DIST_NORMAL(%li, %ri, %ti)"; }
};
class AstDistUniform final : public AstNodeDistTriop {
public:
AstDistUniform(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
: ASTGEN_SUPER_DistUniform(fl, lhsp, rhsp, thsp) {}
ASTGEN_MEMBERS_AstDistUniform;
string emitVerilog() override { return "%f$dist_uniform(%l, %r, %t)"; }
string emitC() override { return "VL_DIST_UNIFORM(%li, %ri, %ti)"; }
};
// === AstNodeUniop ===
class AstAtoN final : public AstNodeUniop {
// string.atoi(), atobin(), atohex(), atooct(), atoireal()

View File

@ -43,6 +43,14 @@ class EmitCInlines final : EmitCBaseVisitor {
if (v3Global.opt.trace()) v3Global.needTraceDumper(true);
iterateChildren(nodep);
}
void visit(AstNodeDistBiop* nodep) override {
v3Global.setUsesProbDist();
iterateChildren(nodep);
}
void visit(AstNodeDistTriop* nodep) override {
v3Global.setUsesProbDist();
iterateChildren(nodep);
}
//---------------------------------------
void visit(AstNode* nodep) override { iterateChildren(nodep); }

View File

@ -159,6 +159,9 @@ class CMakeEmitter final {
global.emplace_back("${VERILATOR_ROOT}/include/" + v3Global.opt.traceSourceBase()
+ "_c.cpp");
}
if (v3Global.usesProbDist()) {
global.emplace_back("${VERILATOR_ROOT}/include/verilated_probdist.cpp");
}
if (v3Global.usesTiming()) {
global.emplace_back("${VERILATOR_ROOT}/include/verilated_timing.cpp");
}

View File

@ -106,6 +106,7 @@ public:
if (v3Global.opt.trace()) {
putMakeClassEntry(of, v3Global.opt.traceSourceBase() + "_c.cpp");
}
if (v3Global.usesProbDist()) putMakeClassEntry(of, "verilated_probdist.cpp");
if (v3Global.usesTiming()) putMakeClassEntry(of, "verilated_timing.cpp");
if (v3Global.opt.threads()) putMakeClassEntry(of, "verilated_threads.cpp");
if (v3Global.opt.usesProfiler()) {

View File

@ -107,6 +107,7 @@ class V3Global final {
bool m_dpi = false; // Need __Dpi include files
bool m_hasEvents = false; // Design uses SystemVerilog named events
bool m_hasClasses = false; // Design uses SystemVerilog classes
bool m_usesProbDist = false; // Uses $dist_*
bool m_usesStdPackage = false; // Design uses the std package
bool m_usesTiming = false; // Design uses timing constructs
bool m_hasForceableSignals = false; // Need to apply V3Force pass
@ -153,6 +154,8 @@ public:
void setHasEvents() { m_hasEvents = true; }
bool hasClasses() const { return m_hasClasses; }
void setHasClasses() { m_hasClasses = true; }
bool usesProbDist() const { return m_usesProbDist; }
void setUsesProbDist() { m_usesProbDist = true; }
bool usesStdPackage() const { return m_usesStdPackage; }
void setUsesStdPackage() { m_usesStdPackage = true; }
bool usesTiming() const { return m_usesTiming; }

View File

@ -250,6 +250,21 @@ private:
iterateAndNextNull(nodep->fmtp());
}
}
void visit(AstNodeDistBiop* nodep) override {
VL_RESTORER(m_setRefLvalue);
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->lhsp());
m_setRefLvalue = VAccess::NOCHANGE;
iterateAndNextNull(nodep->rhsp());
}
void visit(AstNodeDistTriop* nodep) override {
VL_RESTORER(m_setRefLvalue);
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->lhsp());
m_setRefLvalue = VAccess::NOCHANGE;
iterateAndNextNull(nodep->rhsp());
iterateAndNextNull(nodep->thsp());
}
void prepost_visit(AstNodeTriop* nodep) {
VL_RESTORER(m_setRefLvalue);
{

View File

@ -773,6 +773,21 @@ private:
}
}
}
void visit(AstNodeDistBiop* nodep) override {
if (m_vup->prelim()) { // First stage evaluation
iterateCheckSigned32(nodep, "seed", nodep->lhsp(), BOTH);
iterateCheckSigned32(nodep, "RHS", nodep->rhsp(), BOTH);
nodep->dtypeSetSigned32();
}
}
void visit(AstNodeDistTriop* nodep) override {
if (m_vup->prelim()) { // First stage evaluation
iterateCheckSigned32(nodep, "seed", nodep->lhsp(), BOTH);
iterateCheckSigned32(nodep, "RHS", nodep->rhsp(), BOTH);
iterateCheckSigned32(nodep, "THS", nodep->thsp(), BOTH);
nodep->dtypeSetSigned32();
}
}
void visit(AstNodeStream* nodep) override {
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);

View File

@ -183,6 +183,13 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$displayb" { FL; return yD_DISPLAYB; }
"$displayh" { FL; return yD_DISPLAYH; }
"$displayo" { FL; return yD_DISPLAYO; }
"$dist_chi_square" { FL; return yD_DIST_CHI_SQUARE; }
"$dist_erlang" { FL; return yD_DIST_ERLANG; }
"$dist_exponential" { FL; return yD_DIST_EXPONENTIAL; }
"$dist_normal" { FL; return yD_DIST_NORMAL; }
"$dist_poisson" { FL; return yD_DIST_POISSON; }
"$dist_t" { FL; return yD_DIST_T; }
"$dist_uniform" { FL; return yD_DIST_UNIFORM; }
"$dumpall" { FL; return yD_DUMPALL; }
"$dumpfile" { FL; return yD_DUMPFILE; }
"$dumpflush" { FL; return yD_DUMPFLUSH; }

View File

@ -776,6 +776,13 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yD_DISPLAYB "$displayb"
%token<fl> yD_DISPLAYH "$displayh"
%token<fl> yD_DISPLAYO "$displayo"
%token<fl> yD_DIST_CHI_SQUARE "$dist_chi_square"
%token<fl> yD_DIST_ERLANG "$dist_erlang"
%token<fl> yD_DIST_EXPONENTIAL "$dist_exponential"
%token<fl> yD_DIST_NORMAL "$dist_normal"
%token<fl> yD_DIST_POISSON "$dist_poisson"
%token<fl> yD_DIST_T "$dist_t"
%token<fl> yD_DIST_UNIFORM "$dist_uniform"
%token<fl> yD_DUMPALL "$dumpall"
%token<fl> yD_DUMPFILE "$dumpfile"
%token<fl> yD_DUMPFLUSH "$dumpflush"
@ -4038,6 +4045,13 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
BBUNSUP($11, "Unsupported: $countbits with more than 3 control fields"); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes{$1, $3}; }
| yD_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_DIMENSIONS, $3}; }
| yD_DIST_CHI_SQUARE '(' expr ',' expr ')' { $$ = new AstDistChiSquare{$1, $3, $5}; }
| yD_DIST_ERLANG '(' expr ',' expr ',' expr ')' { $$ = new AstDistErlang{$1, $3, $5, $7}; }
| yD_DIST_EXPONENTIAL '(' expr ',' expr ')' { $$ = new AstDistExponential{$1, $3, $5}; }
| yD_DIST_NORMAL '(' expr ',' expr ',' expr ')' { $$ = new AstDistNormal{$1, $3, $5, $7}; }
| yD_DIST_POISSON '(' expr ',' expr ')' { $$ = new AstDistPoisson{$1, $3, $5}; }
| yD_DIST_T '(' expr ',' expr ')' { $$ = new AstDistT{$1, $3, $5}; }
| yD_DIST_UNIFORM '(' expr ',' expr ',' expr ')' { $$ = new AstDistUniform{$1, $3, $5, $7}; }
| yD_EXP '(' expr ')' { $$ = new AstExpD{$1, $3}; }
| yD_FELL '(' expr ')' { $$ = new AstFell{$1, $3}; }
| yD_FELL '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $fell and clock arguments"); }

View File

@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
compile(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
execute(
check_finished => 1,
) if !$Self->{vlt_all};
);
ok(1);
1;

View File

@ -13,7 +13,7 @@ module t(/*AUTOARG*/);
integer sum;
initial begin
// Illegal values
//=======
seed = 1234;
r = $dist_chi_square(seed, 5);
`checkd(seed, 923940542);
@ -21,7 +21,14 @@ module t(/*AUTOARG*/);
sum = 1;
repeat(20) sum += $dist_chi_square(seed, 5);
`checkd(sum, 130);
sum = 1;
repeat(20) sum += $dist_chi_square(seed, -5);
`checkd(sum, 1);
sum = 1;
repeat(20) sum += $dist_chi_square(seed, 2);
`checkd(sum, 30);
//=======
seed = 1234;
r = $dist_erlang(seed, 5, 10);
`checkd(seed, 1025211431);
@ -29,7 +36,11 @@ module t(/*AUTOARG*/);
sum = 1;
repeat(20) sum += $dist_erlang(seed, 5, 10);
`checkd(sum, 173);
sum = 1;
repeat(20) sum += $dist_erlang(seed, 5, -10);
`checkd(sum, -241);
//=======
seed = 1234;
r = $dist_exponential(seed, 5);
`checkd(seed, 85231147);
@ -38,6 +49,7 @@ module t(/*AUTOARG*/);
repeat(20) sum += $dist_exponential(seed, 5);
`checkd(sum, 104);
//=======
seed = 1234;
r = $dist_normal(seed, 5, 10);
`checkd(seed, -1570070672);
@ -46,6 +58,7 @@ module t(/*AUTOARG*/);
repeat(20) sum += $dist_normal(seed, 5, 10);
`checkd(sum, 114);
//=======
seed = 1234;
r = $dist_poisson(seed, 5);
`checkd(seed, 418012337);
@ -54,6 +67,7 @@ module t(/*AUTOARG*/);
repeat(20) sum += $dist_poisson(seed, 5);
`checkd(sum, 111);
//=======
seed = 1234;
r = $dist_t(seed, 5);
`checkd(seed, -797481412);
@ -62,6 +76,7 @@ module t(/*AUTOARG*/);
repeat(20) sum += $dist_t(seed, 5);
`checkd(sum, -2);
//=======
seed = 1234;
r = $dist_uniform(seed, 5, 10);
`checkd(seed, 85231147);
@ -70,6 +85,24 @@ module t(/*AUTOARG*/);
repeat(20) sum += $dist_uniform(seed, 5, 10);
`checkd(sum, 147);
seed = 1234;
r = $dist_uniform(seed, 10, 5);
`checkd(r, 10);
sum = 1;
repeat(20) sum += $dist_uniform(seed, -2147483648, -20);
`checkd(sum, 1768955681);
sum = 1;
repeat(20) sum += $dist_uniform(seed, 20, 2147483647);
`checkd(sum, 1534326415);
sum = 1;
repeat(20) sum += $dist_uniform(seed, -2147483648, 2147483647);
`checkd(sum, 1394525852);
seed = 0;
sum = 1;
repeat(20) sum += $dist_uniform(seed, -10, 100);
`checkd(seed, 1003647461);
`checkd(sum, 896);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -1,19 +0,0 @@
%Error: t/t_probdist_bad.v:16:11: Unsupported or unknown PLI call: '$dist_chi_square'
16 | r = $dist_chi_square(seed, 0);
| ^~~~~~~~~~~~~~~~
%Error: t/t_probdist_bad.v:18:11: Unsupported or unknown PLI call: '$dist_erlang'
18 | r = $dist_erlang(seed, 0, 0);
| ^~~~~~~~~~~~
%Error: t/t_probdist_bad.v:20:11: Unsupported or unknown PLI call: '$dist_exponential'
20 | r = $dist_exponential(seed, 0);
| ^~~~~~~~~~~~~~~~~
%Error: t/t_probdist_bad.v:23:11: Unsupported or unknown PLI call: '$dist_poisson'
23 | r = $dist_poisson(seed, 0);
| ^~~~~~~~~~~~~
%Error: t/t_probdist_bad.v:25:11: Unsupported or unknown PLI call: '$dist_t'
25 | r = $dist_t(seed, 0);
| ^~~~~~~
%Error: t/t_probdist_bad.v:27:11: Unsupported or unknown PLI call: '$dist_uniform'
27 | r = $dist_uniform(seed, 10, 0);
| ^~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
compile(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
execute(
check_finished => 1,
) if !$Self->{vlt_all};
);
ok(1);
1;

View File

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

View File

@ -12,12 +12,15 @@ module t (/*AUTOARG*/
input clk;
integer cyc;
integer seed = 123;
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc!=0) begin
if (cyc==10) begin
#5 $write("*-* All Finished *-*\n");
if (cyc != 0) begin
if (cyc == 10) begin
#5;
$display("dist: %f ", $dist_poisson(seed, 12)); // Get verilated_probdist.cpp
$write("*-* All Finished *-*\n");
$finish;
end
end