Fix 10s/100s timeunits.

This commit is contained in:
Wilson Snyder 2020-05-11 08:15:52 -04:00
parent fac43811fd
commit 29695adf70
10 changed files with 140 additions and 80 deletions

View File

@ -244,8 +244,8 @@ Verilated::Serialized::Serialized() {
s_errorLimit = 1; s_errorLimit = 1;
s_randReset = 0; s_randReset = 0;
s_randSeed = 0; s_randSeed = 0;
s_timeunit = -VL_TIME_UNIT; // Initial value until overriden by _Vconfigure s_timeunit = VL_TIME_UNIT; // Initial value until overriden by _Vconfigure
s_timeprecision = -VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
} }
Verilated::NonSerialized::NonSerialized() { Verilated::NonSerialized::NonSerialized() {
@ -2007,14 +2007,13 @@ int VL_TIME_STR_CONVERT(const char* strp) {
} }
static const char* vl_time_str(int scale) { static const char* vl_time_str(int scale) {
static const char* const names[] static const char* const names[]
= {"1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns", = {"100s", "10s", "1s", "100ms", "10ms", "1ms", "100us", "10us", "1us",
"10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs"}; "100ns", "10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs"};
if (scale < 0) scale = -scale; if (VL_UNLIKELY(scale > 2 || scale < -15)) scale = 0;
if (VL_UNLIKELY(scale > 15)) scale = 0; return names[2 - scale];
return names[scale];
} }
double vl_time_multiplier(int scale) { double vl_time_multiplier(int scale) {
// Return timescale multipler -15 to +15 // Return timescale multipler -18 to +18
// For speed, this does not check for illegal values // For speed, this does not check for illegal values
static double pow10[] = {1.0, static double pow10[] = {1.0,
10.0, 10.0,
@ -2031,7 +2030,10 @@ double vl_time_multiplier(int scale) {
1000000000000.0, 1000000000000.0,
10000000000000.0, 10000000000000.0,
100000000000000.0, 100000000000000.0,
1000000000000000.0}; 1000000000000000.0,
10000000000000000.0,
100000000000000000.0,
1000000000000000000.0};
static double neg10[] = {1.0, static double neg10[] = {1.0,
0.1, 0.1,
0.01, 0.01,
@ -2047,7 +2049,10 @@ double vl_time_multiplier(int scale) {
0.000000000001, 0.000000000001,
0.0000000000001, 0.0000000000001,
0.00000000000001, 0.00000000000001,
0.000000000000001}; 0.000000000000001,
0.0000000000000001,
0.00000000000000001,
0.000000000000000001};
if (scale < 0) { if (scale < 0) {
return neg10[-scale]; return neg10[-scale];
} else { } else {

View File

@ -386,8 +386,8 @@ class Verilated {
bool s_assertOn; ///< Assertions are enabled bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
// Slow path // Slow path
unsigned s_timeunit : 4; ///< Time unit as 0..15 vlsint8_t s_timeunit; ///< Time unit as 0..15
unsigned s_timeprecision : 4; ///< Time precision as 0..15 vlsint8_t s_timeprecision; ///< Time precision as 0..15
int s_errorCount; ///< Number of errors int s_errorCount; ///< Number of errors
int s_errorLimit; ///< Stop on error number int s_errorLimit; ///< Stop on error number
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

View File

@ -2308,12 +2308,12 @@ void EmitCImp::emitConfigureImp(AstNodeModule* modp) {
puts("if (false && this->__VlSymsp) {} // Prevent unused\n"); puts("if (false && this->__VlSymsp) {} // Prevent unused\n");
if (v3Global.opt.coverage()) { puts(protect("_configure_coverage") + "(vlSymsp, first);\n"); } if (v3Global.opt.coverage()) { puts(protect("_configure_coverage") + "(vlSymsp, first);\n"); }
if (modp->isTop() && !v3Global.rootp()->timeunit().isNone()) { if (modp->isTop() && !v3Global.rootp()->timeunit().isNone()) {
puts("Verilated::timeunit(" + cvtToStr(v3Global.rootp()->timeunit().negativeInt()) puts("Verilated::timeunit(" + cvtToStr(v3Global.rootp()->timeunit().powerOfTen())
+ ");\n"); + ");\n");
} }
if (modp->isTop() && !v3Global.rootp()->timeprecision().isNone()) { if (modp->isTop() && !v3Global.rootp()->timeprecision().isNone()) {
puts("Verilated::timeprecision(" puts("Verilated::timeprecision("
+ cvtToStr(v3Global.rootp()->timeprecision().negativeInt()) + ");\n"); + cvtToStr(v3Global.rootp()->timeprecision().powerOfTen()) + ");\n");
} }
puts("}\n"); puts("}\n");
splitSizeInc(10); splitSizeInc(10);

View File

@ -292,7 +292,7 @@ class EmitCSyms : EmitCBaseVisitor {
string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE"; string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE";
string name = nodep->scopep()->name() + "__DOT__" + nodep->name(); string name = nodep->scopep()->name() + "__DOT__" + nodep->name();
string name_dedot = AstNode::dedotName(name); string name_dedot = AstNode::dedotName(name);
int timeunit = m_modp->timeunit().negativeInt(); int timeunit = m_modp->timeunit().powerOfTen();
m_vpiScopeCandidates.insert( m_vpiScopeCandidates.insert(
make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type))); make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type)));
} }
@ -305,7 +305,7 @@ class EmitCSyms : EmitCBaseVisitor {
if (v3Global.opt.vpi() && !nodep->isTop()) { if (v3Global.opt.vpi() && !nodep->isTop()) {
string name_dedot = AstNode::dedotName(nodep->shortName()); string name_dedot = AstNode::dedotName(nodep->shortName());
int timeunit = m_modp->timeunit().negativeInt(); int timeunit = m_modp->timeunit().powerOfTen();
m_vpiScopeCandidates.insert( m_vpiScopeCandidates.insert(
make_pair(nodep->name(), ScopeData(scopeSymString(nodep->name()), name_dedot, make_pair(nodep->name(), ScopeData(scopeSymString(nodep->name()), name_dedot,
timeunit, "SCOPE_MODULE"))); timeunit, "SCOPE_MODULE")));
@ -315,7 +315,7 @@ class EmitCSyms : EmitCBaseVisitor {
string name = nodep->scopeSymName(); string name = nodep->scopeSymName();
// UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName() // UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()
// <<" ss"<<name<<endl); // <<" ss"<<name<<endl);
int timeunit = m_modp ? m_modp->timeunit().negativeInt() : 0; int timeunit = m_modp ? m_modp->timeunit().powerOfTen() : 0;
if (m_scopeNames.find(name) == m_scopeNames.end()) { if (m_scopeNames.find(name) == m_scopeNames.end()) {
m_scopeNames.insert(make_pair( m_scopeNames.insert(make_pair(
name, ScopeData(name, nodep->scopePrettySymName(), timeunit, "SCOPE_OTHER"))); name, ScopeData(name, nodep->scopePrettySymName(), timeunit, "SCOPE_OTHER")));

View File

@ -125,7 +125,7 @@ VTimescale::VTimescale(const string& value, bool& badr)
: m_e(VTimescale::NONE) { : m_e(VTimescale::NONE) {
badr = true; badr = true;
string spaceless = VString::removeWhitespace(value); string spaceless = VString::removeWhitespace(value);
for (int i = TS_1S; i < _ENUM_END; ++i) { for (int i = TS_100S; i < _ENUM_END; ++i) {
VTimescale ts(i); VTimescale ts(i);
if (spaceless == ts.ascii()) { if (spaceless == ts.ascii()) {
badr = false; badr = false;

View File

@ -72,15 +72,15 @@ inline std::ostream& operator<<(std::ostream& os, const VOptionBool& rhs) {
class VTimescale { class VTimescale {
public: public:
enum en { enum en {
TS_1S = 0,
// clang-format off // clang-format off
TS_100MS = 1, TS_10MS = 2, TS_1MS = 3, TS_100S = 0, TS_10S = 1, TS_1S = 2,
TS_100US = 4, TS_10US = 5, TS_1US = 6, TS_100MS = 3, TS_10MS = 4, TS_1MS = 5,
TS_100NS = 7, TS_10NS = 8, TS_1NS = 9, TS_100US = 6, TS_10US = 7, TS_1US = 8,
TS_100PS = 10, TS_10PS = 11, TS_1PS = 12, TS_100NS = 9, TS_10NS = 10, TS_1NS = 11,
TS_100FS = 13, TS_10FS = 14, TS_1FS = 15, TS_100PS = 12, TS_10PS = 13, TS_1PS = 14,
TS_100FS = 15, TS_10FS = 16, TS_1FS = 17,
// clang-format on // clang-format on
NONE = 16, NONE = 18,
_ENUM_END _ENUM_END
}; };
enum { TS_DEFAULT = TS_1PS }; enum { TS_DEFAULT = TS_1PS };
@ -93,13 +93,14 @@ public:
: m_e(_e) {} : m_e(_e) {}
explicit inline VTimescale(int _e) explicit inline VTimescale(int _e)
: m_e(static_cast<en>(_e)) {} : m_e(static_cast<en>(_e)) {}
int negativeInt() { return -static_cast<int>(m_e); }
// Construct from string // Construct from string
VTimescale(const string& value, bool& badr); VTimescale(const string& value, bool& badr);
VTimescale(double value, bool& badr) { VTimescale(double value, bool& badr) {
badr = false; badr = false;
// clang-format off // clang-format off
if (value == 1e0) m_e = TS_1S; if (value == 10e2) m_e = TS_100S;
else if (value == 1e1) m_e = TS_10S;
else if (value == 1e0) m_e = TS_1S;
else if (value == 1e-1) m_e = TS_100MS; else if (value == 1e-1) m_e = TS_100MS;
else if (value == 1e-2) m_e = TS_10MS; else if (value == 1e-2) m_e = TS_10MS;
else if (value == 1e-3) m_e = TS_1MS; else if (value == 1e-3) m_e = TS_1MS;
@ -127,13 +128,14 @@ public:
bool allowEmpty = false); bool allowEmpty = false);
const char* ascii() const { const char* ascii() const {
static const char* const names[] static const char* const names[]
= {"1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns", "10ns", = {"100s", "10s", "1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns",
"1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs", "NONE"}; "10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs", "NONE"};
return names[m_e]; return names[m_e];
} }
int powerOfTen() { return 2 - static_cast<int>(m_e); }
double multiplier() const { double multiplier() const {
static double values[] = {1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, static double values[] = {100, 10, 1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7,
1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 0}; 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 0};
return values[m_e]; return values[m_e];
} }
}; };

View File

@ -1,2 +1,2 @@
%Error: SystemC's sc_set_time_resolution is 10^-9, which does not match Verilog timeprecision 10^-12. Suggest use 'sc_set_time_resolution(1ps)', or Verilator '--timescale-override 1ns/1ns' %Error: SystemC's sc_set_time_resolution is 10^-9, which does not match Verilog timeprecision 10^-12. Suggest use 'sc_set_time_resolution(1s)', or Verilator '--timescale-override 1s/1s'
Aborting... Aborting...

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 100s / 10ms
[100000000] time%0d=10000 123%0t=1230000
dig%0t=0 dig%0d=0
rdig%0t=543 rdig%0f=0.054321
[0.000000ns] time%0d=10000 123%0t=12300000000000.000000ns
dig%0t=0.000000ns dig%0d=0
rdig%0t=5432109876.543210ns rdig%0f=0.054321
[0.000000ns] stime%0t=0.000000ns stime%0d=10000 stime%0f=10000.000000
[0.000000ns] rtime%0t=0.000000ns rtime%0d=10000 rtime%0f=10000.000000
global vpiSimTime = 0,100000000 vpiScaledRealTime = 1e+08
global vpiTimeUnit = -2 vpiTimePrecision = -2
top.t vpiSimTime = 0,100000000 vpiScaledRealTime = 10000
top.t vpiTimeUnit = 2 vpiTimePrecision = -2
*-* All Finished *-*

View File

@ -0,0 +1,30 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 100e0 / 10e-6;
compile(
v_flags2 => ['+define+time_scale_units=100s +define+time_scale_prec=10ms',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -12,38 +12,42 @@ module modname; \
task check; t = 1ns; $write("%m %0t\n", t); endtask \ task check; t = 1ns; $write("%m %0t\n", t); endtask \
endmodule endmodule
`timescale 100s/1fs
`testmod(sp2)
`timescale 10s/1fs
`testmod(sp1)
`timescale 1s/1fs `timescale 1s/1fs
`testmod(s0) `testmod(sp0)
`timescale 100ms/1fs `timescale 100ms/1fs
`testmod(s1) `testmod(sm1)
`timescale 10ms/1fs `timescale 10ms/1fs
`testmod(s2) `testmod(sm2)
`timescale 1ms/1fs `timescale 1ms/1fs
`testmod(s3) `testmod(sm3)
`timescale 100us/1fs `timescale 100us/1fs
`testmod(s4) `testmod(sm4)
`timescale 10us/1fs `timescale 10us/1fs
`testmod(s5) `testmod(sm5)
`timescale 1us/1fs `timescale 1us/1fs
`testmod(s6) `testmod(sm6)
`timescale 100ns/1fs `timescale 100ns/1fs
`testmod(s7) `testmod(sm7)
`timescale 10ns/1fs `timescale 10ns/1fs
`testmod(s8) `testmod(sm8)
`timescale 1ns/1fs `timescale 1ns/1fs
`testmod(s9) `testmod(sm9)
`timescale 100ps/1fs `timescale 100ps/1fs
`testmod(s10) `testmod(sm10)
`timescale 10ps/1fs `timescale 10ps/1fs
`testmod(s11) `testmod(sm11)
`timescale 1ps/1fs `timescale 1ps/1fs
`testmod(s12) `testmod(sm12)
`timescale 100 fs/1fs `timescale 100 fs/1fs
`testmod(s13) `testmod(sm13)
`timescale 10fs/1 fs `timescale 10fs/1 fs
`testmod(s14) `testmod(sm14)
`timescale 1 fs / 1 fs // Comment `timescale 1 fs / 1 fs // Comment
`testmod(s15) `testmod(sm15)
module r0; module r0;
@ -58,43 +62,47 @@ module r1;
endmodule endmodule
module t; module t;
s0 s0(); sp2 sp2();
s1 s1(); sp1 sp1();
s2 s2(); sp0 sp0();
s3 s3(); sm1 sm1();
s4 s4(); sm2 sm2();
s5 s5(); sm3 sm3();
s6 s6(); sm4 sm4();
s7 s7(); sm5 sm5();
s8 s8(); sm6 sm6();
s9 s9(); sm7 sm7();
s10 s10(); sm8 sm8();
s11 s11(); sm9 sm9();
s12 s12(); sm10 sm10();
s13 s13(); sm11 sm11();
s14 s14(); sm12 sm12();
s15 s15(); sm13 sm13();
sm14 sm14();
sm15 sm15();
r0 r0(); r0 r0();
r1 r1(); r1 r1();
final begin final begin
s0.check(); sp2.check();
s1.check(); sp1.check();
s2.check(); sp0.check();
s3.check(); sm1.check();
s4.check(); sm2.check();
s5.check(); sm3.check();
s6.check(); sm4.check();
s7.check(); sm5.check();
s8.check(); sm6.check();
s9.check(); sm7.check();
s10.check(); sm8.check();
s11.check(); sm9.check();
s12.check(); sm10.check();
s13.check(); sm11.check();
s14.check(); sm12.check();
s15.check(); sm13.check();
sm14.check();
sm15.check();
r0.check(); r0.check();
r1.check(); r1.check();
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");