mirror of
https://github.com/verilator/verilator.git
synced 2025-01-22 14:24:18 +00:00
a83043d735
Allow constant folding through adjacent nodes of all associative operations, for example '((a & 2) & 3)' or '(3 & (2 & a))' can now be folded into '(a & 2)' and '(2 & a)' respectively. Also improve speed of making associative expression trees right leaning by using rotation of the existing vertices whenever instead of allocation of new nodes.
202 lines
11 KiB
Systemverilog
202 lines
11 KiB
Systemverilog
// DESCRIPTION: Verilator: Verilog Test module
|
|
//
|
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
|
// any use, without warranty, 2022 by Geza Lore.
|
|
// SPDX-License-Identifier: CC0-1.0
|
|
|
|
`define signal(name, expr) wire [$bits(expr)-1:0] ``name = expr
|
|
|
|
module t (
|
|
`include "portlist.vh" // Boilerplate generated by t_dfg_peephole.pl
|
|
rand_a, rand_b, srand_a
|
|
);
|
|
|
|
`include "portdecl.vh" // Boilerplate generated by t_dfg_peephole.pl
|
|
|
|
input rand_a;
|
|
input rand_b;
|
|
input srand_a;
|
|
wire logic [63:0] rand_a;
|
|
wire logic [63:0] rand_b;
|
|
wire logic signed [63:0] srand_a;
|
|
|
|
wire logic randbit_a = rand_a[0];
|
|
wire logic [127:0] rand_ba = {rand_b, rand_a};
|
|
wire logic [127:0] rand_aa = {2{rand_a}};
|
|
wire logic [63:0] const_a;
|
|
wire logic [63:0] const_b;
|
|
wire logic signed [63:0] sconst_a;
|
|
wire logic signed [63:0] sconst_b;
|
|
wire logic [63:0] array [3:0];
|
|
assign array[0] = (rand_a << 32) | (rand_a >> 32);
|
|
assign array[1] = (rand_a << 16) | (rand_a >> 48);
|
|
|
|
// x, but with evaluation slightly delayed in DfgPeephole
|
|
`define DFG(x) (&16'hffff ? (x) : (~x))
|
|
|
|
`signal(FOLD_UNARY_CLog2, $clog2(const_a));
|
|
`signal(FOLD_UNARY_CountOnes, $countones(const_a));
|
|
`signal(FOLD_UNARY_IsUnknown, $isunknown(const_a));
|
|
`signal(FOLD_UNARY_LogNot, !const_a[0]);
|
|
`signal(FOLD_UNARY_Negate, -const_a);
|
|
`signal(FOLD_UNARY_Not, ~const_a);
|
|
`signal(FOLD_UNARY_OneHot, $onehot(const_a));
|
|
`signal(FOLD_UNARY_OneHot0, $onehot0(const_a));
|
|
`signal(FOLD_UNARY_RedAnd, &const_a);
|
|
`signal(FOLD_UNARY_RedOr, |const_a);
|
|
`signal(FOLD_UNARY_RedXor, ^const_a);
|
|
// verilator lint_off WIDTH
|
|
wire logic [79:0] tmp_FOLD_UNARY_Extend = const_a;
|
|
wire logic signed [79:0] tmp_FOLD_UNARY_ExtendS = sconst_a;
|
|
//verilator lint_on WIDTH
|
|
`signal(FOLD_UNARY_Extend, tmp_FOLD_UNARY_Extend);
|
|
`signal(FOLD_UNARY_ExtendS, tmp_FOLD_UNARY_ExtendS);
|
|
|
|
`signal(FOLD_BINARY_Add, const_a + const_b);
|
|
`signal(FOLD_BINARY_And, const_a & const_b);
|
|
`signal(FOLD_BINARY_Concat, {const_a, const_b});
|
|
`signal(FOLD_BINARY_Div, const_a / 64'd3);
|
|
`signal(FOLD_BINARY_DivS, sconst_a / 64'sd3);
|
|
`signal(FOLD_BINARY_Eq, const_a == const_b);
|
|
`signal(FOLD_BINARY_Gt, const_a > const_b);
|
|
`signal(FOLD_BINARY_GtS, sconst_a > sconst_b);
|
|
`signal(FOLD_BINARY_Gte, const_a >= const_b);
|
|
`signal(FOLD_BINARY_GteS, sconst_a >= sconst_b);
|
|
`signal(FOLD_BINARY_LogAnd, const_a[0] && const_b[0]);
|
|
`signal(FOLD_BINARY_LogEq, const_a[0] <-> const_b[0]);
|
|
`signal(FOLD_BINARY_LogIf, const_a[0] -> const_b[0]);
|
|
`signal(FOLD_BINARY_LogOr, const_a[0] || const_b[0]);
|
|
`signal(FOLD_BINARY_Lt, const_a < const_b);
|
|
`signal(FOLD_BINARY_LtS, sconst_a < sconst_b);
|
|
`signal(FOLD_BINARY_Lte, const_a <= const_b);
|
|
`signal(FOLD_BINARY_LteS, sconst_a <= sconst_b);
|
|
`signal(FOLD_BINARY_ModDiv, const_a % 64'd3);
|
|
`signal(FOLD_BINARY_ModDivS, sconst_a % 64'sd3);
|
|
`signal(FOLD_BINARY_Mul, const_a * 64'd3);
|
|
`signal(FOLD_BINARY_MulS, sconst_a * 64'sd3);
|
|
`signal(FOLD_BINARY_Neq, const_a != const_b);
|
|
`signal(FOLD_BINARY_Or, const_a | const_b);
|
|
`signal(FOLD_BINARY_Pow, const_a ** 64'd2);
|
|
`signal(FOLD_BINARY_PowSS, sconst_a ** 64'sd2);
|
|
`signal(FOLD_BINARY_PowSU, sconst_a ** 64'd2);
|
|
`signal(FOLD_BINARY_PowUS, const_a ** 64'sd2);
|
|
`signal(FOLD_BINARY_Replicate, {2{const_a}});
|
|
`signal(FOLD_BINARY_ShiftL, const_a << 2);
|
|
`signal(FOLD_BINARY_ShiftR, const_a >> 2);
|
|
`signal(FOLD_BINARY_ShiftRS, sconst_a >>> 2);
|
|
`signal(FOLD_BINARY_Sub, const_a - const_b);
|
|
`signal(FOLD_BINARY_Xor, const_a ^ const_b);
|
|
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_And, (const_a & (const_b & rand_a)));
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_Or, (const_a | (const_b | rand_a)));
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_Xor, (const_a ^ (const_b ^ rand_a)));
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_Add, (const_a + (const_b + rand_a)));
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_Mul, (const_a * (const_b * rand_a)));
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_MulS, (sconst_a * (sconst_b * srand_a)));
|
|
`signal(FOLD_ASSOC_BINARY_LHS_OF_RHS_Concat, {const_a, {const_b, rand_a}});
|
|
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_And, ((rand_a & const_b) & const_a));
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_Or, ((rand_a | const_b) | const_a));
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_Xor, ((rand_a ^ const_b) ^ const_a));
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_Add, ((rand_a + const_b) + const_a));
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_Mul, ((rand_a * const_b) * const_a));
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_MulS, ((srand_a * sconst_b) * sconst_a));
|
|
`signal(FOLD_ASSOC_BINARY_RHS_OF_LHS_Concat, {{rand_a, const_b}, const_a});
|
|
|
|
`signal(FOLD_SEL, const_a[3:1]);
|
|
|
|
`signal(SWAP_CONST_IN_COMMUTATIVE_BINARY, rand_a + const_a);
|
|
`signal(SWAP_NOT_IN_COMMUTATIVE_BINARY, rand_a + ~rand_a);
|
|
`signal(SWAP_VAR_IN_COMMUTATIVE_BINARY, rand_b + rand_a);
|
|
`signal(PUSH_BITWISE_OP_THROUGH_CONCAT, 32'h12345678 ^ {8'h0, rand_a[23:0]});
|
|
`signal(PUSH_BITWISE_OP_THROUGH_CONCAT_2, 32'h12345678 ^ {rand_b[7:0], rand_a[23:0]});
|
|
`signal(PUSH_COMPARE_OP_THROUGH_CONCAT, 4'b1011 == {2'b10, rand_a[1:0]});
|
|
`signal(PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH, |(rand_a[32] ? rand_a[3:0] : 4'h0));
|
|
`signal(REPLACE_REDUCTION_OF_CONST_AND, &const_a);
|
|
`signal(REPLACE_REDUCTION_OF_CONST_OR, |const_a);
|
|
`signal(REPLACE_REDUCTION_OF_CONST_XOR, ^const_a);
|
|
`signal(REPLACE_EXTEND, 4'(rand_a[0]));
|
|
`signal(PUSH_NOT_THROUGH_COND, ~(rand_a[0] ? rand_a[4:0] : 5'hb));
|
|
`signal(REMOVE_NOT_NOT, ~~rand_a);
|
|
`signal(REPLACE_NOT_NEQ, ~(rand_a != rand_b));
|
|
`signal(REPLACE_NOT_EQ, ~(rand_a == rand_b));
|
|
`signal(REPLACE_NOT_OF_CONST, ~4'd0);
|
|
`signal(REPLACE_AND_OF_NOT_AND_NOT, ~rand_a[1] & ~rand_b[1]);
|
|
`signal(REPLACE_AND_OF_NOT_AND_NEQ, ~rand_a[2] & (rand_b != 64'd2));
|
|
`signal(REPLACE_AND_OF_CONST_AND_CONST, const_a & const_b);
|
|
`signal(REPLACE_AND_WITH_ZERO, 64'd0 & rand_a);
|
|
`signal(REMOVE_AND_WITH_ONES, -64'd1 & rand_a);
|
|
`signal(REPLACE_CONTRADICTORY_AND, rand_a & ~rand_a);
|
|
`signal(REPLACE_OR_OF_NOT_AND_NOT, ~rand_a[3] | ~rand_b[3]);
|
|
`signal(REPLACE_OR_OF_NOT_AND_NEQ, ~rand_a[4] | (rand_b != 64'd3));
|
|
`signal(REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO, {2'd0, rand_a[1:0]} | {rand_b[1:0], 2'd0});
|
|
`signal(REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS, {rand_a[1:0], 2'd0} | {2'd0, rand_b[1:0]});
|
|
`signal(REPLACE_OR_OF_CONST_AND_CONST, const_a | const_b);
|
|
`signal(REMOVE_OR_WITH_ZERO, 64'd0 | rand_a);
|
|
`signal(REPLACE_OR_WITH_ONES, -64'd1 | rand_a);
|
|
`signal(REPLACE_TAUTOLOGICAL_OR, rand_a | ~rand_a);
|
|
`signal(REMOVE_SUB_ZERO, rand_a - 64'd0);
|
|
`signal(REPLACE_SUB_WITH_NOT, rand_a[0] - 1'b1);
|
|
`signal(REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT, rand_a << {2'b0, rand_a[2:0]});
|
|
`signal(REPLACE_EQ_OF_CONST_AND_CONST, 4'd0 == 4'd1);
|
|
`signal(REMOVE_FULL_WIDTH_SEL, rand_a[63:0]);
|
|
`signal(REMOVE_SEL_FROM_RHS_OF_CONCAT, rand_ba[63:0]);
|
|
`signal(REMOVE_SEL_FROM_LHS_OF_CONCAT, rand_ba[127:64]);
|
|
`signal(PUSH_SEL_THROUGH_CONCAT, rand_ba[120:0]);
|
|
`signal(PUSH_SEL_THROUGH_REPLICATE, rand_aa[0]);
|
|
`signal(REPLACE_SEL_FROM_CONST, const_a[2]);
|
|
`signal(REPLACE_CONCAT_OF_CONSTS, {const_a, const_b});
|
|
`signal(REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR, {62'd0, rand_a[63:62]});
|
|
`signal(REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL, {rand_a[1:0], 62'd0});
|
|
`signal(PUSH_CONCAT_THROUGH_NOTS, {~(rand_a+64'd101), ~(rand_b+64'd101)} );
|
|
`signal(REMOVE_CONCAT_OF_ADJOINING_SELS, {rand_a[10:3], rand_a[2:1]});
|
|
`signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS, {rand_a[10:3], `DFG({rand_a[2:1], rand_b})});
|
|
`signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS, {`DFG({rand_b, rand_a[10:3]}), rand_a[2:1]});
|
|
`signal(REMOVE_COND_WITH_FALSE_CONDITION, 1'd0 ? rand_a : rand_b);
|
|
`signal(REMOVE_COND_WITH_TRUE_CONDITION, 1'd1 ? rand_a : rand_b);
|
|
`signal(SWAP_COND_WITH_NOT_CONDITION, (~rand_a[0] & 1'd1) ? rand_a : rand_b);
|
|
`signal(SWAP_COND_WITH_NEQ_CONDITION, rand_b != rand_a ? rand_a : rand_b);
|
|
`signal(PULL_NOTS_THROUGH_COND, rand_a[0] ? ~rand_a[4:0] : ~rand_b[4:0]);
|
|
`signal(REPLACE_COND_WITH_THEN_BRANCH_ZERO, rand_a[0] ? 1'd0 : rand_a[1]);
|
|
`signal(REPLACE_COND_WITH_THEN_BRANCH_ONES, rand_a[0] ? 1'd1 : rand_a[1]);
|
|
`signal(REPLACE_COND_WITH_ELSE_BRANCH_ZERO, rand_a[0] ? rand_a[1] : 1'd0);
|
|
`signal(REPLACE_COND_WITH_ELSE_BRANCH_ONES, rand_a[0] ? rand_a[1] : 1'd1);
|
|
`signal(INLINE_ARRAYSEL, array[0]);
|
|
`signal(PUSH_BITWISE_THROUGH_REDUCTION_AND, (&(rand_a + 64'd105)) & (&(rand_b + 64'd108)));
|
|
`signal(PUSH_BITWISE_THROUGH_REDUCTION_OR, (|(rand_a + 64'd106)) | (|(rand_b + 64'd109)));
|
|
`signal(PUSH_BITWISE_THROUGH_REDUCTION_XOR, (^(rand_a + 64'd107)) ^ (^(rand_b + 64'd110)));
|
|
`signal(PUSH_REDUCTION_THROUGH_CONCAT_AND, &{1'd1, rand_b});
|
|
`signal(PUSH_REDUCTION_THROUGH_CONCAT_OR, |{1'd1, rand_b});
|
|
`signal(PUSH_REDUCTION_THROUGH_CONCAT_XOR, ^{1'd1, rand_b});
|
|
`signal(REMOVE_WIDTH_ONE_REDUCTION_AND, &rand_a[0]);
|
|
`signal(REMOVE_WIDTH_ONE_REDUCTION_OR, |rand_a[0]);
|
|
`signal(REMOVE_WIDTH_ONE_REDUCTION_XOR, ^rand_a[0]);
|
|
`signal(REMOVE_XOR_WITH_ZERO, 64'd0 ^ rand_a);
|
|
`signal(REMOVE_XOR_WITH_ONES, -64'd1 ^ rand_a);
|
|
`signal(REPLACE_COND_DEC, randbit_a ? rand_b - 64'b1 : rand_b);
|
|
`signal(REPLACE_COND_INC, randbit_a ? rand_b + 64'b1 : 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});
|
|
|
|
// 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;
|
|
wire [31:0] sel_from_sel = rand_a[10+:32];
|
|
|
|
`signal(PUSH_SEL_THROUGH_COND, sel_from_cond[2]);
|
|
`signal(PUSH_SEL_THROUGH_SHIFTL, sel_from_shiftl[20:0]);
|
|
`signal(REPLACE_SEL_FROM_SEL, sel_from_sel[4:3]);
|
|
|
|
// Sel from not requires the operand to have a sinle sink, so can't use
|
|
// the chekc due to the raw expression referencing the operand
|
|
wire [63:0] sel_from_not_tmp = ~(rand_a >> rand_b[2:0] << rand_a[3:0]);
|
|
wire sel_from_not = sel_from_not_tmp[2];
|
|
always @(posedge randbit_a) if ($c(0)) $display(sel_from_not); // Do not remove signal
|
|
|
|
// Assigned at the end to avoid inlining by other passes
|
|
assign const_a = 64'h0123456789abcdef;
|
|
assign const_b = 64'h98badefc10325647;
|
|
assign sconst_a = 64'hfedcba9876543210;
|
|
assign sconst_b = 64'hba0123456789cdef;
|
|
endmodule
|