From 3069860fdf0ca05ee95deecdbf7be1a560c6e3ec Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sun, 22 Jan 2023 10:43:16 +0000 Subject: [PATCH] Allow mismatched widths in operands of shifts in DFG Fixes #3872. Testing this is a bit tricky, as the front-end fixes up the operand widths in shifts to match, and we need V3Const to introduce a mismatched one by reducing `4'd2 ** x` (with x being 2 2-bit wide signal) to `4'd1 << x`, but t_dfg_peephole runs with V3Const disabled exactly because it makes it hard to write tests. Rather than fixing this one case in V3Const (which we should do systematically at some point), I fixed DFG to accept these just in case V3Const generates more of them. The assertions were there only because of paranoia (as I thought these were not possible inputs), the code otherwise works. --- src/V3DfgPeephole.cpp | 9 --------- test_regress/t/t_dfg_3872.pl | 16 ++++++++++++++++ test_regress/t/t_dfg_3872.v | 12 ++++++++++++ test_regress/t/t_dfg_peephole.cpp | 3 +++ test_regress/t/t_dfg_peephole.v | 13 ++++++++++++- 5 files changed, 43 insertions(+), 10 deletions(-) create mode 100755 test_regress/t/t_dfg_3872.pl create mode 100644 test_regress/t/t_dfg_3872.v diff --git a/src/V3DfgPeephole.cpp b/src/V3DfgPeephole.cpp index 213e9de6b..72d1f19b0 100644 --- a/src/V3DfgPeephole.cpp +++ b/src/V3DfgPeephole.cpp @@ -1400,26 +1400,17 @@ class V3DfgPeephole final : public DfgVisitor { } void visit(DfgShiftL* vtxp) override { - UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width"); - if (foldBinary(vtxp)) return; - optimizeShiftRHS(vtxp); } void visit(DfgShiftR* vtxp) override { - UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width"); - if (foldBinary(vtxp)) return; - optimizeShiftRHS(vtxp); } void visit(DfgShiftRS* vtxp) override { - UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width"); - if (foldBinary(vtxp)) return; - optimizeShiftRHS(vtxp); } diff --git a/test_regress/t/t_dfg_3872.pl b/test_regress/t/t_dfg_3872.pl new file mode 100755 index 000000000..31e4367f7 --- /dev/null +++ b/test_regress/t/t_dfg_3872.pl @@ -0,0 +1,16 @@ +#!/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); + +compile(); + +ok(1); +1; diff --git a/test_regress/t/t_dfg_3872.v b/test_regress/t/t_dfg_3872.v new file mode 100644 index 000000000..2a7b0617a --- /dev/null +++ b/test_regress/t/t_dfg_3872.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Geza Lore. +// SPDX-License-Identifier: CC0-1.0 + +module top( + input wire [1:0] i, + output wire [3:0] o +); + assign o = 4'd2 ** i; +endmodule diff --git a/test_regress/t/t_dfg_peephole.cpp b/test_regress/t/t_dfg_peephole.cpp index 4efbd858a..0664397e1 100644 --- a/test_regress/t/t_dfg_peephole.cpp +++ b/test_regress/t/t_dfg_peephole.cpp @@ -30,17 +30,20 @@ int main(int, char**) { uint64_t rand_a = 0x5aef0c8dd70a4497; uint64_t rand_b = 0xf0c0a8dd75ae4497; uint64_t srand_a = 0x00fa8dcc7ae4957; + uint64_t srand_b = 0x0fa8dc7ae3c9574; for (size_t n = 0; n < 200000; ++n) { // Update rngs rngUpdate(rand_a); rngUpdate(rand_b); rngUpdate(srand_a); + rngUpdate(srand_b); // Assign inputs ref.rand_a = opt.rand_a = rand_a; ref.rand_b = opt.rand_b = rand_b; ref.srand_a = opt.srand_a = srand_a; + ref.srand_b = opt.srand_b = srand_b; // Evaluate both models ref.eval(); diff --git a/test_regress/t/t_dfg_peephole.v b/test_regress/t/t_dfg_peephole.v index de4f54229..7f0ea086e 100644 --- a/test_regress/t/t_dfg_peephole.v +++ b/test_regress/t/t_dfg_peephole.v @@ -8,7 +8,7 @@ module t ( `include "portlist.vh" // Boilerplate generated by t_dfg_peephole.pl - rand_a, rand_b, srand_a + rand_a, rand_b, srand_a, srand_b ); `include "portdecl.vh" // Boilerplate generated by t_dfg_peephole.pl @@ -16,9 +16,11 @@ module t ( input rand_a; input rand_b; input srand_a; + input srand_b; wire logic [63:0] rand_a; wire logic [63:0] rand_b; wire logic signed [63:0] srand_a; + wire logic signed [63:0] srand_b; wire logic randbit_a = rand_a[0]; wire logic [127:0] rand_ba = {rand_b, rand_a}; @@ -179,6 +181,15 @@ module t ( `signal(RIGHT_LEANING_ASSOC, (((rand_a + rand_b) + rand_a) + rand_b)); `signal(RIGHT_LEANING_CONCET, {{{rand_a, rand_b}, rand_a}, rand_b}); + // Operators that should work wiht mismatched widths + `signal(MISMATCHED_ShiftL,const_a << 4'd2); + `signal(MISMATCHED_ShiftR,const_a >> 4'd2); + `signal(MISMATCHED_ShiftRS, const_a >> 4'd2); + `signal(MISMATCHED_PowUU, rand_a ** 4'd5); + `signal(MISMATCHED_PowSS, srand_a ** 4'sd5); + `signal(MISMATCHED_PowSU, srand_b ** 4'd5); + `signal(MISMATCHED_PowUS, rand_b ** 4'sd5); + // Some selects need extra temporaries wire [63:0] sel_from_cond = rand_a[0] ? rand_a : const_a; wire [63:0] sel_from_shiftl = rand_a << 10;