diff --git a/Changes b/Changes index 656f88f33..cfbe0328d 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,7 @@ Verilator 5.027 devel * Fix fusing macro arguments to not ignore whitespace (#5061). [Tudor Timi] * Fix mis-removing $value$plusargs calls (#5127) (#5137). [Seth Pellegrino] * Fix splitting if statements with impure conditions (#5219). [Bartłomiej Chmiel, Antmicro Ltd.] +* Fix unknown conversion on queues (#5220). [Alex Solomatnikov] * Fix top-level unpacked structure resets (#5221). * Fix concurrency for mailbox and semaphores (#5222). [Liam Braun] diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 4d7e57e23..632793693 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -469,20 +469,18 @@ class UnknownVisitor final : public VNVisitor { nodep->bitp()->cloneTreePure(false)}; // Note below has null backp(); the Edit function knows how to deal with that. condp = V3Const::constifyEdit(condp); + AstNodeDType* nodeDtp = nodep->dtypep()->skipRefp(); if (condp->isOne()) { // We don't need to add a conditional; we know the existing expression is ok VL_DO_DANGLING(condp->deleteTree(), condp); } else if (!lvalue // Making a scalar would break if we're making an array - && !VN_IS(nodep->dtypep()->skipRefp(), NodeArrayDType) - && !(VN_IS(nodep->dtypep()->skipRefp(), NodeUOrStructDType) - && !VN_CAST(nodep->dtypep()->skipRefp(), NodeUOrStructDType) - ->packed())) { + && VN_IS(nodeDtp, BasicDType)) { // ARRAYSEL(...) -> COND(LT(bitunlinkFrBack(&replaceHandle); V3Number xnum{nodep, nodep->width()}; - if (nodep->isString()) { + if (nodeDtp->isString()) { xnum = V3Number{V3Number::String{}, nodep, ""}; } else { xnum.setAllBitsX(); diff --git a/test_regress/t/t_queue_unknown_sel.pl b/test_regress/t/t_queue_unknown_sel.pl new file mode 100755 index 000000000..157d7a50b --- /dev/null +++ b/test_regress/t/t_queue_unknown_sel.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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(simulator => 1); + +compile( + ); + +ok(1); +1; diff --git a/test_regress/t/t_queue_unknown_sel.v b/test_regress/t/t_queue_unknown_sel.v new file mode 100644 index 000000000..a62e5f031 --- /dev/null +++ b/test_regress/t/t_queue_unknown_sel.v @@ -0,0 +1,409 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Alex Solomatnikov. +// SPDX-License-Identifier: CC0-1.0 + +package z_pkg; + localparam int OPCODEW=3; + localparam int CIDW=4; + localparam int SIDW=10; + localparam int CTAGW=7; + localparam int STAGW=9; + localparam int STATEW=3; + localparam int ADDRW=37; + localparam int DATAW=256; + localparam int MASKW=DATAW/8; + localparam int SIZEW=4; + typedef enum logic [OPCODEW-1:0] { + A = 3'h 0, + B = 3'h 1 + } a_op_t; + typedef enum logic [OPCODEW-1:0] { + C = 3'h 0, + D = 3'h 1 + } b_op_t; + typedef enum logic [OPCODEW-1:0] { + E = 3'h 0, + F = 3'h 1 + } c_op_t; + typedef enum logic [OPCODEW-1:0] { + G = 3'h 0, + H = 3'h 1 + } d_op_t; + typedef logic [CIDW-1:0] cid_t; + typedef logic [SIDW-1:0] sid_t; + typedef logic [CTAGW-1:0] ctag_t; + typedef logic [STAGW-1:0] stag_t; + typedef logic [STATEW-1:0] state_t; + typedef logic [ADDRW-1:0] address_t; + typedef logic [SIZEW-1:0] size_t; + typedef logic [DATAW-1:0] data_t; + typedef logic [MASKW-1:0] mask_t; + typedef struct packed { + cid_t cid; + a_op_t opcode; + address_t address; + } x1_ch_t; + typedef struct packed { + cid_t cid; + b_op_t opcode; + address_t address; + } x2_ch_t; + typedef struct packed { + cid_t cid; + sid_t sid; + ctag_t ctag; + stag_t stag; + c_op_t opcode; + state_t state2; + state_t state3; + address_t address; + logic f4; + size_t size; + logic f2; + } x3_ch_t; + typedef struct packed { + cid_t cid; + sid_t sid; + ctag_t ctag; + stag_t stag; + d_op_t opcode; + state_t state1; + logic f4; + logic f1; + size_t size; + logic f3; + } x4_ch_t; + typedef struct packed { + cid_t cid; + ctag_t ctag; + stag_t stag; + d_op_t opcode; + logic f1; + logic f3; + } x5_ch_t; + typedef struct packed { + logic last; + logic corrupt; + } x6_ch_t; + typedef struct packed { + sid_t sid; + stag_t stag; + } x7_ch_t; + typedef enum { + CH_X1, + CH_Y1, + CH_Y2, + CH_X2, + CH_X3, + CH_Y3, + CH_X4, + CH_X5, + CH_X6, + CH_X7 + } channel_t; + parameter channel_t CH_ALL[CH_X7+1] = '{CH_X1, CH_Y1, CH_Y2, CH_X2, CH_X3, CH_Y3, CH_X4, CH_X5, CH_X6, CH_X7}; + typedef enum { + TXN_0, + TXN_1, + TXN_2, + TXN_3, + TXN_4, + TXN_5, + TXN_6, + TXN_7 + } txn_type_t; + function txn_type_t txn_type(bit [2:0] opcode, channel_t ch); + case(opcode) + 3'd0: begin + case(ch) + CH_X1: txn_type = TXN_1; + CH_X2: txn_type = TXN_7; + CH_X3: txn_type = TXN_7; + CH_Y3: txn_type = TXN_7; + CH_X4: txn_type = TXN_2; + CH_X6: txn_type = TXN_2; + default: txn_type = TXN_0; + endcase + end + 3'd1: begin + case(ch) + CH_Y1: txn_type = TXN_3; + CH_X2: txn_type = TXN_4; + CH_X3: txn_type = TXN_5; + CH_Y3: txn_type = TXN_5; + CH_X5: txn_type = TXN_6; + default: txn_type = TXN_0; + endcase + end + 3'd2: begin + case(ch) + CH_Y1: txn_type = TXN_7; + CH_X2: txn_type = TXN_7; + CH_X3: txn_type = TXN_7; + CH_Y3: txn_type = TXN_7; + CH_X4: txn_type = TXN_7; + CH_X6: txn_type = TXN_7; + default: txn_type = TXN_0; + endcase + end + 3'd3: begin + case(ch) + CH_Y1: txn_type = TXN_7; + CH_X2: txn_type = TXN_7; + CH_X3: txn_type = TXN_7; + CH_Y3: txn_type = TXN_7; + CH_X5: txn_type = TXN_7; + default: txn_type = TXN_0; + endcase + end + 3'd4: begin + case(ch) + CH_X1: txn_type = TXN_7; + CH_X2: txn_type = TXN_7; + CH_X3: txn_type = TXN_7; + CH_Y3: txn_type = TXN_7; + CH_X4: txn_type = TXN_7; + CH_X6: txn_type = TXN_7; + CH_X7: txn_type = TXN_7; + default: txn_type = TXN_0; + endcase + end + 3'd5: begin + case(ch) + CH_Y1: txn_type = TXN_7; + CH_X2: txn_type = TXN_7; + CH_X3: txn_type = TXN_7; + CH_Y3: txn_type = TXN_7; + CH_X5: txn_type = TXN_7; + default: txn_type = TXN_0; + endcase + end + 3'd6: begin + case(ch) + CH_X3: txn_type = TXN_7; + CH_Y3: txn_type = TXN_7; + CH_X5: txn_type = TXN_7; + default: txn_type = TXN_0; + endcase + end + 3'd7: begin + case(ch) + CH_Y2: txn_type = TXN_7; + default: txn_type = TXN_0; + endcase + end + endcase + endfunction +endpackage +interface z_if; + import z_pkg::*; + logic x1_valid; + x1_ch_t x1; + logic x2_valid; + x2_ch_t x2; + logic x3_valid; + x3_ch_t x3; + logic x4_valid; + x4_ch_t x4; + logic x5_valid; + x5_ch_t x5; + logic x6_valid; + x6_ch_t x6; + data_t x6_data; + logic x7_valid; + x7_ch_t x7; + function automatic logic x2_trig(); return x2_valid; endfunction + function automatic logic x4_trig(); return x4_valid; endfunction + function automatic logic x5_trig(); return x5_valid; endfunction + function automatic logic x6_trig(); return x6_valid; endfunction + modport sender ( + output x1_valid, + output x1, + input x2_valid, + input x2, + output x3_valid, + output x3, + input x4_valid, + input x4, + input x5_valid, + input x5, + input x6_valid, + input x6, + input x6_data, + output x7_valid, + output x7, + import x2_trig, + import x4_trig, + import x5_trig, + import x6_trig + ); + modport receiver ( + input x1_valid, + input x1, + output x2_valid, + output x2, + input x3_valid, + input x3, + output x4_valid, + output x4, + output x5_valid, + output x5, + output x6_valid, + output x6, + output x6_data, + input x7_valid, + input x7, + import x2_trig, + import x4_trig, + import x5_trig, + import x6_trig + ); +endinterface +class z_txn_class; + import z_pkg::*; + rand txn_type_t req_txn_type; + rand cid_t cid; + rand sid_t sid; + rand ctag_t ctag; + rand stag_t stag; + rand size_t size; + rand address_t address; + rand state_t state1; + rand state_t state2; + rand state_t state3; + rand logic f1; + rand logic f2; + rand logic f3; + rand logic f4; + data_t data[]; + mask_t mask[]; + bit corrupt[]; + logic [2:0] req_opcode; +endclass +module z_bfm_sender import z_pkg::*; + ( + input logic clk, + input logic reset_l, + z_if.sender z_if_sender + ); + channel_t ch; + typedef z_txn_class z_txn_q_t[$]; + z_txn_q_t z_txn_qs[ch.num()]; + z_txn_class z_txn[ch.num()]; + always @(posedge clk or negedge reset_l) begin + if (!reset_l) begin + z_if_sender.x1_valid <= '0; + z_if_sender.x3_valid <= '0; + z_if_sender.x7_valid <= '0; + end + else begin + foreach (CH_ALL[i]) begin + case(CH_ALL[i]) + CH_X1: begin + if (z_txn_qs[i].size() > 0) begin + z_txn[i] = z_txn_qs[i].pop_front(); + z_if_sender.x1_valid <= '1; + z_if_sender.x1.cid <= z_txn[i].cid; + z_if_sender.x1.opcode <= a_op_t'(z_txn[i].req_opcode); + z_if_sender.x1.address <= z_txn[i].address; + end + end + CH_X3: begin + if (z_txn_qs[i].size() > 0) begin + z_txn[i] = z_txn_qs[i].pop_front(); + z_if_sender.x3_valid <= '1; + z_if_sender.x3.cid <= z_txn[i].cid; + z_if_sender.x3.sid <= z_txn[i].sid; + z_if_sender.x3.ctag <= z_txn[i].ctag; + z_if_sender.x3.stag <= z_txn[i].stag; + z_if_sender.x3.opcode <= c_op_t'(z_txn[i].req_opcode); + z_if_sender.x3.state2 <= z_txn[i].state2; + z_if_sender.x3.state3 <= z_txn[i].state3; + z_if_sender.x3.address <= z_txn[i].address; + z_if_sender.x3.f4 <= z_txn[i].f4; + z_if_sender.x3.size <= z_txn[i].size; + z_if_sender.x3.f2 <= z_txn[i].f2; + end + end + CH_X7: begin + if (z_txn_qs[i].size() > 0) begin + z_txn[i] = z_txn_qs[i].pop_front(); + z_if_sender.x7.sid <= z_txn[i].sid; + z_if_sender.x7.stag <= z_txn[i].stag; + end + end + CH_X2: begin + if (z_if_sender.x2_trig()) begin + z_txn[i] = new; + z_txn[i].req_txn_type = txn_type(z_if_sender.x2.opcode, ch); + z_txn[i].cid = z_if_sender.x2.cid; + z_txn[i].address = z_if_sender.x2.address; + z_txn_qs[i].push_back(z_txn[i]); + end + end + CH_X4: begin + if (z_if_sender.x4_trig()) begin + z_txn[i] = new; + z_txn[i].req_txn_type = txn_type(z_if_sender.x4.opcode, ch); + z_txn[i].cid = z_if_sender.x4.cid; + z_txn[i].sid = z_if_sender.x4.sid; + z_txn[i].ctag = z_if_sender.x4.ctag; + z_txn[i].stag = z_if_sender.x4.stag; + z_txn[i].state1 = z_if_sender.x4.state1; + z_txn[i].f1 = z_if_sender.x4.f1; + z_txn[i].f4 = z_if_sender.x4.f4; + z_txn[i].size = z_if_sender.x4.size; + z_txn[i].f3 = z_if_sender.x4.f3; + z_txn_qs[i].push_back(z_txn[i]); + end + end + CH_X5: begin + if (z_if_sender.x5_trig()) begin + z_txn[i] = new; + z_txn[i].req_txn_type = txn_type(z_if_sender.x5.opcode, ch); + z_txn[i].cid = z_if_sender.x5.cid; + z_txn[i].ctag = z_if_sender.x5.ctag; + z_txn[i].f1 = z_if_sender.x5.f1; + z_txn_qs[i].push_back(z_txn[i]); + end + end + CH_X6: begin + if (z_if_sender.x6_trig()) begin + z_txn[i] = new; + z_txn[i].data = new[1]; + z_txn[i].corrupt = new[1]; + z_txn[i].data[0] = z_if_sender.x6_data; + z_txn[i].corrupt[0] = z_if_sender.x6.corrupt; + z_txn_qs[i].push_back(z_txn[i]); + end + end + endcase + end + end + end +endmodule +module test_core_wrapper + ( + input logic clk, + input logic reset_l, + z_if.sender z, + mmio_z + ); + z_bfm_sender mem_z_bfm( .z_if_sender(z), + .*); + z_bfm_sender mmio_z_bfm( .z_if_sender(mmio_z), + .*); +endmodule +module t + ( + input clk, + input reset_l + ); + z_if z(), + mmio_z(); + test_core_wrapper tile( .z (z.sender), + .mmio_z(mmio_z.sender), + .*); +endmodule