verilator/test_regress/t/t_dfg_break_cycles.v

231 lines
6.7 KiB
Systemverilog
Raw Normal View History

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
`define signal(name, width) wire [width-1:0] name
module t (
`include "portlist.vh" // Boilerplate generated by t_dfg_break_cycles.py
rand_a, rand_b, srand_a, srand_b
);
`include "portdecl.vh" // Boilerplate generated by t_dfg_break_cycles.py
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;
//////////////////////////////////////////////////////////////////////////
// Interesting user code to cover
//////////////////////////////////////////////////////////////////////////
2025-08-15 09:20:36 +02:00
`signal(GRAY_SEL, 3); // UNOPTFLAT
assign GRAY_SEL = rand_a[2:0] ^ 3'(GRAY_SEL[2:1]);
2025-08-15 09:20:36 +02:00
`signal(GRAY_SHIFT, 3); // UNOPTFLAT
assign GRAY_SHIFT = rand_a[2:0] ^ (GRAY_SHIFT >> 1);
2025-08-15 09:20:36 +02:00
`signal(GRAY_REV_SEL, 3); // UNOPTFLAT
assign GRAY_REV_SEL = rand_a[2:0] ^ {GRAY_REV_SEL[1:0], 1'b0};
2025-08-15 09:20:36 +02:00
`signal(GRAY_REV_SHIFT, 3); // UNOPTFLAT
assign GRAY_REV_SHIFT = rand_a[2:0] ^ (GRAY_REV_SHIFT << 1);
//////////////////////////////////////////////////////////////////////////
// Fill coverage
//////////////////////////////////////////////////////////////////////////
2025-08-15 09:20:36 +02:00
`signal(CONCAT_RHS, 2); // UNOPTFLAT
assign CONCAT_RHS[0] = rand_a[0];
assign CONCAT_RHS[1] = CONCAT_RHS[0];
2025-08-15 09:20:36 +02:00
`signal(CONCAT_LHS, 2); // UNOPTFLAT
assign CONCAT_LHS[0] = CONCAT_LHS[1];
assign CONCAT_LHS[1] = rand_a[1];
2025-08-15 09:20:36 +02:00
`signal(CONCAT_MID, 3); // UNOPTFLAT
assign CONCAT_MID[0] = |CONCAT_MID[2:1];
assign CONCAT_MID[2:1] = {rand_a[2], ~rand_a[2]};
2025-08-15 09:20:36 +02:00
`signal(SEL, 3); // UNOPTFLAT
assign SEL[0] = rand_a[4];
assign SEL[1] = SEL[0];
assign SEL[2] = SEL[1];
2025-08-15 09:20:36 +02:00
`signal(EXTEND, 8); // UNOPTFLAT
assign EXTEND[0] = rand_a[3];
assign EXTEND[3:1] = 3'(EXTEND[0]);
assign EXTEND[4] = EXTEND[1];
assign EXTEND[6:5] = EXTEND[2:1];
assign EXTEND[7] = EXTEND[3];
2025-08-15 09:20:36 +02:00
`signal(NOT, 3); // UNOPTFLAT
assign NOT = ~(rand_a[2:0] ^ 3'(NOT[2:1]));
2025-08-15 09:20:36 +02:00
`signal(AND, 3); // UNOPTFLAT
assign AND = rand_a[2:0] & 3'(AND[2:1]);
2025-08-15 09:20:36 +02:00
`signal(OR, 3); // UNOPTFLAT
assign OR = rand_a[2:0] | 3'(OR[2:1]);
2025-08-15 09:20:36 +02:00
`signal(SHIFTR, 14); // UNOPTFLAT
assign SHIFTR = {
SHIFTR[6:5], // 13:12
SHIFTR[7:6], // 11:10
SHIFTR[5:4], // 9:8
SHIFTR[3:0] >> 2, // 7:4
rand_a[3:0] // 3:0
};
2025-08-15 09:20:36 +02:00
`signal(SHIFTR_VARIABLE, 2); // UNOPTFLAT
assign SHIFTR_VARIABLE = rand_a[1:0] ^ ({1'b0, SHIFTR_VARIABLE[1]} >> rand_b[0]);
2025-08-15 09:20:36 +02:00
`signal(SHIFTL, 14); // UNOPTFLAT
assign SHIFTL = {
SHIFTL[6:5], // 13:12
SHIFTL[7:6], // 11:10
SHIFTL[5:4], // 9:8
SHIFTL[3:0] << 2, // 7:4
rand_a[3:0] // 3:0
};
2025-08-15 09:20:36 +02:00
`signal(SHIFTL_VARIABLE, 2); // UNOPTFLAT
assign SHIFTL_VARIABLE = rand_a[1:0] ^ ({SHIFTL_VARIABLE[0], 1'b0} << rand_b[0]);
2025-08-15 09:20:36 +02:00
`signal(VAR_A, 2); // UNOPTFLAT
wire logic [1:0] VAR_B;
assign VAR_A = {rand_a[0], VAR_B[0]};
assign VAR_B = (VAR_A >> 1) ^ 2'(VAR_B[1]);
2025-08-15 09:20:36 +02:00
`signal(REPLICATE, 4); // UNOPTFLAT
assign REPLICATE = rand_a[3:0] ^ ({2{REPLICATE[3:2]}} >> 2);
2025-08-15 09:20:36 +02:00
`signal(PARTIAL, 4); // UNOPTFLAT
assign PARTIAL[0] = rand_a[0];
// PARTIAL[1] intentionally unconnected
assign PARTIAL[3:2] = rand_a[3:2] ^ {PARTIAL[2], PARTIAL[0]};
wire [2:0] array_0 [2];
assign array_0[0] = rand_a[2:0];
assign array_0[1] = array_0[0];
2025-08-15 09:20:36 +02:00
`signal(ARRAY_0, 3); // UNOPTFLAT
assign ARRAY_0 = array_0[1];
wire [2:0] array_1 [1];
assign array_1[0][0] = rand_a[0];
assign array_1[0][1] = array_1[0][0];
assign array_1[0][2] = array_1[0][1];
2025-08-15 09:20:36 +02:00
`signal(ARRAY_1, 3); // UNOPTFLAT
assign ARRAY_1 = array_1[0];
wire [2:0] array_2a [2];
wire [2:0] array_2b [2];
assign array_2a[0][0] = rand_a[0];
assign array_2a[0][1] = array_2b[1][0];
assign array_2a[0][2] = array_2b[1][1];
assign array_2a[1] = array_2a[0];
assign array_2b = array_2a;
2025-08-15 09:20:36 +02:00
`signal(ARRAY_2, 3); // UNOPTFLAT
assign ARRAY_2 = array_2a[0];
wire [2:0] array_3 [2];
assign array_3[0] = rand_a[2:0] ^ array_3[1] >> 1;
assign array_3[1] = array_3[0];
2025-08-15 09:20:36 +02:00
`signal(ARRAY_3, 3); // UNOPTFLAT
assign ARRAY_3 = array_3[0];
2025-08-15 09:20:36 +02:00
`signal(ADD_A, 8); // UNOPTFLAT
`signal(ADD_B, 8);
`signal(ADD_C, 8);
assign ADD_C = rand_b[7:0] + ADD_B;
assign ADD_B = (ADD_A << 4) + rand_a[7:0];
assign ADD_A = {ADD_C[7], 7'd0};
`signal(SUB_A, 8); // UNOPTFLAT
`signal(SUB_B, 8);
`signal(SUB_C, 8);
assign SUB_C = rand_b[7:0] - SUB_B;
assign SUB_B = (SUB_A << 4) - rand_a[7:0];
assign SUB_A = {SUB_C[7], 7'd0};
`signal(EQ_A, 1); // UNOPTFLAT
`signal(EQ_B, 3);
assign EQ_A = EQ_B >> 1 == rand_b[2:0];
assign EQ_B = {rand_a[1:0], EQ_A};
`signal(NEQ_A, 1); // UNOPTFLAT
`signal(NEQ_B, 3);
assign NEQ_A = NEQ_B >> 1 != rand_b[2:0];
assign NEQ_B = {rand_a[1:0], NEQ_A};
`signal(LT_A, 1); // UNOPTFLAT
`signal(LT_B, 3);
assign LT_A = LT_B >> 1 < rand_b[2:0];
assign LT_B = {rand_a[1:0], LT_A};
`signal(LTE_A, 1); // UNOPTFLAT
`signal(LTE_B, 3);
assign LTE_A = LTE_B >> 1 <= rand_b[2:0];
assign LTE_B = {rand_a[1:0], LTE_A};
`signal(GT_A, 1); // UNOPTFLAT
`signal(GT_B, 3);
assign GT_A = GT_B >> 1 > rand_b[2:0];
assign GT_B = {rand_a[1:0], GT_A};
`signal(GTE_A, 1); // UNOPTFLAT
`signal(GTE_B, 3);
assign GTE_A = GTE_B >> 1 >= rand_b[2:0];
assign GTE_B = {rand_a[1:0], GTE_A};
`signal(COND_THEN, 3); // UNOPTFLAT
assign COND_THEN = {rand_a[0], rand_a[0] ? 2'(COND_THEN << 2) : rand_b[1:0]};
2025-08-15 09:20:36 +02:00
`signal(COND_ELSE, 3); // UNOPTFLAT
assign COND_ELSE = {rand_a[0], rand_a[0] ? rand_b[1:0] : 2'(COND_ELSE << 2)};
2025-08-15 09:20:36 +02:00
`signal(COND_COND, 3); // UNOPTFLAT
assign COND_COND = {rand_a[0], (COND_COND >> 2) == 3'b001 ? rand_b[3:2] : rand_b[1:0]};
Optimize complex combinational logic in DFG (#6298) This patch adds DfgLogic, which is a vertex that represents a whole, arbitrarily complex combinational AstAlways or AstAssignW in the DfgGraph. Implementing this requires computing the variables live at entry to the AstAlways (variables read by the block), so there is a new ControlFlowGraph data structure and a classical data-flow analysis based live variable analysis to do that at the variable level (as opposed to bit/element level). The actual CFG construction and live variable analysis is best effort, and might fail for currently unhandled constructs or data types. This can be extended later. V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices. The DfgLogic are then subsequently synthesized into primitive operations by the new V3DfgSynthesize pass, which is a combination of the old V3DfgAstToDfg conversion and new code to handle AstAlways blocks with complex flow control. V3DfgSynthesize by default will synthesize roughly the same constructs as V3DfgAstToDfg used to handle before, plus any logic that is part of a combinational cycle within the DfgGraph. This enables breaking up these cycles, for which there are extensions to V3DfgBreakCycles in this patch as well. V3DfgSynthesize will then delete all non synthesized or non synthesizable DfgLogic vertices and the rest of the Dfg pipeline is identical, with minor changes to adjust for the changed representation. Because with this change we can now eliminate many more UNOPTFLAT, DFG has been disabled in all the tests that specifically target testing the scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
// verilator lint_off ALWCOMBORDER
logic [3:0] always_0;
always_comb begin
always_0[3] = ~always_0[1];
always_0[2] = always_0[1];
always_0[0] = rand_a[0];
end
assign always_0[1] = ~always_0[0];
`signal(ALWAYS_0, 4); // UNOPTFLAT
assign ALWAYS_0 = always_0;
// verilator lint_on ALWCOMBORDER
// verilator lint_off ALWCOMBORDER
logic [4:0] always_1;
always_comb begin
always_1[4] = always_1[0];
always_1[0] = rand_a[0];
always_1[3:2] = always_1[1:0];
end
assign always_1[1] = always_1[0];
`signal(ALWAYS_1, 5); // UNOPTFLAT
assign ALWAYS_1 = always_1;
// verilator lint_on ALWCOMBORDER
// verilator lint_off ALWCOMBORDER
logic [3:0] always_2;
always_comb begin
always_2[2:0] = 3'((always_2 << 1) | 4'(rand_a[0]));
always_2[3] = rand_a[0];
end
`signal(ALWAYS_2, 4); // UNOPTFLAT
assign ALWAYS_2 = always_2;
// verilator lint_on ALWCOMBORDER
endmodule