forked from github/verilator
Fix non-32 bit conversion to float (#2495).
This commit is contained in:
parent
e029ba845e
commit
98cd925fda
5
Changes
5
Changes
@ -6,9 +6,12 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
*** Fix arrayed interfaces, broke in 4.038 (#2468). [Josh Redford]
|
||||
|
||||
**** Support $stable. [Peter Monsson]
|
||||
|
||||
**** Fix combining different-width parameters (#2484). [abirkmanis]
|
||||
|
||||
**** Support $stable. [Peter Monsson]
|
||||
**** Fix non-32 bit conversion to float (#2495). [dsvf]
|
||||
|
||||
|
||||
* Verilator 4.038 2020-07-11
|
||||
|
||||
|
@ -584,6 +584,31 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig
|
||||
return VL_POW_QQW(obits, rbits, rbits, lhs, rwp);
|
||||
}
|
||||
|
||||
double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE {
|
||||
int ms_word = VL_WORDS_I(lbits) - 1;
|
||||
for (; !lwp[ms_word] && ms_word > 0;) --ms_word;
|
||||
if (ms_word == 0) return static_cast<double>(lwp[0]);
|
||||
if (ms_word == 1) return static_cast<double>(VL_SET_QW(lwp));
|
||||
// We need 53 bits of mantissa, which might mean looking at 3 words
|
||||
// namely ms_word, ms_word-1 and ms_word-2
|
||||
EData ihi = lwp[ms_word];
|
||||
EData imid = lwp[ms_word - 1];
|
||||
EData ilo = lwp[ms_word - 2];
|
||||
double hi = static_cast<double>(ihi) * exp2(2 * VL_EDATASIZE);
|
||||
double mid = static_cast<double>(imid) * exp2(VL_EDATASIZE);
|
||||
double lo = static_cast<double>(ilo);
|
||||
double d = (hi + mid + lo) * exp2(VL_EDATASIZE * (ms_word - 2));
|
||||
return d;
|
||||
}
|
||||
double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE {
|
||||
if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
|
||||
vluint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||
VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp);
|
||||
_VL_CLEAN_INPLACE_W(lbits, pos);
|
||||
double d = VL_ITOR_D_W(lbits, pos);
|
||||
return -VL_ITOR_D_W(lbits, pos);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Formatting
|
||||
|
||||
|
@ -764,9 +764,27 @@ static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
|
||||
return static_cast<double>(static_cast<vlsint32_t>(lhs));
|
||||
/// Return double from lhs (numeric) unsigned
|
||||
double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE;
|
||||
static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE {
|
||||
return static_cast<double>(static_cast<vluint32_t>(lhs));
|
||||
}
|
||||
static inline double VL_ITOR_D_Q(int, QData lhs) VL_PURE {
|
||||
return static_cast<double>(static_cast<vluint64_t>(lhs));
|
||||
}
|
||||
/// Return double from lhs (numeric) signed
|
||||
double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE;
|
||||
static inline double VL_ISTOR_D_I(int lbits, IData lhs) VL_PURE {
|
||||
if (lbits == 32) return static_cast<double>(static_cast<vlsint32_t>(lhs));
|
||||
WData lwp[VL_WQ_WORDS_E];
|
||||
VL_SET_WI(lwp, lhs);
|
||||
return VL_ISTOR_D_W(lbits, lwp);
|
||||
}
|
||||
static inline double VL_ISTOR_D_Q(int lbits, QData lhs) VL_PURE {
|
||||
if (lbits == 64) return static_cast<double>(static_cast<vlsint64_t>(lhs));
|
||||
WData lwp[VL_WQ_WORDS_E];
|
||||
VL_SET_WQ(lwp, lhs);
|
||||
return VL_ISTOR_D_W(lbits, lwp);
|
||||
}
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
|
||||
@ -1453,6 +1471,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
//=========================================================================
|
||||
// Math
|
||||
|
||||
// Output NOT clean
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
||||
EData carry = 1;
|
||||
for (int i = 0; i < words; ++i) {
|
||||
|
@ -5523,6 +5523,7 @@ public:
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
class AstIToRD : public AstNodeUniop {
|
||||
// $itor where lhs is unsigned
|
||||
public:
|
||||
AstIToRD(FileLine* fl, AstNode* lhsp)
|
||||
: ASTGEN_SUPER(fl, lhsp) {
|
||||
@ -5531,10 +5532,27 @@ public:
|
||||
ASTNODE_NODE_FUNCS(IToRD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
|
||||
virtual string emitVerilog() { return "%f$itor(%l)"; }
|
||||
virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
|
||||
virtual string emitC() { return "VL_ITOR_D_%lq(%lw, %li)"; }
|
||||
virtual bool cleanOut() const { return false; }
|
||||
virtual bool cleanLhs() const { return false; } // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() const { return false; } // Eliminated before matters
|
||||
virtual bool cleanLhs() const { return true; }
|
||||
virtual bool sizeMattersLhs() const { return false; }
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
class AstISToRD : public AstNodeUniop {
|
||||
// $itor where lhs is signed
|
||||
public:
|
||||
AstISToRD(FileLine* fl, AstNode* lhsp)
|
||||
: ASTGEN_SUPER(fl, lhsp) {
|
||||
dtypeSetDouble();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ISToRD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opISToRD(lhs); }
|
||||
virtual string emitVerilog() { return "%f$itor($signed(%l))"; }
|
||||
virtual string emitC() { return "VL_ISTOR_D_%lq(%lw, %li)"; }
|
||||
virtual bool emitCheckMaxWords() { return true; }
|
||||
virtual bool cleanOut() const { return false; }
|
||||
virtual bool cleanLhs() const { return true; }
|
||||
virtual bool sizeMattersLhs() const { return false; }
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
class AstRealToBits : public AstNodeUniop {
|
||||
|
@ -877,6 +877,15 @@ public:
|
||||
emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL);
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
|
||||
if (nodep->emitCheckMaxWords()
|
||||
&& (nodep->widthWords() > VL_MULS_MAX_WORDS
|
||||
|| nodep->lhsp()->widthWords() > VL_MULS_MAX_WORDS)) {
|
||||
nodep->v3warn(
|
||||
E_UNSUPPORTED,
|
||||
"Unsupported: "
|
||||
<< nodep->prettyOperatorName() << " operator of " << nodep->width()
|
||||
<< " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
|
||||
}
|
||||
if (emitSimpleOk(nodep)) {
|
||||
putbs("(");
|
||||
puts(nodep->emitSimpleOperator());
|
||||
|
@ -2232,13 +2232,24 @@ V3Number& V3Number::opSelInto(const V3Number& lhs, int lsbval, int width) {
|
||||
//======================================================================
|
||||
// Ops - Floating point
|
||||
|
||||
V3Number& V3Number::opIToRD(const V3Number& lhs) {
|
||||
V3Number& V3Number::opIToRD(const V3Number& lhs, bool isSigned) {
|
||||
NUM_ASSERT_OP_ARGS1(lhs);
|
||||
NUM_ASSERT_LOGIC_ARGS1(lhs);
|
||||
// IEEE says we ignore x/z in real conversions
|
||||
V3Number noxz(lhs);
|
||||
noxz.opAssignNonXZ(lhs);
|
||||
return setDouble(noxz.toSInt());
|
||||
double d = 0;
|
||||
bool negate = isSigned && noxz.isNegative();
|
||||
if (negate) {
|
||||
V3Number noxz_signed = noxz;
|
||||
noxz.opNegate(noxz_signed);
|
||||
}
|
||||
for (int bit = noxz.width() - 1; bit >= 0; bit--) {
|
||||
// Some precision might be lost in this add, that's what we want
|
||||
if (noxz.bitIs1(bit)) d += exp2(bit);
|
||||
}
|
||||
if (negate) d = -d;
|
||||
return setDouble(d);
|
||||
}
|
||||
V3Number& V3Number::opRToIS(const V3Number& lhs) {
|
||||
NUM_ASSERT_OP_ARGS1(lhs);
|
||||
|
@ -385,7 +385,8 @@ public:
|
||||
V3Number& opLteS(const V3Number& lhs, const V3Number& rhs); // Signed
|
||||
|
||||
// "D" - double (aka real) math
|
||||
V3Number& opIToRD(const V3Number& lhs);
|
||||
V3Number& opIToRD(const V3Number& lhs, bool isSigned = false);
|
||||
V3Number& opISToRD(const V3Number& lhs) { return opIToRD(lhs, true); }
|
||||
V3Number& opRToIS(const V3Number& lhs);
|
||||
V3Number& opRToIRoundS(const V3Number& lhs);
|
||||
V3Number& opRealToBits(const V3Number& lhs);
|
||||
|
@ -332,7 +332,6 @@ private:
|
||||
//========
|
||||
// Widths: Output real, input integer signed
|
||||
virtual void visit(AstBitsToRealD* nodep) VL_OVERRIDE { visit_Or_Lu64(nodep); }
|
||||
virtual void visit(AstIToRD* nodep) VL_OVERRIDE { visit_Or_Ls32(nodep); }
|
||||
|
||||
// Widths: Output integer signed, input real
|
||||
virtual void visit(AstRToIS* nodep) VL_OVERRIDE { visit_Os32_Lr(nodep); }
|
||||
@ -1549,7 +1548,11 @@ private:
|
||||
}
|
||||
AstNode* newp = nodep->lhsp()->unlinkFrBack();
|
||||
if (basicp->isDouble() && !newp->isDouble()) {
|
||||
newp = new AstIToRD(nodep->fileline(), newp);
|
||||
if (newp->isSigned()) {
|
||||
newp = new AstISToRD(nodep->fileline(), newp);
|
||||
} else {
|
||||
newp = new AstIToRD(nodep->fileline(), newp);
|
||||
}
|
||||
} else if (!basicp->isDouble() && newp->isDouble()) {
|
||||
if (basicp->isSigned()) {
|
||||
newp = new AstRToIRoundS(nodep->fileline(), newp);
|
||||
@ -3931,16 +3934,27 @@ private:
|
||||
iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
void visit_Or_Ls32(AstNodeUniop* nodep) {
|
||||
// CALLER: AstIToRD
|
||||
virtual void visit(AstIToRD* nodep) VL_OVERRIDE {
|
||||
// Real: Output real
|
||||
// LHS presumed self-determined, then coerced to real
|
||||
if (m_vup->prelim()) { // First stage evaluation
|
||||
nodep->dtypeSetDouble();
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(32, 32, VSigning::SIGNED);
|
||||
// Self-determined operand
|
||||
// Self-determined operand (TODO check if numeric type)
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p());
|
||||
if (nodep->lhsp()->isSigned()) {
|
||||
nodep->replaceWith(
|
||||
new AstISToRD(nodep->fileline(), nodep->lhsp()->unlinkFrBack()));
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstISToRD* nodep) VL_OVERRIDE {
|
||||
// Real: Output real
|
||||
// LHS presumed self-determined, then coerced to real
|
||||
if (m_vup->prelim()) { // First stage evaluation
|
||||
nodep->dtypeSetDouble();
|
||||
// Self-determined operand (TODO check if numeric type)
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p());
|
||||
iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
void visit_Os32_Lr(AstNodeUniop* nodep) {
|
||||
@ -4800,7 +4814,12 @@ private:
|
||||
UINFO(6, " spliceCvtD: " << nodep << endl);
|
||||
AstNRelinker linker;
|
||||
nodep->unlinkFrBack(&linker);
|
||||
AstNode* newp = new AstIToRD(nodep->fileline(), nodep);
|
||||
AstNode* newp;
|
||||
if (nodep->dtypep()->skipRefp()->isSigned()) {
|
||||
newp = new AstISToRD(nodep->fileline(), nodep);
|
||||
} else {
|
||||
newp = new AstIToRD(nodep->fileline(), nodep);
|
||||
}
|
||||
linker.relink(newp);
|
||||
return newp;
|
||||
} else {
|
||||
|
@ -6,6 +6,7 @@
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define is_near_real(a,b) (( ((a)<(b)) ? (b)-(a) : (a)-(b)) < (((a)/(b))*0.0001))
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
@ -16,6 +17,16 @@ module t (/*AUTOARG*/
|
||||
|
||||
integer i;
|
||||
reg [63:0] b;
|
||||
reg [47:0] i48;
|
||||
reg signed [47:0] is48;
|
||||
reg [31:0] ci32;
|
||||
reg signed [31:0] cis32;
|
||||
reg [47:0] ci48;
|
||||
reg signed [47:0] cis48;
|
||||
reg [63:0] ci64;
|
||||
reg signed [63:0] cis64;
|
||||
reg [95:0] ci96;
|
||||
reg signed [95:0] cis96;
|
||||
real r, r2;
|
||||
integer cyc=0;
|
||||
|
||||
@ -88,6 +99,41 @@ module t (/*AUTOARG*/
|
||||
// bug
|
||||
b = 64'h7fe8000000000000;
|
||||
$display("%6.3f", $bitstoreal(b));
|
||||
// bug
|
||||
i48 = 48'hff00_00000000;
|
||||
r = real'(i48);
|
||||
if (r != 280375465082880.0) $stop;
|
||||
r = $itor(i48);
|
||||
if (r != 280375465082880.0) $stop;
|
||||
|
||||
is48 = 48'shff00_00000000;
|
||||
r = real'(is48);
|
||||
if (r != -1099511627776.0) $stop;
|
||||
r = $itor(is48);
|
||||
if (r != -1099511627776.0) $stop;
|
||||
|
||||
r = 0;
|
||||
r = i48;
|
||||
if (r != 280375465082880.0) $stop;
|
||||
r = 0;
|
||||
|
||||
r = $itor(-10);
|
||||
if (r != -10.0) $stop;
|
||||
|
||||
r = real'(4'sb1111);
|
||||
if (r != -1) $stop;
|
||||
r = $itor(4'sb1111);
|
||||
if (r != -1) $stop;
|
||||
|
||||
r = real'(4'b1111);
|
||||
if (r != 15) $stop;
|
||||
r = $itor(4'b1111);
|
||||
if (r != 15) $stop;
|
||||
|
||||
r = real'(96'hf0000000_00000000_00000000);
|
||||
if (r != 74276402357122816493947453440.0) $stop;
|
||||
r = real'(96'shf0000000_00000000_00000000);
|
||||
if (r != -4951760157141521099596496896.0) $stop;
|
||||
end
|
||||
|
||||
// Test loop
|
||||
@ -98,8 +144,18 @@ module t (/*AUTOARG*/
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
ci48 <= '0;
|
||||
cis48 <= '0;
|
||||
ci96 <= '0;
|
||||
cis96 <= '0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
else if (cyc == 1) begin
|
||||
ci48 <= 48'hff00_00000000;
|
||||
cis48 <= 48'shff00_00000000;
|
||||
ci96 <= 96'hf0000000_00000000_00000000;
|
||||
cis96 <= 96'shf0000000_00000000_00000000;
|
||||
end
|
||||
else if (cyc<80) begin
|
||||
if ($time != {32'h0, $rtoi($realtime)}) $stop;
|
||||
if ($itor(cyc) != cyc) $stop;
|
||||
//Unsup: if ((real `($time)) != $realtime) $stop;
|
||||
@ -141,6 +197,76 @@ module t (/*AUTOARG*/
|
||||
!= (((cyc-50)!=0) ? 10 : 20)) $stop;
|
||||
//
|
||||
if ((!(r-50.0)) != (!((cyc-50) != 0))) $stop;
|
||||
//
|
||||
r = real'(ci48);
|
||||
`checkr(r, 280375465082880.0);
|
||||
r = real'(cis48);
|
||||
`checkr(r, -1099511627776.0);
|
||||
//
|
||||
r = real'(ci96);
|
||||
`checkr(r, 74276402357122816493947453440.0);
|
||||
r = real'(cis96);
|
||||
`checkr(r, -4951760157141521099596496896.0);
|
||||
end
|
||||
else if (cyc==90) begin
|
||||
ci32 <= '0;
|
||||
cis32 <= '0;
|
||||
ci48 <= '0;
|
||||
cis48 <= '0;
|
||||
ci64 <= '0;
|
||||
cis64 <= '0;
|
||||
ci96 <= '0;
|
||||
cis96 <= '0;
|
||||
end
|
||||
else if (cyc==91) begin
|
||||
`checkr(real'(ci32), 0.0);
|
||||
`checkr(real'(cis32), 0.0);
|
||||
`checkr(real'(ci48), 0.0);
|
||||
`checkr(real'(cis48), 0.0);
|
||||
`checkr(real'(ci64), 0.0);
|
||||
`checkr(real'(cis64), 0.0);
|
||||
`checkr(real'(ci96), 0.0);
|
||||
`checkr(real'(cis96), 0.0);
|
||||
end
|
||||
else if (cyc==92) begin
|
||||
ci32 <= 32'b1;
|
||||
cis32 <= 32'b1;
|
||||
ci48 <= 48'b1;
|
||||
cis48 <= 48'b1;
|
||||
ci64 <= 64'b1;
|
||||
cis64 <= 64'b1;
|
||||
ci96 <= 96'b1;
|
||||
cis96 <= 96'b1;
|
||||
end
|
||||
else if (cyc==93) begin
|
||||
`checkr(real'(ci32), 1.0);
|
||||
`checkr(real'(cis32), 1.0);
|
||||
`checkr(real'(ci48), 1.0);
|
||||
`checkr(real'(cis48), 1.0);
|
||||
`checkr(real'(ci64), 1.0);
|
||||
`checkr(real'(cis64), 1.0);
|
||||
`checkr(real'(ci96), 1.0);
|
||||
`checkr(real'(cis96), 1.0);
|
||||
end
|
||||
else if (cyc==94) begin
|
||||
ci32 <= ~ '0;
|
||||
cis32 <= ~ '0;
|
||||
ci48 <= ~ '0;
|
||||
cis48 <= ~ '0;
|
||||
ci64 <= ~ '0;
|
||||
cis64 <= ~ '0;
|
||||
ci96 <= ~ '0;
|
||||
cis96 <= ~ '0;
|
||||
end
|
||||
else if (cyc==95) begin
|
||||
`checkr(real'(ci32), 4294967295.0);
|
||||
`checkr(real'(cis32), -1.0);
|
||||
`checkr(real'(ci48), 281474976710655.0);
|
||||
`checkr(real'(cis48), -1.0);
|
||||
`checkr(real'(ci64), 18446744073709551616.0);
|
||||
`checkr(real'(cis64), -1.0);
|
||||
`checkr(real'(ci96), 79228162514264337593543950336.0);
|
||||
`checkr(real'(cis96), -1.0);
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
21
test_regress/t/t_math_real_random.pl
Executable file
21
test_regress/t/t_math_real_random.pl
Executable 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 2019 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;
|
100
test_regress/t/t_math_real_random.v
Normal file
100
test_regress/t/t_math_real_random.v
Normal file
@ -0,0 +1,100 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
reg [127:0] in;
|
||||
|
||||
check #(48) check48 (.*);
|
||||
check #(31) check31 (.*);
|
||||
check #(32) check32 (.*);
|
||||
check #(63) check63 (.*);
|
||||
check #(64) check64 (.*);
|
||||
check #(96) check96 (.*);
|
||||
check #(128) check128 (.*);
|
||||
|
||||
always_comb begin
|
||||
if (crc[2:0] == 0) in = '0;
|
||||
else if (crc[2:0] == 1) in = ~'0;
|
||||
else if (crc[2:0] == 2) in = 128'b1;
|
||||
else if (crc[2:0] == 3) in = ~ 128'b1;
|
||||
else begin
|
||||
in = {crc, crc};
|
||||
if (crc[3]) in[31:0] = '0;
|
||||
if (crc[4]) in[63:32] = '0;
|
||||
if (crc[5]) in[95:64] = '0;
|
||||
if (crc[6]) in[127:96] = '0;
|
||||
if (crc[7]) in[31:0] = ~'0;
|
||||
if (crc[8]) in[63:32] = ~'0;
|
||||
if (crc[9]) in[95:64] = ~'0;
|
||||
if (crc[10]) in[127:96] = ~'0;
|
||||
end
|
||||
end
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d in=%x\n",$time, cyc, in);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
if (cyc == 0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc == 99) begin
|
||||
`checkr(check48.sum, 14574057015683440.000000);
|
||||
`checkr(check31.sum, 114141374814.000000);
|
||||
`checkr(check32.sum, 236547942750.000000);
|
||||
`checkr(check63.sum, 513694866079917670400.000000);
|
||||
`checkr(check64.sum, 1002533584033221181440.000000);
|
||||
`checkr(check96.sum, 4377373669974269260279175970816.000000);
|
||||
`checkr(check128.sum, 18358899571808044815012294240949812330496.000000);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module check(/*AUTOARG*/
|
||||
// Inputs
|
||||
in, clk, cyc
|
||||
);
|
||||
parameter WIDTH = 128;
|
||||
input [127:0] in;
|
||||
|
||||
wire [WIDTH-1:0] ci = in[WIDTH-1:0];
|
||||
wire signed [WIDTH-1:0] cis = in[WIDTH-1:0];
|
||||
|
||||
real r;
|
||||
real rs;
|
||||
always_comb r = ci;
|
||||
always_comb rs = cis;
|
||||
|
||||
input clk;
|
||||
input integer cyc;
|
||||
real sum;
|
||||
|
||||
always_ff @ (negedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] w%0d in=%h r=%f rs=%f sum=%f\n", $time, WIDTH, ci, r, rs, sum);
|
||||
`endif
|
||||
if (cyc < 10) sum <= 0;
|
||||
else sum <= sum + r + rs;
|
||||
end
|
||||
endmodule
|
@ -1,7 +1,10 @@
|
||||
%Error-UNSUPPORTED: t/t_math_wide_bad.v:21:18: Unsupported: operator POWSS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
|
||||
21 | assign z2 = a ** 3;
|
||||
%Error-UNSUPPORTED: t/t_math_wide_bad.v:22:18: Unsupported: operator POWSS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
|
||||
22 | assign z2 = a ** 3;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_math_wide_bad.v:20:17: Unsupported: operator MULS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
|
||||
20 | assign z = a * b;
|
||||
%Error-UNSUPPORTED: t/t_math_wide_bad.v:23:15: Unsupported: operator ISTORD operator of 64 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
|
||||
23 | assign r = real'(a);
|
||||
| ^~~~
|
||||
%Error-UNSUPPORTED: t/t_math_wide_bad.v:21:17: Unsupported: operator MULS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h
|
||||
21 | assign z = a * b;
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
z, z2,
|
||||
z, z2, r,
|
||||
// Inputs
|
||||
a, b
|
||||
);
|
||||
@ -16,8 +16,10 @@ module t (/*AUTOARG*/
|
||||
|
||||
output signed [17*32 : 0] z;
|
||||
output signed [17*32 : 0] z2;
|
||||
output real r;
|
||||
|
||||
assign z = a * b;
|
||||
assign z2 = a ** 3;
|
||||
assign r = real'(a);
|
||||
|
||||
endmodule
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
`define ratio_error(a,b) (((a)>(b) ? ((a)-(b)) : ((b)-(a))) /(a))
|
||||
`define checkr(gotv,expv) do if (`ratio_error((gotv),(expv))>0.0001) begin $write("%%Error: %s:%0d: got=%g exp=%g\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checkr(gotv,expv) do if (`ratio_error((gotv),(expv))>0.0001) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
|
@ -11,7 +11,7 @@ module t (/*AUTOARG*/
|
||||
input clk;
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%g exp=%g\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
// IEEE: integer_atom_type
|
||||
wire byte w_byte;
|
||||
|
Loading…
Reference in New Issue
Block a user