From 4f6d80c6022c2258abf0cb1a05f661029d5a51ab Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 28 Oct 2013 20:41:05 -0400 Subject: [PATCH] Add UNPACKED warning to convert unpacked structs. --- Changes | 2 ++ bin/verilator | 7 +++++++ src/V3Ast.h | 1 + src/V3Changed.cpp | 2 +- src/V3Error.h | 3 ++- src/V3Width.cpp | 4 +++- src/V3WidthSel.cpp | 2 +- test_regress/t/t_struct_unpacked.pl | 18 +++++++++++++++++ test_regress/t/t_struct_unpacked.v | 26 +++++++++++++++++++++++++ test_regress/t/t_struct_unpacked_bad.pl | 3 ++- test_regress/t/t_struct_unpacked_bad.v | 10 +++++++++- 11 files changed, 72 insertions(+), 6 deletions(-) create mode 100755 test_regress/t/t_struct_unpacked.pl create mode 100644 test_regress/t/t_struct_unpacked.v diff --git a/Changes b/Changes index 89af2fa73..ca279eb48 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.854 devel +*** Add UNPACKED warning to convert unpacked structs. [Jeremy Bennett] + **** Support vpi_get of vpiSuppressVal, bug687. [Varun Koyyalagunta] **** Support vpi_get_time, bug688. [Varun Koyyalagunta] diff --git a/bin/verilator b/bin/verilator index 5b49ad5ad..0b57e3f93 100755 --- a/bin/verilator +++ b/bin/verilator @@ -3225,6 +3225,13 @@ section for more details. Ignoring this warning will only slow simulations, it will simulate correctly. +=item UNPACKED + +Warns that unpacked structs and unions are not supported. + +Ignoring this warning will make Verilator treat the structure as packed, +which may make Verilator simulations differ from other simulators. + =item UNSIGNED Warns that you are comparing a unsigned value in a way that implies it is diff --git a/src/V3Ast.h b/src/V3Ast.h index 24e9d0a7f..bd6d47d61 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1597,6 +1597,7 @@ public: AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list void addMembersp(AstNode* nodep) { addNOp1p(nodep); } bool packed() const { return m_packed; } + bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs void clearCache() { m_members.clear(); } void repairMemberCache(); AstMemberDType* findMember(const string& name) const { diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index b9483f1d6..525f9d505 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -89,7 +89,7 @@ private: AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType(); AstStructDType *structp = varp->dtypeSkipRefp()->castStructDType(); bool isArray = arrayp; - bool isStruct = structp && structp->packed(); + bool isStruct = structp && structp->packedUnsup(); int elements = isArray ? arrayp->elementsConst() : 1; if (isArray && (elements > DETECTARRAY_MAX_INDEXES)) { vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5," NODECLASS "<=9) nodep->dumpTree("-class-in--"); - if (!nodep->packed()) nodep->v3error("Unsupported: Unpacked struct/union"); + if (!nodep->packed()) { + nodep->v3warn(UNPACKED, "Unsupported: Unpacked struct/union"); + } nodep->iterateChildren(*this); // First size all members nodep->repairMemberCache(); // Determine bit assignments and width diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 3626aa464..4f5357f64 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -389,7 +389,7 @@ private: VNumRange fromRange = fromdata.m_fromRange; if (ddtypep->castBasicDType() || (ddtypep->castNodeClassDType() - && ddtypep->castNodeClassDType()->packed())) { + && ddtypep->castNodeClassDType()->packedUnsup())) { AstSel* newp = NULL; if (nodep->castSelPlus()) { if (fromRange.littleEndian()) { diff --git a/test_regress/t/t_struct_unpacked.pl b/test_regress/t/t_struct_unpacked.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_struct_unpacked.pl @@ -0,0 +1,18 @@ +#!/usr/bin/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. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_struct_unpacked.v b/test_regress/t/t_struct_unpacked.v new file mode 100644 index 000000000..92d759653 --- /dev/null +++ b/test_regress/t/t_struct_unpacked.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2009 by Wilson Snyder. + +module x; + + // verilator lint_off UNPACKED + typedef struct { + int a; + } notpacked_t; + // verilator lint_on UNPACKED + + typedef struct packed { + notpacked_t b; + } ispacked_t; + + ispacked_t p; + + initial begin + p.b = 1; + if (p.b != 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_struct_unpacked_bad.pl b/test_regress/t/t_struct_unpacked_bad.pl index b58b030b5..095c3500c 100755 --- a/test_regress/t/t_struct_unpacked_bad.pl +++ b/test_regress/t/t_struct_unpacked_bad.pl @@ -10,7 +10,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di compile ( fails=>$Self->{v3}, expect=> -q{%Error: t/t_struct_unpacked_bad.v:8: Unsupported: Unpacked struct/union +q{%Warning-UNPACKED: t/t_struct_unpacked_bad.v:\d+: Unsupported: Unpacked struct/union +%Warning-UNPACKED: Use .* .*%Error: Exiting due to.*}, ); diff --git a/test_regress/t/t_struct_unpacked_bad.v b/test_regress/t/t_struct_unpacked_bad.v index d5030de2e..c726c13d2 100644 --- a/test_regress/t/t_struct_unpacked_bad.v +++ b/test_regress/t/t_struct_unpacked_bad.v @@ -10,7 +10,15 @@ module x; } notpacked_t; typedef struct packed { - notpacked_t a; + notpacked_t b; } ispacked_t; + ispacked_t p; + + initial begin + p.b = 1; + if (p.b != 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end endmodule