// 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-FileCopyrightText: 2026 Wilson Snyder // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 // // DESCRIPTION: Verilator: TRULY BLENDED test for interface typedef resolution // This test BLENDS both patterns into a single interacting structure: // - Sibling cells (like t_lparam_dep_iface10) // - Nested interface chains (like aerial_wrap) // - COMBINED: Sibling cells that EACH contain nested interface chains // // The key test: A module accesses typedefs from TWO sibling nested interface // chains, and each must resolve to the correct parameterized type. // // verilog_format: off `define stop $stop `define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); // verilog_format: on typedef struct packed { int unsigned AddrBits; int unsigned DataBits; int unsigned IdBits; } axi_cfg_t; // INNERMOST: Parameterized interface with typedefs interface axi4_if #( parameter axi_cfg_t cfg = 0 ) (); localparam int unsigned AddrBits = cfg.AddrBits * 2; localparam int unsigned DataBits = cfg.DataBits * 2; localparam int unsigned IdBits = cfg.IdBits * 2; typedef logic [AddrBits-1:0] addr_t; typedef logic [DataBits-1:0] data_t; typedef logic [IdBits-1:0] id_t; typedef struct packed { id_t id; addr_t addr; } ar_chan_t; typedef struct packed { id_t id; data_t data; } r_chan_t; ar_chan_t ar; r_chan_t r; endinterface // MIDDLE: Interface that wraps axi4_if and re-exports its typedefs interface tlb_io_if #( parameter axi_cfg_t axi_cfg = 0 ) (); axi4_if #(.cfg(axi_cfg)) axi_tlb_io (); // Re-export typedefs from nested interface typedef axi_tlb_io.r_chan_t r_chan_t; typedef axi_tlb_io.ar_chan_t ar_chan_t; endinterface // OUTER: Interface with TWO SIBLING tlb_io_if instances with DIFFERENT params // This is the BLENDED pattern: sibling cells + nested chains interface cca_io_if #( parameter axi_cfg_t axi_cfg_a = 0, parameter axi_cfg_t axi_cfg_b = 0 ) (); // SIBLING CELLS - same interface type, DIFFERENT params tlb_io_if #(.axi_cfg(axi_cfg_a)) tlb_io_a (); tlb_io_if #(.axi_cfg(axi_cfg_b)) tlb_io_b (); // Re-export from each sibling (these should be DIFFERENT types) typedef tlb_io_a.r_chan_t r_chan_a_t; typedef tlb_io_b.r_chan_t r_chan_b_t; endinterface // MODULE: Accesses typedefs from BOTH sibling nested chains via interface port // This is the CRITICAL test - must distinguish between tlb_io_a and tlb_io_b module cca_xbar ( cca_io_if cca_io ); // Access typedefs through SIBLING nested interface chains // These MUST resolve to DIFFERENT types based on the different params typedef cca_io.tlb_io_a.r_chan_t m_r_chan_a_t; // From axi_cfg_a typedef cca_io.tlb_io_b.r_chan_t m_r_chan_b_t; // From axi_cfg_b typedef cca_io.tlb_io_a.ar_chan_t m_ar_chan_a_t; typedef cca_io.tlb_io_b.ar_chan_t m_ar_chan_b_t; m_r_chan_a_t r_data_a; m_r_chan_b_t r_data_b; initial begin #1; // axi_cfg_a: AddrBits=32, DataBits=64, IdBits=4 // r_chan_t = id(4) + data(64) = 68 bits * 2 = 136 bits // ar_chan_t = id(4) + addr(32) = 36 bits * 2 = 72 bits `checkd($bits(m_r_chan_a_t), 136); `checkd($bits(m_ar_chan_a_t), 72); // axi_cfg_b: AddrBits=40, DataBits=128, IdBits=8 // r_chan_t = id(8) + data(128) = 136 bits * 2 = 272 bits // ar_chan_t = id(8) + addr(40) = 48 bits * 2 = 96 bits `checkd($bits(m_r_chan_b_t), 272); `checkd($bits(m_ar_chan_b_t), 96); end endmodule // TOP MODULE module t; localparam axi_cfg_t cfg_a = '{AddrBits: 32, DataBits: 64, IdBits: 4}; localparam axi_cfg_t cfg_b = '{AddrBits: 40, DataBits: 128, IdBits: 8}; cca_io_if #( .axi_cfg_a(cfg_a), .axi_cfg_b(cfg_b) ) cca_io (); cca_xbar xbar (.cca_io(cca_io)); initial begin #2; $write("*-* All Finished *-*\n"); $finish; end endmodule