From c702fc944e4ae1da0a5da1c792347130a13fff00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Chmiel?= Date: Fri, 2 Feb 2024 13:00:13 +0100 Subject: [PATCH] Fix SystemC biguint sign desynchronization (#4870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix writing to SystemC values with `VL_ASSIGN_SBW` Signed-off-by: Krzysztof Bieganski Co-authored-by: Bartłomiej Chmiel --- docs/CONTRIBUTORS | 1 + include/verilated_funcs.h | 1 + test_regress/t/t_vl_assign_sbw.cpp | 36 ++++++++++++++++++++++++++++++ test_regress/t/t_vl_assign_sbw.pl | 24 ++++++++++++++++++++ test_regress/t/t_vl_assign_sbw.v | 29 ++++++++++++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 test_regress/t/t_vl_assign_sbw.cpp create mode 100755 test_regress/t/t_vl_assign_sbw.pl create mode 100644 test_regress/t/t_vl_assign_sbw.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index cf5f12e42..098df0de4 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -19,6 +19,7 @@ Andrew Nolte Anthony Donlon Arkadiusz Kozdra Aylon Chaim Porat +Bartłomiej Chmiel Cameron Kirk Chih-Mao Chen Chris Randall diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index c997c7d65..b53cd2ab8 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -520,6 +520,7 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE { const uint32_t msb_data = VL_SEL_IWII((obits) + 1, (rwp).data(), lsb, (obits)-lsb); \ *chunkp = msb_data & VL_MASK_E((obits)-lsb); \ } \ + _butemp.set(0, *(rwp).data() & 1); /* force update the sign */ \ (svar).write(_butemp); \ } diff --git a/test_regress/t/t_vl_assign_sbw.cpp b/test_regress/t/t_vl_assign_sbw.cpp new file mode 100644 index 000000000..4b07210dd --- /dev/null +++ b/test_regress/t/t_vl_assign_sbw.cpp @@ -0,0 +1,36 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +#include VM_PREFIX_INCLUDE + +#include + +#include + +int sc_main(int argc, char* argv[]) { + using namespace sc_core; + + VM_PREFIX* tb = new VM_PREFIX{"t"}; + constexpr int val = 1; + sc_signal> SC_NAMED(in, val); + sc_signal> SC_NAMED(out); + + tb->in(in); + tb->out(out); + + bool pass = out.read().iszero(); + + sc_start(1, SC_NS); + + pass &= !out.read().iszero(); + pass &= out == val; + + tb->final(); + VL_DO_DANGLING(delete tb, tb); + + if (pass) { VL_PRINTF("*-* All Finished *-*\n"); } + + return 0; +} diff --git a/test_regress/t/t_vl_assign_sbw.pl b/test_regress/t/t_vl_assign_sbw.pl new file mode 100755 index 000000000..8d5b8bcd0 --- /dev/null +++ b/test_regress/t/t_vl_assign_sbw.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Antmicro. 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( + make_top_shell => 0, + make_main => 0, + verilator_flags2 => ["--exe --pins-sc-biguint --sc $Self->{t_dir}/t_vl_assign_sbw.cpp"], +); + +execute( + check_finished => 1 +); + +ok(1); +1; diff --git a/test_regress/t/t_vl_assign_sbw.v b/test_regress/t/t_vl_assign_sbw.v new file mode 100644 index 000000000..348ea05e5 --- /dev/null +++ b/test_regress/t/t_vl_assign_sbw.v @@ -0,0 +1,29 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. 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 + +module t( + input [255:0] in, + output [255:0] out + ); + + // do not optimize assignment + logic tmp = $c(0); + typedef logic[255:0] biguint; + assign out = in + biguint'(tmp); + + always @(out) begin + if (in !== 1) begin + $write("'in' mismatch: (1 !== %d)\n", logic'(in)); + $stop; + end + else if (out !== 1) begin + $write("'out' mismatch: (1 !== %d)\n", logic'(out)); + $stop; + end + end +endmodule