forked from github/verilator
Support probablity distribution functions.
This commit is contained in:
parent
84c7368621
commit
ea1b141d13
@ -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
|
||||
|
||||
|
240
include/verilated_probdist.cpp
Normal file
240
include/verilated_probdist.cpp
Normal 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);
|
||||
}
|
@ -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()
|
||||
|
@ -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); }
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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"); }
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
|
25
test_regress/t/t_probdist_cmake.pl
Executable file
25
test_regress/t/t_probdist_cmake.pl
Executable 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;
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user