From 748fa4cb8039971a2d5dc472923141846b8a3e87 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 10 Dec 2021 23:08:03 -0500 Subject: [PATCH] Fix coredump after huge enum warning. --- src/V3Width.cpp | 14 ++++---- test_regress/t/t_enum_huge_methods_bad.out | 9 +++++ test_regress/t/t_enum_huge_methods_bad.pl | 19 +++++++++++ test_regress/t/t_enum_huge_methods_bad.v | 39 ++++++++++++++++++++++ 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 test_regress/t/t_enum_huge_methods_bad.out create mode 100755 test_regress/t/t_enum_huge_methods_bad.pl create mode 100644 test_regress/t/t_enum_huge_methods_bad.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index d8ab99fce..27197839d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -216,6 +216,8 @@ private: std::map m_queueDTypeIndexed; // Queues with given index type + static constexpr int ENUM_LOOKUP_BITS = 16; // Maximum # bits to make enum lookup table + // ENUMS enum ExtendRule : uint8_t { EXTEND_EXP, // Extend if expect sign and node signed, e.g. node=y in ADD(x,y), "x + y" @@ -5910,10 +5912,10 @@ private: UASSERT_OBJ(vconstp, errNodep, "Enum item without constified value"); if (vconstp->toUQuad() >= maxval) maxval = vconstp->toUQuad(); } - if (adtypep->itemsp()->width() > 64 || maxval >= (1 << 16)) { + if (adtypep->itemsp()->width() > 64 || maxval >= (1 << ENUM_LOOKUP_BITS)) { errNodep->v3warn(E_UNSUPPORTED, "Unsupported: enum next/prev method on enum with > 10 bits"); - return 0; + return ENUM_LOOKUP_BITS; } return maxval; } @@ -5962,9 +5964,7 @@ private: // Find valid values and populate UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items"); - std::vector values; - values.resize(msbdim + 1); - for (unsigned i = 0; i < (msbdim + 1); ++i) values[i] = nullptr; + std::map values; { AstEnumItem* const firstp = nodep->itemsp(); const AstEnumItem* prevp = firstp; // Prev must start with last item @@ -5973,7 +5973,7 @@ private: AstEnumItem* const nextp = VN_AS(itemp->nextp(), EnumItem); const AstConst* const vconstp = VN_AS(itemp->valuep(), Const); UASSERT_OBJ(vconstp, nodep, "Enum item without constified value"); - const uint32_t i = vconstp->toUInt(); + const vluint64_t i = vconstp->toUQuad(); if (attrType == AstAttrType::ENUM_NAME) { values[i] = new AstConst(nodep->fileline(), AstConst::String(), itemp->name()); } else if (attrType == AstAttrType::ENUM_NEXT) { @@ -5990,7 +5990,7 @@ private: } } // Add all specified values to table - for (unsigned i = 0; i < (msbdim + 1); ++i) { + for (vluint64_t i = 0; i < (msbdim + 1); ++i) { if (values[i]) initp->addIndexValuep(i, values[i]); } userIterate(varp, nullptr); // May have already done $unit so must do this var diff --git a/test_regress/t/t_enum_huge_methods_bad.out b/test_regress/t/t_enum_huge_methods_bad.out new file mode 100644 index 000000000..cee01c470 --- /dev/null +++ b/test_regress/t/t_enum_huge_methods_bad.out @@ -0,0 +1,9 @@ +%Error: t/t_enum_huge_methods_bad.v:15:11: Value too wide for 64-bits expected in this context 160'h12344567abcd12344567abcd + 15 | ELARGE = 160'h1234_4567_abcd_1234_4567_abcd + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +%Error-UNSUPPORTED: t/t_enum_huge_methods_bad.v:30:14: Unsupported: enum next/prev method on enum with > 10 bits + : ... In instance t + 30 | $display(e.name); + | ^~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_enum_huge_methods_bad.pl b/test_regress/t/t_enum_huge_methods_bad.pl new file mode 100755 index 000000000..b5861b2ab --- /dev/null +++ b/test_regress/t/t_enum_huge_methods_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2008 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); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_enum_huge_methods_bad.v b/test_regress/t/t_enum_huge_methods_bad.v new file mode 100644 index 000000000..8502a98c0 --- /dev/null +++ b/test_regress/t/t_enum_huge_methods_bad.v @@ -0,0 +1,39 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2014 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + typedef enum logic [159:0] { + E01 = 160'h1, + ELARGE = 160'h1234_4567_abcd_1234_4567_abcd + } my_t; + + my_t e; + + int cyc; + + // Check runtime + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc==0) begin + // Setup + e <= E01; + end + else if (cyc==1) begin + $display(e.name); + e <= ELARGE; + end + else if (cyc==99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule