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.
This commit is contained in:
Geza Lore 2023-01-22 10:43:16 +00:00
parent 3a8288b0f6
commit 3069860fdf
5 changed files with 43 additions and 10 deletions

View File

@ -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);
}

16
test_regress/t/t_dfg_3872.pl Executable file
View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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;