forked from github/verilator
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:
parent
3a8288b0f6
commit
3069860fdf
@ -1400,26 +1400,17 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void visit(DfgShiftL* vtxp) override {
|
void visit(DfgShiftL* vtxp) override {
|
||||||
UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
|
|
||||||
|
|
||||||
if (foldBinary(vtxp)) return;
|
if (foldBinary(vtxp)) return;
|
||||||
|
|
||||||
optimizeShiftRHS(vtxp);
|
optimizeShiftRHS(vtxp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(DfgShiftR* vtxp) override {
|
void visit(DfgShiftR* vtxp) override {
|
||||||
UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
|
|
||||||
|
|
||||||
if (foldBinary(vtxp)) return;
|
if (foldBinary(vtxp)) return;
|
||||||
|
|
||||||
optimizeShiftRHS(vtxp);
|
optimizeShiftRHS(vtxp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(DfgShiftRS* vtxp) override {
|
void visit(DfgShiftRS* vtxp) override {
|
||||||
UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
|
|
||||||
|
|
||||||
if (foldBinary(vtxp)) return;
|
if (foldBinary(vtxp)) return;
|
||||||
|
|
||||||
optimizeShiftRHS(vtxp);
|
optimizeShiftRHS(vtxp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
test_regress/t/t_dfg_3872.pl
Executable file
16
test_regress/t/t_dfg_3872.pl
Executable 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;
|
12
test_regress/t/t_dfg_3872.v
Normal file
12
test_regress/t/t_dfg_3872.v
Normal 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
|
@ -30,17 +30,20 @@ int main(int, char**) {
|
|||||||
uint64_t rand_a = 0x5aef0c8dd70a4497;
|
uint64_t rand_a = 0x5aef0c8dd70a4497;
|
||||||
uint64_t rand_b = 0xf0c0a8dd75ae4497;
|
uint64_t rand_b = 0xf0c0a8dd75ae4497;
|
||||||
uint64_t srand_a = 0x00fa8dcc7ae4957;
|
uint64_t srand_a = 0x00fa8dcc7ae4957;
|
||||||
|
uint64_t srand_b = 0x0fa8dc7ae3c9574;
|
||||||
|
|
||||||
for (size_t n = 0; n < 200000; ++n) {
|
for (size_t n = 0; n < 200000; ++n) {
|
||||||
// Update rngs
|
// Update rngs
|
||||||
rngUpdate(rand_a);
|
rngUpdate(rand_a);
|
||||||
rngUpdate(rand_b);
|
rngUpdate(rand_b);
|
||||||
rngUpdate(srand_a);
|
rngUpdate(srand_a);
|
||||||
|
rngUpdate(srand_b);
|
||||||
|
|
||||||
// Assign inputs
|
// Assign inputs
|
||||||
ref.rand_a = opt.rand_a = rand_a;
|
ref.rand_a = opt.rand_a = rand_a;
|
||||||
ref.rand_b = opt.rand_b = rand_b;
|
ref.rand_b = opt.rand_b = rand_b;
|
||||||
ref.srand_a = opt.srand_a = srand_a;
|
ref.srand_a = opt.srand_a = srand_a;
|
||||||
|
ref.srand_b = opt.srand_b = srand_b;
|
||||||
|
|
||||||
// Evaluate both models
|
// Evaluate both models
|
||||||
ref.eval();
|
ref.eval();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
module t (
|
module t (
|
||||||
`include "portlist.vh" // Boilerplate generated by t_dfg_peephole.pl
|
`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
|
`include "portdecl.vh" // Boilerplate generated by t_dfg_peephole.pl
|
||||||
@ -16,9 +16,11 @@ module t (
|
|||||||
input rand_a;
|
input rand_a;
|
||||||
input rand_b;
|
input rand_b;
|
||||||
input srand_a;
|
input srand_a;
|
||||||
|
input srand_b;
|
||||||
wire logic [63:0] rand_a;
|
wire logic [63:0] rand_a;
|
||||||
wire logic [63:0] rand_b;
|
wire logic [63:0] rand_b;
|
||||||
wire logic signed [63:0] srand_a;
|
wire logic signed [63:0] srand_a;
|
||||||
|
wire logic signed [63:0] srand_b;
|
||||||
|
|
||||||
wire logic randbit_a = rand_a[0];
|
wire logic randbit_a = rand_a[0];
|
||||||
wire logic [127:0] rand_ba = {rand_b, rand_a};
|
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_ASSOC, (((rand_a + rand_b) + rand_a) + rand_b));
|
||||||
`signal(RIGHT_LEANING_CONCET, {{{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
|
// Some selects need extra temporaries
|
||||||
wire [63:0] sel_from_cond = rand_a[0] ? rand_a : const_a;
|
wire [63:0] sel_from_cond = rand_a[0] ? rand_a : const_a;
|
||||||
wire [63:0] sel_from_shiftl = rand_a << 10;
|
wire [63:0] sel_from_shiftl = rand_a << 10;
|
||||||
|
Loading…
Reference in New Issue
Block a user