From 9e2c8aefc8a7c789c267a13cf36a4b2854384330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Chmiel?= Date: Tue, 25 Jun 2024 11:27:09 +0200 Subject: [PATCH] Add `--pins-sc-uint-bool` to force SystemC uint type (#5192) --- bin/verilator | 1 + docs/guide/exe_verilator.rst | 4 ++ src/V3AstNodeOther.h | 1 + src/V3AstNodes.cpp | 5 +- src/V3EmitCFunc.h | 8 ++-- src/V3EmitCImp.cpp | 2 +- src/V3Options.cpp | 1 + src/V3Options.h | 2 + test_regress/driver.pl | 47 +++++++++++++++---- test_regress/t/t_var_pins_sc_uint_bool.pl | 43 +++++++++++++++++ .../t/t_var_pins_sc_uint_bool_nomain.pl | 30 ++++++++++++ 11 files changed, 129 insertions(+), 15 deletions(-) create mode 100755 test_regress/t/t_var_pins_sc_uint_bool.pl create mode 100755 test_regress/t/t_var_pins_sc_uint_bool_nomain.pl diff --git a/bin/verilator b/bin/verilator index 264f0d6c2..f9670ef8b 100755 --- a/bin/verilator +++ b/bin/verilator @@ -410,6 +410,7 @@ detailed descriptions of these arguments. --pins-inout-enables Specify that __en and __out signals be created for inouts --pins-sc-biguint Specify types for top-level ports --pins-sc-uint Specify types for top-level ports + --pins-sc-uint-bool Specify types for top-level ports --pins-uint8 Specify types for top-level ports --no-pins64 Don't use uint64_t's for 33-64 bit sigs --pipe-filter Filter all input through a script diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 237671b5b..52ed6946e 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -1004,6 +1004,10 @@ Summary: :vlopt:`--pins-sc-biguint` combination, it results in sc_uint being used between 2 and 64 and sc_biguint being used between 65 and 512. +.. option:: --pins-sc-uint-bool + + Specifies SystemC inputs/outputs one bit wide should use sc_uint<1>. + .. option:: --pins-sc-biguint Specifies SystemC inputs/outputs greater than 65 bits wide should use diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 98748dd80..b9e141a6b 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -2067,6 +2067,7 @@ public: bool isScQuad() const; bool isScBv() const; bool isScUint() const; + bool isScUintBool() const; bool isScBigUint() const; bool isScSensitive() const { return m_scSensitive; } bool isSigPublic() const; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 58fa93eed..ed2d23d99 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -380,6 +380,9 @@ bool AstVar::isScBv() const { bool AstVar::isScUint() const { return ((isSc() && v3Global.opt.pinsScUint() && width() >= 2 && width() <= 64) && !isScBv()); } +bool AstVar::isScUintBool() const { + return (isSc() && v3Global.opt.pinsScUintBool() && width() == 1); +} bool AstVar::isScBigUint() const { return ((isSc() && v3Global.opt.pinsScBigUint() && width() >= 65 && width() <= 512) && !isScBv()); @@ -671,7 +674,7 @@ string AstVar::scType() const { if (isScBigUint()) { return (string{"sc_dt::sc_biguint<"} + cvtToStr(widthMin()) + "> "); // Keep the space so don't get >> - } else if (isScUint()) { + } else if (isScUint() || isScUintBool()) { return (string{"sc_dt::sc_uint<"} + cvtToStr(widthMin()) + "> "); // Keep the space so don't get >> } else if (isScBv()) { diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index a825d210a..54355a473 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -192,10 +192,10 @@ public: } void emitScIQW(AstVar* nodep) { UASSERT_OBJ(nodep->isSc(), nodep, "emitting SystemC operator on non-SC variable"); - puts(nodep->isScBigUint() ? "SB" - : nodep->isScUint() ? "SU" - : nodep->isScBv() ? "SW" - : (nodep->isScQuad() ? "SQ" : "SI")); + puts(nodep->isScBigUint() ? "SB" + : (nodep->isScUint() || nodep->isScUintBool()) ? "SU" + : nodep->isScBv() ? "SW" + : (nodep->isScQuad() ? "SQ" : "SI")); } void emitDatap(AstNode* nodep) { // When passing to a function with va_args the compiler doesn't diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 3bfebebb5..19ba599f4 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -694,7 +694,7 @@ class EmitCTrace final : EmitCFunc { const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef); if (!varrefp) return false; AstVar* const varp = varrefp->varp(); - return varp->isSc() && varp->isScUint(); + return varp->isSc() && (varp->isScUint() || varp->isScUintBool()); } void emitTraceInitOne(AstTraceDecl* nodep, int enumNum) { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 9f86dac80..89875ee01 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1406,6 +1406,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, m_pinsScUint = flag; if (!m_pinsScBigUint) m_pinsBv = 65; }); + DECL_OPTION("-pins-sc-uint-bool", CbOnOff, [this](bool flag) { m_pinsScUintBool = flag; }); DECL_OPTION("-pins-sc-biguint", CbOnOff, [this](bool flag) { m_pinsScBigUint = flag; m_pinsBv = 513; diff --git a/src/V3Options.h b/src/V3Options.h index 386c6222c..a7b9f2268 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -260,6 +260,7 @@ private: bool m_pedantic = false; // main switch: --Wpedantic bool m_pinsInoutEnables = false;// main switch: --pins-inout-enables bool m_pinsScUint = false; // main switch: --pins-sc-uint + bool m_pinsScUintBool = false; // main switch: --pins-sc-uint-bool bool m_pinsScBigUint = false; // main switch: --pins-sc-biguint bool m_pinsUint8 = false; // main switch: --pins-uint8 bool m_ppComments = false; // main switch: --pp-comments @@ -514,6 +515,7 @@ public: bool pedantic() const { return m_pedantic; } bool pinsInoutEnables() const { return m_pinsInoutEnables; } bool pinsScUint() const { return m_pinsScUint; } + bool pinsScUintBool() const { return m_pinsScUintBool; } bool pinsScBigUint() const { return m_pinsScBigUint; } bool pinsUint8() const { return m_pinsUint8; } bool ppComments() const { return m_ppComments; } diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 74f1d4e58..363b8c18a 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -967,6 +967,10 @@ sub _compile_vlt_flags { my $checkflags = $self->_checkflags(%param); die "%Error: specify threads via 'threads =>' argument, not as a command line option" unless ($checkflags !~ /(^|\s)-?-threads\s/); $self->{coverage} = 1 if ($checkflags =~ /-coverage\b/); + my $driver_verilator_flags = ' '.join(' ', driver_verilator_flags()).' '; + $self->{pins_sc_uint_bool} = 1 if (($checkflags =~ /-pins-sc-uint-bool\b/) + || ($driver_verilator_flags =~ /-pins-sc-uint-bool\b/)); + $self->{savable} = 1 if ($checkflags =~ /-savable\b/); $self->{sc} = 1 if ($checkflags =~ /-sc\b/); $self->{timing} = 1 if ($checkflags =~ / -?-timing\b/ || $checkflags =~ / -?-binary\b/ ); @@ -1963,8 +1967,13 @@ sub _make_main { if ($self->sc) { print $fh "extern int sc_main(int argc, char** argv);\n"; print $fh "int sc_main(int argc, char** argv) {\n"; - print $fh " sc_signal fastclk;\n" if $self->{inputs}{fastclk}; - print $fh " sc_signal clk;\n" if $self->{inputs}{clk}; + if ($self->{pins_sc_uint_bool}) { + print $fh " sc_signal> fastclk;\n" if $self->{inputs}{fastclk}; + print $fh " sc_signal> clk;\n" if $self->{inputs}{clk}; + } else { + print $fh " sc_signal fastclk;\n" if $self->{inputs}{fastclk}; + print $fh " sc_signal clk;\n" if $self->{inputs}{clk}; + } print $fh " sc_set_time_resolution(1, $Self->{sc_time_resolution});\n"; print $fh " sc_time sim_time($self->{sim_time}, $Self->{sc_time_resolution});\n"; } else { @@ -2059,7 +2068,11 @@ sub _make_main { print $fh " topp->nextTimeSlot() / MAIN_TIME_MULTIPLIER <= cycles) {\n"; print $fh " new_time = topp->nextTimeSlot();\n"; print $fh " } else {\n"; - print $fh " ${set}clk = !${set}clk;\n"; + if ($self->{pins_sc_uint_bool}) { + print $fh " ${set}clk.write(!${set}clk.read());\n"; + } else { + print $fh " ${set}clk = !${set}clk;\n"; + } print $fh " }\n"; print $fh " contextp->time(new_time);\n"; } else { @@ -2070,11 +2083,19 @@ sub _make_main { for (my $i = 0; $i < 5; $i++) { my $action = 0; if ($self->{inputs}{fastclk}) { - print $fh " ${set}fastclk = !${set}fastclk;\n"; + if ($self->{pins_sc_uint_bool}) { + print $fh " ${set}fastclk.write(!${set}fastclk.read());\n"; + } else { + print $fh " ${set}fastclk = !${set}fastclk;\n"; + } $action = 1; } if ($i == 0 && $self->{inputs}{clk}) { - print $fh " ${set}clk = !${set}clk;\n"; + if ($self->{pins_sc_uint_bool}) { + print $fh " ${set}clk.write(!${set}clk.read());\n"; + } else { + print $fh " ${set}clk = !${set}clk;\n"; + } $action = 1; } if ($self->{savable}) { @@ -2206,10 +2227,18 @@ sub _make_top_v { print $fh " fastclk = 1;\n" if $self->{inputs}{fastclk}; print $fh " clk = 1;\n" if $self->{inputs}{clk}; print $fh " while (\$time < $self->{sim_time}) begin\n"; - for (my $i = 0; $i < 5; $i++) { - print $fh " #1;\n"; - print $fh " fastclk = !fastclk;\n" if $self->{inputs}{fastclk}; - print $fh " clk = !clk;\n" if $i == 4 && $self->{inputs}{clk}; + if ($self->{pins_sc_uint_bool}) { + for (my $i = 0; $i < 5; $i++) { + print $fh " #1;\n"; + print $fh " fastclk.write(!fastclk.read());\n" if $self->{inputs}{fastclk}; + print $fh " clk.write(!clk.read());\n" if $i == 4 && $self->{inputs}{clk}; + } + } else { + for (my $i = 0; $i < 5; $i++) { + print $fh " #1;\n"; + print $fh " fastclk = !fastclk;\n" if $self->{inputs}{fastclk}; + print $fh " clk = !clk;\n" if $i == 4 && $self->{inputs}{clk}; + } } print $fh " end\n"; print $fh " end\n"; diff --git a/test_regress/t/t_var_pins_sc_uint_bool.pl b/test_regress/t/t_var_pins_sc_uint_bool.pl new file mode 100755 index 000000000..05a4dd4d3 --- /dev/null +++ b/test_regress/t/t_var_pins_sc_uint_bool.pl @@ -0,0 +1,43 @@ +#!/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 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(vlt => 1); + +top_filename("t/t_var_pinsizes.v"); + +compile( + verilator_flags2 => ["-sc --pins-sc-uint-bool --trace --exe $Self->{t_dir}/t_var_pinsizes.cpp"], + make_main => 0, + ); + +{ + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in\s> \s+ &i1;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in \s+ &i8;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in \s+ &i16;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in \s+ &i32;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in \s+ &i64;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in\s> \s+ &i65;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in\s> \s+ &i128;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_in\s> \s+ &i513;/x); + + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out\s> \s+ &o1;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out \s+ &o8;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out \s+ &o16;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out \s+ &o32;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out \s+ &o64;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out\s> \s+ &o65;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out\s> \s+ &o128;/x); + file_grep("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/sc_core::sc_out\s> \s+ &o513;/x); +} + +execute(); + +ok(1); +1; diff --git a/test_regress/t/t_var_pins_sc_uint_bool_nomain.pl b/test_regress/t/t_var_pins_sc_uint_bool_nomain.pl new file mode 100755 index 000000000..6b27f802f --- /dev/null +++ b/test_regress/t/t_var_pins_sc_uint_bool_nomain.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 2024 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 + +# This test runs the very first time we've executed Verilator --sc +# after building so we make sure to run with --gdbbt, so if it dumps we'll +# get a trace. + +scenarios(simulator => 1); + +top_filename("t/t_a1_first_cc.v"); + +$DEBUG_QUIET = "--debug --debugi 0 --gdbbt --no-dump-tree"; + +compile( + verilator_flags2 => [$DEBUG_QUIET, "-sc --trace --pins-sc-uint-bool"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1;