From bf972963f4473a9fb059032426a00157d75b6b4b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 1 Jan 2022 22:14:46 -0500 Subject: [PATCH] Misc internal and test work towards enum type checks (#726). --- src/V3Ast.h | 2 +- src/V3Width.cpp | 20 +++++++++++---- test_regress/t/t_enum_huge_methods.v | 2 +- test_regress/t/t_enum_large_methods.v | 2 +- test_regress/t/t_enum_type_bad.pl | 18 +++++++++++++ test_regress/t/t_enum_type_bad.v | 37 +++++++++++++++++++++++++++ test_regress/t/t_trace_complex.v | 6 ++--- 7 files changed, 76 insertions(+), 11 deletions(-) create mode 100755 test_regress/t/t_enum_type_bad.pl create mode 100644 test_regress/t/t_enum_type_bad.v diff --git a/src/V3Ast.h b/src/V3Ast.h index f8d826ccc..11097f8b7 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1699,7 +1699,7 @@ public: editCountInc(); } } - void dtypeFrom(AstNode* fromp) { + void dtypeFrom(const AstNode* fromp) { if (fromp) dtypep(fromp->dtypep()); } void dtypeChgSigned(bool flag = true); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 451786cbb..29396ed1c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -101,9 +101,17 @@ std::ostream& operator<<(std::ostream& str, const Determ& rhs) { return str << s_det[rhs]; } -enum Castable : uint8_t { UNSUPPORTED, COMPATIBLE, DYNAMIC_ENUM, DYNAMIC_CLASS, INCOMPATIBLE }; +enum Castable : uint8_t { + UNSUPPORTED, + COMPATIBLE, + ENUM_EXPLICIT, + ENUM_IMPLICIT, + DYNAMIC_CLASS, + INCOMPATIBLE +}; std::ostream& operator<<(std::ostream& str, const Castable& rhs) { - static const char* const s_det[] = {"UNSUP", "COMPAT", "DYN_ENUM", "DYN_CLS", "INCOMPAT"}; + static const char* const s_det[] + = {"UNSUP", "COMPAT", "ENUM_EXP", "ENUM_IMP", "DYN_CLS", "INCOMPAT"}; return str << s_det[rhs]; } @@ -1665,7 +1673,7 @@ private: if (castable == DYNAMIC_CLASS) { // Keep in place, will compute at runtime return; - } else if (castable == DYNAMIC_ENUM) { + } else if (castable == ENUM_EXPLICIT || castable == ENUM_IMPLICIT) { // TODO is from is a constant we could simplify, though normal constant // elimination should do much the same // Form: "( ((v > size) ? false : enum_valid[v[N:0]]) @@ -1760,7 +1768,8 @@ private: << toDtp->prettyDTypeNameQ() << " from " << fromDtp->prettyDTypeNameQ()); bad = true; - } else if (castable == COMPATIBLE || castable == DYNAMIC_ENUM) { + } else if (castable == COMPATIBLE || castable == ENUM_IMPLICIT + || castable == ENUM_EXPLICIT) { ; // Continue } else if (castable == DYNAMIC_CLASS) { nodep->v3error("Dynamic, not static cast, required to cast " @@ -6277,7 +6286,8 @@ private: if (VN_IS(toDtp, BasicDType) || VN_IS(toDtp, NodeUOrStructDType)) { if (fromNumericable) return COMPATIBLE; } else if (VN_IS(toDtp, EnumDType)) { - if (fromNumericable) return DYNAMIC_ENUM; + if (VN_IS(fromBaseDtp, EnumDType) && toDtp->sameTree(fromDtp)) return ENUM_IMPLICIT; + if (fromNumericable) return ENUM_EXPLICIT; } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromConstp, Const)) { if (VN_IS(fromConstp, Const) && VN_AS(fromConstp, Const)->num().isNull()) return COMPATIBLE; diff --git a/test_regress/t/t_enum_huge_methods.v b/test_regress/t/t_enum_huge_methods.v index 499af6fde..3fd9eb1d6 100644 --- a/test_regress/t/t_enum_huge_methods.v +++ b/test_regress/t/t_enum_huge_methods.v @@ -59,7 +59,7 @@ module t (/*AUTOARG*/ end // else if (cyc == 20) begin - e <= 'h11; // Unknown + e <= my_t'('h11); // Unknown end else if (cyc == 21) begin `checks(e.name, ""); // Unknown diff --git a/test_regress/t/t_enum_large_methods.v b/test_regress/t/t_enum_large_methods.v index 136f5f5cc..84255f66e 100644 --- a/test_regress/t/t_enum_large_methods.v +++ b/test_regress/t/t_enum_large_methods.v @@ -42,7 +42,7 @@ module t (/*AUTOARG*/ e <= E01; end else if (cyc==20) begin - e <= 'h11; // Unknown + e <= my_t'('h11); // Unknown end else if (cyc==21) begin `checks(e.name, ""); // Unknown diff --git a/test_regress/t/t_enum_type_bad.pl b/test_regress/t/t_enum_type_bad.pl new file mode 100755 index 000000000..aa2cd3195 --- /dev/null +++ b/test_regress/t/t_enum_type_bad.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 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 => 0, # But should fail + ); + +ok(1); +1; diff --git a/test_regress/t/t_enum_type_bad.v b/test_regress/t/t_enum_type_bad.v new file mode 100644 index 000000000..84608dbe5 --- /dev/null +++ b/test_regress/t/t_enum_type_bad.v @@ -0,0 +1,37 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + + typedef enum {ZERO, ONE, TWO} e_t; + + typedef enum {THREE=3, FOUR, FIVE} o_t; + + typedef struct packed { + e_t m_e; + o_t m_o; + } struct_t; + + initial begin + e_t e; + o_t o; + struct_t str; + + e = ONE; + e = e_t'(1); + e = e; + + e = 1; // Bad + o = e; // Bad + + str.m_e = ONE; + str.m_o = THREE; + e = str.m_e; + o = str.m_o; + o = str.m_e; // Bad + + end +endmodule diff --git a/test_regress/t/t_trace_complex.v b/test_regress/t/t_trace_complex.v index 9572e92dc..313440c33 100644 --- a/test_regress/t/t_trace_complex.v +++ b/test_regress/t/t_trace_complex.v @@ -92,9 +92,9 @@ module t (clk); v_string <= cyc[0] ? "foo" : "bar"; v_arr_real[0] <= v_arr_real[0] + 0.2; v_arr_real[1] <= v_arr_real[1] + 0.3; - v_enumed <= v_enumed + 1; - v_enumed2 <= v_enumed2 + 2; - v_enumb <= v_enumb - 1; + v_enumed <= enumed_t'(v_enumed + 1); + v_enumed2 <= enumed_t'(v_enumed2 + 2); + v_enumb <= enumb_t'(v_enumb - 3'd1); v_enumb2_str <= {v_enumb, v_enumb}; for (integer b=3; b<=4; b++) begin v_arru[b] <= ~v_arru[b];