From 6715cb988001917ec341413f7ea133bc04a94fd4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 20 Mar 2010 21:29:16 -0400 Subject: [PATCH] Improve error handling on slices of arrays, bug226. --- Changes | 2 ++ src/V3Slice.cpp | 21 +++++++++++++++--- test_regress/t/t_mem_packed_bad.pl | 22 +++++++++++++++++++ test_regress/t/t_mem_packed_bad.v | 34 ++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100755 test_regress/t/t_mem_packed_bad.pl create mode 100644 test_regress/t/t_mem_packed_bad.v diff --git a/Changes b/Changes index 48dbcd9fd..6af2a885e 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix "make install" with configure outside srcdir. [Stefan Wallentowitz] +**** Improve error handling on slices of arrays, bug226. [by Bryon Bradley] + * Verilator 3.801 2010/03/17 *** Support "break", "continue", "return". diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index ebc482215..3363b040b 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -151,6 +151,7 @@ class SliceVisitor : public AstNVisitor { AstNode* m_assignp; // Assignment we are under AstNodeVarRef* m_lhsVarRefp; // Var on the LHS bool m_extend; // We have found an extend node + bool m_assignError; // True if the current assign already has an error // METHODS static int debug() { @@ -239,8 +240,18 @@ class SliceVisitor : public AstNVisitor { virtual void visit(AstExtend* nodep, AstNUser*) { m_extend = true; - if (m_assignp && m_assignp->user2() > 1) { + if (m_assignp && m_assignp->user2() > 1 && !m_assignError) { m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions"); + m_assignError = true; + } + nodep->iterateChildren(*this); + } + + virtual void visit(AstConst* nodep, AstNUser*) { + m_extend = true; + if (m_assignp && m_assignp->user2() > 1 && !m_assignError) { + m_assignp->v3error("Unsupported: Assignment between a constant and an array slice"); + m_assignError = true; } nodep->iterateChildren(*this); } @@ -258,13 +269,15 @@ class SliceVisitor : public AstNVisitor { int clones = countClones(nodep); if (m_assignp->user2() > 0 && m_assignp->user2() != clones) { m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions"); - } else if (m_assignp->user2() == 0) { + } else if (m_assignp->user2() == 0 && !m_assignError) { if (m_extend && clones > 1) { m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions"); + m_assignError = true; } if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp() && !m_assignp->castAssignDly()) { // LHS Var != RHS Var for a non-delayed assignment m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides"); + m_assignError = true; } m_assignp->user2(clones); } @@ -272,8 +285,9 @@ class SliceVisitor : public AstNVisitor { virtual void visit(AstSel* nodep, AstNUser*) { m_extend = true; - if (m_assignp && m_assignp->user2() > 1) { + if (m_assignp && m_assignp->user2() > 1 && !m_assignError) { m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions"); + m_assignError = true; } nodep->iterateChildren(*this); } @@ -314,6 +328,7 @@ class SliceVisitor : public AstNVisitor { void findImplicit(AstNodeAssign* nodep) { if (m_assignp) nodep->v3fatalSrc("Found a NodeAssign under another NodeAssign"); m_assignp = nodep; + m_assignError = false; m_extend = false; nodep->user1(true); // Record the LHS Var so we can check if the Var on the RHS is the same diff --git a/test_regress/t/t_mem_packed_bad.pl b/test_regress/t/t_mem_packed_bad.pl new file mode 100755 index 000000000..024aedf5d --- /dev/null +++ b/test_regress/t/t_mem_packed_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2010 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 ( + verilator_flags2 => ["--lint-only"], + fails=>1, + expect=> +'%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions +%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions +%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions +%Error: t/t_mem_packed_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions +%Error: Exiting due to.*', + ) if $Self->{v3}; + +ok(1); +1; diff --git a/test_regress/t/t_mem_packed_bad.v b/test_regress/t/t_mem_packed_bad.v new file mode 100644 index 000000000..d52bf76eb --- /dev/null +++ b/test_regress/t/t_mem_packed_bad.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2010 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + integer cyc; initial cyc = 0; + + logic [1:0][27:0] ch01; + logic [1:0][27:0] ch02; + logic [1:0][27:0] ch03; + logic [27:0] ch04[1:0]; + + /* verilator lint_off WIDTH */ + always @ (posedge clk) begin + // LHS is a 2D packed array, RHS is 1D packed or Const. Unsupported. + ch01 <= {{2{28'd4}}}; + ch02 <= {{2{cyc}}}; + ch03 <= 56'd0; + // LHS is 1D packed, 1D unpacked, this should never work. + ch04 <= 56'd0; + $display("ch01: %0x %0x", ch01[0], ch01[1]); + $display("ch01: %0x %0x", ch02[0], ch02[1]); + $display("ch01: %0x %0x", ch03[0], ch03[1]); + $display("ch01: %0x %0x", ch04[0], ch04[1]); + end + /* verilator lint_on WIDTH */ + +endmodule