diff --git a/Changes b/Changes index 0d1802b68..d2e483fce 100644 --- a/Changes +++ b/Changes @@ -36,6 +36,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix --savable invalid C++ on packed arrays, bug1465. [Alex Chadwick] +**** Fix constant function return of function var, bug1467. [Roman Popov] + * Verilator 4.014 2019-05-08 diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 4448775d1..713431381 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -1658,13 +1658,17 @@ V3Number& V3Number::opBufIf1(const V3Number& ens, const V3Number& if1s) { } V3Number& V3Number::opAssign(const V3Number& lhs) { - // Note may be a width change during the assign - setZero(); - if (isString()) { - m_stringVal = lhs.m_stringVal; - } else { - for (int bit=0; bitwidth(); bit++) { - setBit(bit, lhs.bitIs(bit)); + // Note may be a width change during the assign. + // Special case: opAssign unlike other ops, allows this an assignment + // to itself; V3Simulate does this when hits "foo=foo;" + if (this != &lhs) { + setZero(); + if (isString()) { + m_stringVal = lhs.m_stringVal; + } else { + for (int bit=0; bitwidth(); bit++) { + setBit(bit, lhs.bitIs(bit)); + } } } return *this; diff --git a/test_regress/t/t_gen_self_return.pl b/test_regress/t/t_gen_self_return.pl new file mode 100755 index 000000000..6b3b15be5 --- /dev/null +++ b/test_regress/t/t_gen_self_return.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 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. + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_gen_self_return.v b/test_regress/t/t_gen_self_return.v new file mode 100644 index 000000000..9af9d9e12 --- /dev/null +++ b/test_regress/t/t_gen_self_return.v @@ -0,0 +1,54 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Roman Popov. + +module dut + #( + parameter DEPTH = 16, + parameter WIDTH = 32, + parameter RAM_SPLIT_WIDTH = 16 + ) + ( + output logic [WIDTH-1:0] ram_dataout + ); + + localparam RAM_ADDR_WIDTH = $clog2(DEPTH); // = 4 + localparam NUM_RAM_BLOCKS = (WIDTH/RAM_SPLIT_WIDTH) + {31'h0, ((WIDTH % RAM_SPLIT_WIDTH) > 0)}; // = 2 + typedef logic [NUM_RAM_BLOCKS:0][31:0] block_index_t; // width 96 + + function automatic block_index_t index_calc(input int WIDTH, NUM_RAM_BLOCKS); + index_calc[0] = '0; + for(int i = 0; i < NUM_RAM_BLOCKS; i++) index_calc[i+1] = WIDTH/NUM_RAM_BLOCKS + {31'h0, (i < (WIDTH%NUM_RAM_BLOCKS))}; + for(int i = 0; i < NUM_RAM_BLOCKS; i++) index_calc[i+1] = index_calc[i+1] + index_calc[i]; + // bug1467 was this return + return index_calc; + endfunction + + localparam block_index_t RAM_BLOCK_INDEX = index_calc(WIDTH, NUM_RAM_BLOCKS); + + generate + begin : ram_dataout_gen + for (genvar i = 0; i < NUM_RAM_BLOCKS; i++) begin + always_comb ram_dataout[RAM_BLOCK_INDEX[i+1]-1:RAM_BLOCK_INDEX[i]] = 0; + end + end + endgenerate + + initial begin + if (RAM_BLOCK_INDEX != {32'd32, 32'd16, 32'd0}) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule + +module t + ( + input clk, + output logic [31:0] ram_dataout + ); + + dut dut0(.*); + +endmodule