diff --git a/Changes b/Changes index 7ff484f82..f56dd042e 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.011 devel +*** Add +verilator+seed, bug1396. [Stan Sokorac] + * Verilator 4.010 2019-01-27 diff --git a/bin/verilator b/bin/verilator index ee6af7e48..bceba8bd2 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1599,6 +1599,11 @@ When a model was Verilated using "-x-inital unique", sets the initialization technique. 0 = Reset to zeros. 1 = Reset to all-ones. 2 = Randomize. See L. +=item +verilator+seed+I + +For $random and "-x-initial unique", set the random seed value. If zero or +not specified picks a value from the system random number generator. + =item +verilator+V Shows the verbose version, including configuration information. diff --git a/include/verilated.cpp b/include/verilated.cpp index 2c6979a1a..ab406b9fb 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -208,6 +208,7 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE { Verilated::Serialized::Serialized() { s_randReset = 0; + s_randSeed = 0; s_debug = 0; s_calcUnusedSigs = false; s_gotFinish = false; @@ -245,18 +246,25 @@ vluint64_t vl_rand64() VL_MT_SAFE { static VL_THREAD_LOCAL bool t_seeded = false; static VL_THREAD_LOCAL vluint64_t t_state[2]; if (VL_UNLIKELY(!t_seeded)) { - t_seeded = true; - { - VerilatedLockGuard lock(s_mutex); - t_state[0] = ((static_cast(vl_sys_rand32()) << 32) - ^ (static_cast(vl_sys_rand32()))); - t_state[1] = ((static_cast(vl_sys_rand32()) << 32) - ^ (static_cast(vl_sys_rand32()))); + t_seeded = true; + { + VerilatedLockGuard lock(s_mutex); + if (Verilated::randSeed() != 0) { + t_state[0] = ((static_cast(Verilated::randSeed()) << 32) + ^ (static_cast(Verilated::randSeed()))); + t_state[1] = ((static_cast(Verilated::randSeed()) << 32) + ^ (static_cast(Verilated::randSeed()))); + } else { + t_state[0] = ((static_cast(vl_sys_rand32()) << 32) + ^ (static_cast(vl_sys_rand32()))); + t_state[1] = ((static_cast(vl_sys_rand32()) << 32) + ^ (static_cast(vl_sys_rand32()))); + } // Fix state as algorithm is slow to randomize if many zeros // This causes a loss of ~ 1 bit of seed entropy, no big deal if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0]; if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1]; - } + } } // Xoroshiro128+ algorithm vluint64_t result = t_state[0] + t_state[1]; @@ -1670,6 +1678,10 @@ void Verilated::randReset(int val) VL_MT_SAFE { VerilatedLockGuard lock(m_mutex); s_s.s_randReset = val; } +void Verilated::randSeed(int val) VL_MT_SAFE { + VerilatedLockGuard lock(m_mutex); + s_s.s_randSeed = val; +} void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE { VerilatedLockGuard lock(m_mutex); s_s.s_calcUnusedSigs = flag; @@ -1879,6 +1891,9 @@ void VerilatedImp::commandArgVl(const std::string& arg) { else if (commandArgVlValue(arg, "+verilator+rand+reset+", value/*ref*/)) { Verilated::randReset(atoi(value.c_str())); } + else if (commandArgVlValue(arg, "+verilator+seed+", value/*ref*/)) { + Verilated::randSeed(atoi(value.c_str())); + } else if (arg == "+verilator+V") { versionDump(); // Someday more info too VL_FATAL_MT("COMMAND_LINE", 0, "", "Exiting due to command line argument (not an error)"); diff --git a/include/verilated.h b/include/verilated.h index c936b730e..a02fc5c37 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -342,7 +342,8 @@ class Verilated { bool s_assertOn; ///< Assertions are enabled bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported // Slow path - int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random + int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random + int s_randSeed; ///< Random seed: 0=random Serialized(); ~Serialized() {} } s_s; @@ -396,6 +397,8 @@ public: /// 2 = Randomize all bits static void randReset(int val) VL_MT_SAFE; static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value + static void randSeed(int val) VL_MT_SAFE; + static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value /// Enable debug of internal verilated code static void debug(int level) VL_MT_SAFE; diff --git a/test_regress/t/t_runflag_seed.pl b/test_regress/t/t_runflag_seed.pl new file mode 100755 index 000000000..f5639384e --- /dev/null +++ b/test_regress/t/t_runflag_seed.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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. + +scenarios(vlt_all => 1); + +compile( + ); + +execute( + all_run_flags => ["+verilator+seed+5 +SEED=fffffff4"], + fails => 0, + ); + +execute( + all_run_flags => ["+verilator+seed+6 +SEED=fffffff2"], + fails => 0, + ); + +ok(1); + +1; diff --git a/test_regress/t/t_runflag_seed.v b/test_regress/t/t_runflag_seed.v new file mode 100644 index 000000000..16e901d19 --- /dev/null +++ b/test_regress/t/t_runflag_seed.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +`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); + +module t; + initial begin + integer r = $random; + integer ex; + if ($value$plusargs("SEED=%x", ex) !== 1) $stop; + `checkh(r, ex); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule