From ed93a111c285ce36e185ed45a45cf9e0d33c9b6a Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Wed, 26 Oct 2022 13:50:28 +0200 Subject: [PATCH] Fix deadlock in ``timeprecision`` when using systemC (#3707) --- include/verilated.cpp | 36 ++++++++++++++++------------- test_regress/t/t_time_sc_bad_mt.out | 2 ++ test_regress/t/t_time_sc_bad_mt.pl | 30 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 test_regress/t/t_time_sc_bad_mt.out create mode 100755 test_regress/t/t_time_sc_bad_mt.pl diff --git a/include/verilated.cpp b/include/verilated.cpp index 506c1e5f7..6428c4ee5 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -2426,23 +2426,25 @@ void VerilatedContext::timeunit(int value) VL_MT_SAFE { } void VerilatedContext::timeprecision(int value) VL_MT_SAFE { if (value < 0) value = -value; // Stored as 0..15 - const VerilatedLockGuard lock{m_mutex}; - m_s.m_timeprecision = value; -#ifdef SYSTEMC_VERSION - const sc_time sc_res = sc_get_time_resolution(); int sc_prec = 99; - if (sc_res == sc_time(1, SC_SEC)) { - sc_prec = 0; - } else if (sc_res == sc_time(1, SC_MS)) { - sc_prec = 3; - } else if (sc_res == sc_time(1, SC_US)) { - sc_prec = 6; - } else if (sc_res == sc_time(1, SC_NS)) { - sc_prec = 9; - } else if (sc_res == sc_time(1, SC_PS)) { - sc_prec = 12; - } else if (sc_res == sc_time(1, SC_FS)) { - sc_prec = 15; + { + const VerilatedLockGuard lock{m_mutex}; + m_s.m_timeprecision = value; +#ifdef SYSTEMC_VERSION + const sc_time sc_res = sc_get_time_resolution(); + if (sc_res == sc_time(1, SC_SEC)) { + sc_prec = 0; + } else if (sc_res == sc_time(1, SC_MS)) { + sc_prec = 3; + } else if (sc_res == sc_time(1, SC_US)) { + sc_prec = 6; + } else if (sc_res == sc_time(1, SC_NS)) { + sc_prec = 9; + } else if (sc_res == sc_time(1, SC_PS)) { + sc_prec = 12; + } else if (sc_res == sc_time(1, SC_FS)) { + sc_prec = 15; + } } if (value != sc_prec) { std::ostringstream msg; @@ -2454,6 +2456,8 @@ void VerilatedContext::timeprecision(int value) VL_MT_SAFE { const std::string msgs = msg.str(); VL_FATAL_MT("", 0, "", msgs.c_str()); } +#else + } #endif } const char* VerilatedContext::timeunitString() const VL_MT_SAFE { return vl_time_str(timeunit()); } diff --git a/test_regress/t/t_time_sc_bad_mt.out b/test_regress/t/t_time_sc_bad_mt.out new file mode 100644 index 000000000..86603162d --- /dev/null +++ b/test_regress/t/t_time_sc_bad_mt.out @@ -0,0 +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(1s)', or Verilator '--timescale-override 1s/1s' +Aborting... diff --git a/test_regress/t/t_time_sc_bad_mt.pl b/test_regress/t/t_time_sc_bad_mt.pl new file mode 100755 index 000000000..6b6f6d637 --- /dev/null +++ b/test_regress/t/t_time_sc_bad_mt.pl @@ -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(vltmt => 1); + +top_filename("t/t_time_sc.v"); + +$Self->{sc_time_resolution} = 'SC_NS'; + +compile( + verilator_flags2 => ['-sc', '-timescale 1ps/1ps', # Mismatch w/sc_time_resolution + '+define+TEST_EXPECT=2us'], + threads => 2, + ); + +execute( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); + +1;