forked from github/verilator
180 lines
7.4 KiB
Systemverilog
180 lines
7.4 KiB
Systemverilog
// DESCRIPTION: Test that slice assignment overflows are handled correctly,
|
|
// i.e. that if you assign to a slice such that some of the bits you assign to
|
|
// do not actually exist, that those bits get correctly discarded.
|
|
// Issue #2803 existed in a number number of different codepaths in
|
|
// verilated.h and V3Expand.cpp. This test should cover all of these cases
|
|
// when run both with and without the -Ox flag to verilator.
|
|
// - Select offset constant, insert IData into CData
|
|
// - Select offset constant, insert IData into SData
|
|
// - Select offset constant, insert IData into IData
|
|
// - Select offset constant, insert QData into QData
|
|
// - Select offset constant, insert IData into WData within a word
|
|
// - Select offset constant, insert IData into WData crossing a word boundary
|
|
// - Select offset constant, insert IData into WData whole word insertion
|
|
// - Select offset constant, insert QData into WData
|
|
// - Select offset constant, insert WData into WData, several whole words
|
|
// - Select offset constant, insert WData into WData, starting at word-offset
|
|
// - Select offset constant, insert WData into WData, all other cases
|
|
// - Select offset is non-constant, destination is wide, bit-select width == 1
|
|
// - Select offset is non-constant, destination is wide, bit-select width != 1
|
|
// - Select offset is non-constant, destination is narrow
|
|
//
|
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
|
// any use, without warranty, 2021 by David Turner.
|
|
// SPDX-License-Identifier: CC0-1.0
|
|
|
|
module t(/*AUTOARG*/
|
|
// Inputs
|
|
clk
|
|
);
|
|
input clk;
|
|
|
|
integer cyc = 0;
|
|
// Non-constant offsets
|
|
reg varoffset1;
|
|
reg [6:0] varoffset2;
|
|
reg [6:0] varoffset3;
|
|
|
|
// Destinations for variable-offset assignments
|
|
reg [69:0] dstwide1;
|
|
reg [69:0] dstwide2;
|
|
reg [1:0] dstnarrow;
|
|
|
|
// Constant offsets
|
|
reg [6:0] constoffset;
|
|
|
|
// Destinations for constant-offset assignments
|
|
reg [2:0] dst_cdata;
|
|
reg [11:0] dst_sdata;
|
|
reg [29:0] dst_idata;
|
|
reg [59:0] dst_qdata;
|
|
reg [69:0] dst_wdata1; // assign idata within word
|
|
reg [69:0] dst_wdata2; // assign idata crossing word boundary
|
|
reg [69:0] dst_wdata3; // assign idata corresponding to whole word
|
|
reg [69:0] dst_wdata4; // assign qdata
|
|
reg [69:0] dst_wdata5; // assign wdata corresponding to several whole words
|
|
reg [69:0] dst_wdata6; // assign wdata starting at word-offset
|
|
reg [69:0] dst_wdata7; // assign wdata unaligned
|
|
|
|
always @(*) begin
|
|
// Non-constant select offset, destination narrow
|
|
dstnarrow = 2'd0;
|
|
dstnarrow[varoffset1 +: 2'd2] = 2'd2;
|
|
|
|
// Non-constant select offset, destination wide, width == 1
|
|
dstwide1 = 70'd0;
|
|
dstwide1[varoffset2 +: 1'd1] = 1'd1;
|
|
|
|
// Non-constant select offset, destination wide, width != 1
|
|
dstwide2 = 70'd0;
|
|
dstwide2[varoffset3 +: 2'd2] = 2'd2;
|
|
|
|
// Constant offset, IData into CData
|
|
constoffset = 7'd2;
|
|
dst_cdata = 3'd0;
|
|
dst_cdata[constoffset[0 +: 2] +: 3'd3] = 3'd6;
|
|
|
|
// Constant offset, IData into SData
|
|
constoffset = 7'd11;
|
|
dst_sdata = 12'd0;
|
|
dst_sdata[constoffset[0 +: 4] +: 2'd2] = 2'd2;
|
|
|
|
// Constant offset, IData into IData
|
|
constoffset = 7'd29;
|
|
dst_idata = 30'd0;
|
|
dst_idata[constoffset[0 +: 5] +: 2'd2] = 2'd2;
|
|
|
|
// Constant offset, QData into QData
|
|
constoffset = 7'd59;
|
|
dst_qdata = 60'd0;
|
|
dst_qdata[constoffset[0 +: 6] +: 2'd2] = 2'd2;
|
|
|
|
// Constant offset, IData into WData within word
|
|
constoffset = 7'd69;
|
|
dst_wdata1 = 70'd0;
|
|
dst_wdata1[constoffset +: 2'd2] = 2'd2;
|
|
|
|
// Constant offset, IData into WData crossing word boundary
|
|
constoffset = 7'd61;
|
|
dst_wdata2 = 70'd0;
|
|
dst_wdata2[constoffset +: 4'd10] = 10'd1 << 4'd9;
|
|
|
|
// Constant offset, IData into WData replacing a whole word
|
|
constoffset = 7'd64;
|
|
dst_wdata3 = 70'd0;
|
|
dst_wdata3[constoffset +: 6'd32] = 32'd1 << 3'd6;
|
|
|
|
// Constant offset, QData into WData
|
|
constoffset = 7'd31;
|
|
dst_wdata4 = 70'd0;
|
|
dst_wdata4[constoffset +: 7'd40] = 40'd1 << 7'd39;
|
|
|
|
// Constant offset, WData into WData replacing whole words
|
|
constoffset = 7'd32;
|
|
dst_wdata5 = 70'd0;
|
|
dst_wdata5[constoffset +: 7'd64] = 64'd1 << 7'd38;
|
|
|
|
// Constant offset, WData into WData offset word aligned
|
|
constoffset = 7'd32;
|
|
dst_wdata6 = 70'd0;
|
|
dst_wdata6[constoffset +: 7'd40] = 40'd1 << 7'd38;
|
|
|
|
// Constant offset, WData into WData unaligned
|
|
constoffset = 7'd1;
|
|
dst_wdata7 = 70'd0;
|
|
dst_wdata7[constoffset +: 7'd70] = 70'd1 << 7'd69;
|
|
end
|
|
|
|
// Test loop
|
|
always @ (posedge clk) begin
|
|
// State machine to avoid verilator constant-folding offset
|
|
if (cyc == 0) begin
|
|
// Initialisation
|
|
varoffset1 <= 1'd0;
|
|
varoffset2 <= 7'd0;
|
|
varoffset3 <= 7'd0;
|
|
end else if (cyc == 1) begin
|
|
// Variable offsets set here to avoid verilator constant folding
|
|
varoffset1 <= 1'd1;
|
|
varoffset2 <= 7'd70;
|
|
varoffset3 <= 7'd69;
|
|
end else if (cyc == 2) begin
|
|
// Check all destinations are 0
|
|
$write("dstwide1 = %23d, downshifted = %23d\n", dstwide1, dstwide1 >> 1);
|
|
$write("dstwide2 = %23d, downshifted = %23d\n", dstwide2, dstwide2 >> 1);
|
|
$write("dstnarrow = %23d, downshifted = %23d\n", dstnarrow, dstnarrow >> 1);
|
|
$write("dst_cdata = %23d, downshifted = %23d\n", dst_cdata, dst_cdata >> 1);
|
|
$write("dst_sdata = %23d, downshifted = %23d\n", dst_sdata, dst_sdata >> 1);
|
|
$write("dst_idata = %23d, downshifted = %23d\n", dst_idata, dst_idata >> 1);
|
|
$write("dst_qdata = %23d, downshifted = %23d\n", dst_qdata, dst_qdata >> 1);
|
|
$write("dst_wdata1 = %23d, downshifted = %23d\n", dst_wdata1, dst_wdata1 >> 1);
|
|
$write("dst_wdata2 = %23d, downshifted = %23d\n", dst_wdata2, dst_wdata2 >> 1);
|
|
$write("dst_wdata3 = %23d, downshifted = %23d\n", dst_wdata3, dst_wdata3 >> 1);
|
|
$write("dst_wdata4 = %23d, downshifted = %23d\n", dst_wdata4, dst_wdata4 >> 1);
|
|
$write("dst_wdata5 = %23d, downshifted = %23d\n", dst_wdata5, dst_wdata5 >> 1);
|
|
$write("dst_wdata6 = %23d, downshifted = %23d\n", dst_wdata6, dst_wdata6 >> 1);
|
|
$write("dst_wdata7 = %23d, downshifted = %23d\n", dst_wdata7, dst_wdata7 >> 1);
|
|
|
|
if (dstwide1 !== 70'd0 || (dstwide1 >> 1) !== 70'd0) $stop;
|
|
if (dstwide2 !== 70'd0 || (dstwide2 >> 1) !== 70'd0) $stop;
|
|
if (dstnarrow !== 2'd0 || (dstnarrow >> 1) !== 2'd0) $stop;
|
|
if (dst_cdata !== 3'd0 || (dst_cdata >> 1) !== 3'd0) $stop;
|
|
if (dst_sdata !== 12'd0 || (dst_sdata >> 1) !== 12'd0) $stop;
|
|
if (dst_idata !== 30'd0 || (dst_idata >> 1) !== 30'd0) $stop;
|
|
if (dst_qdata !== 60'd0 || (dst_qdata >> 1) !== 60'd0) $stop;
|
|
if (dst_wdata1 !== 70'd0 || (dst_wdata1 >> 1) !== 70'd0) $stop;
|
|
if (dst_wdata2 !== 70'd0 || (dst_wdata2 >> 1) !== 70'd0) $stop;
|
|
if (dst_wdata3 !== 70'd0 || (dst_wdata3 >> 1) !== 70'd0) $stop;
|
|
if (dst_wdata4 !== 70'd0 || (dst_wdata4 >> 1) !== 70'd0) $stop;
|
|
if (dst_wdata5 !== 70'd0 || (dst_wdata5 >> 1) !== 70'd0) $stop;
|
|
if (dst_wdata6 !== 70'd0 || (dst_wdata6 >> 1) !== 70'd0) $stop;
|
|
if (dst_wdata7 !== 70'd0 || (dst_wdata7 >> 1) !== 70'd0) $stop;
|
|
end else begin
|
|
$write("*-* All Finished *-*\n");
|
|
$finish;
|
|
end
|
|
|
|
cyc <= cyc + 1;
|
|
end
|
|
endmodule
|