From ce879122bbecf78429938a0d0ecc9dec5674a01a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 17 May 2017 20:15:40 -0400 Subject: [PATCH] Fix --assert with complex case statements, bug1164. --- Changes | 2 + src/V3Assert.cpp | 18 ++------ src/V3AstNodes.cpp | 7 +++ src/V3AstNodes.h | 1 + test_regress/t/t_assert_question.pl | 19 ++++++++ test_regress/t/t_assert_question.v | 33 +++++++++++++ test_regress/t/t_mem_banks.pl | 18 ++++++++ test_regress/t/t_mem_banks.v | 72 +++++++++++++++++++++++++++++ 8 files changed, 156 insertions(+), 14 deletions(-) create mode 100755 test_regress/t/t_assert_question.pl create mode 100644 test_regress/t/t_assert_question.v create mode 100755 test_regress/t/t_mem_banks.pl create mode 100644 test_regress/t/t_mem_banks.v diff --git a/Changes b/Changes index e57f4970d..c15547d85 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson] +**** Fix --assert with complex case statements, bug1164. [Enzo Chi] + * Verilator 3.902 2017-04-02 diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 05d0b7e35..308034079 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -246,20 +246,10 @@ private: for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { AstNode* onep; - AstConst* iconstp = icondp->castConst(); - if (iconstp && iconstp->num().isFourState() - && (nodep->casex() || nodep->casez() || nodep->caseInside())) { - V3Number nummask (itemp->fileline(), iconstp->width()); - nummask.opBitsNonX(iconstp->num()); - V3Number numval (itemp->fileline(), iconstp->width()); - numval.opBitsOne(iconstp->num()); - AstNode* and1p = new AstAnd(itemp->fileline(), nodep->exprp()->cloneTree(false), - new AstConst(itemp->fileline(), nummask)); - AstNode* and2p = new AstAnd(itemp->fileline(), - new AstConst(itemp->fileline(), numval), - new AstConst(itemp->fileline(), nummask)); - onep = AstEq::newTyped(itemp->fileline(), and1p, and2p); - + if (nodep->casex() || nodep->casez() || nodep->caseInside()) { + onep = AstEqWild::newTyped(itemp->fileline(), + nodep->exprp()->cloneTree(false), + icondp->cloneTree(false)); } else { onep = AstEq::newTyped(icondp->fileline(), nodep->exprp()->cloneTree(false), diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 428b248c4..8eb69c210 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -140,6 +140,13 @@ AstNodeBiop* AstLte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) { } } +AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) { + if (lhsp->isDouble() && rhsp->isDouble()) { + return new AstEqD(fl, lhsp, rhsp); + } else { + return new AstEqWild(fl, lhsp, rhsp); + } +} bool AstVar::isSigPublic() const { return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar())); diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index b8d688a28..1404072f2 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -4673,6 +4673,7 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(EqWild) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEqWild/AstEqD virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); } virtual string emitVerilog() { return "%k(%l %f==? %r)"; } virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } diff --git a/test_regress/t/t_assert_question.pl b/test_regress/t/t_assert_question.pl new file mode 100755 index 000000000..b57b2dea8 --- /dev/null +++ b/test_regress/t/t_assert_question.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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 => ['--assert'], + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_assert_question.v b/test_regress/t/t_assert_question.v new file mode 100644 index 000000000..abd4efa9c --- /dev/null +++ b/test_regress/t/t_assert_question.v @@ -0,0 +1,33 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2016 by Wilson Snyder + +module t (/*AUTOARG*/ + // Outputs + dout, + // Inputs + clk, sel, a, c + ); + + input clk; + input bit [3:0] sel; + input bit [3:0] a; + input bit c; + output bit dout; + + localparam logic DC = 1'b?; + + always_ff @(posedge clk) begin + unique casez(sel) + 4'b0000: dout <= a[0]; + 4'b001?: dout <= a[1]; + {1'b0, 1'b1, 1'b?, 1'b?}: dout <= a[2]; + {1'b1, 1'b?, 1'b?, DC}: dout <= a[3]; + default: dout <= '0; + endcase + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_mem_banks.pl b/test_regress/t/t_mem_banks.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_mem_banks.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_mem_banks.v b/test_regress/t/t_mem_banks.v new file mode 100644 index 000000000..27eb6955e --- /dev/null +++ b/test_regress/t/t_mem_banks.v @@ -0,0 +1,72 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2017 by Wilson Snyder. + +module t (/*AUTOARG*/); + + reg [5:0] addr; + + parameter BANKS = 6; + parameter ROWS = 8; + + wire [2:0] bank; + wire [2:0] row; + + integer a; + integer used[BANKS][ROWS]; + + // Test loop + initial begin + for (a = 0; a < BANKS*ROWS; ++a) begin + addr[5:0] = a[5:0]; + hash (addr, bank, row); + used [bank][row] ++; + if (used [bank][row] > 1) begin + $write ("Error: Hash failed addr=%x bank=%x row=%x\n", addr, bank, row); + end + end + $write("*-* All Finished *-*\n"); + $finish; + end + + task hash (input [5:0] addr, + output [2:0] bank, + output [2:0] row); + + reg [1:0] third; + reg [1:0] fourth; + + third = {addr[5], addr[4]}; + fourth = {addr[3] ^ addr[1], + addr[2] ^ addr[0]}; + + case (third) + 2'h0: + case (fourth) + 2'h0: begin bank = 3'h0; row = {1'h0, addr[1:0]}; end + 2'h1: begin bank = 3'h1; row = {1'h0, addr[1:0]}; end + 2'h2: begin bank = 3'h2; row = {1'h0, addr[1:0]}; end + 2'h3: begin bank = 3'h3; row = {1'h0, addr[1:0]}; end + endcase + + 2'h1: + case (fourth) + 2'h0: begin bank = 3'h0; row = {1'h1, addr[1:0]}; end + 2'h1: begin bank = 3'h1; row = {1'h1, addr[1:0]}; end + 2'h2: begin bank = 3'h4; row = {1'h0, addr[1:0]}; end + 2'h3: begin bank = 3'h5; row = {1'h0, addr[1:0]}; end + endcase + + 2'h2: + case (fourth) + 2'h0: begin bank = 3'h2; row = {1'h1, addr[1:0]}; end + 2'h1: begin bank = 3'h3; row = {1'h1, addr[1:0]}; end + 2'h2: begin bank = 3'h4; row = {1'h1, addr[1:0]}; end + 2'h3: begin bank = 3'h5; row = {1'h1, addr[1:0]}; end + endcase + + 2'h3: $stop; + endcase + endtask +endmodule