Files
verilator/test_regress/t/t_interface_array_virtual.v
T
Geza Lore 9e03fed56b Support multi-dim interface instance arrays and interface array ports (#8493)
Companion to #8476, and this now moves all instance array and interface
array/modport array port expansion into elaboration. Fixes #2675.

Arrays of interface instances and interface array ports are now split
into their elements during elaboration, instead of after V3Width in
V3Inst::dearrayAll, which is removed.

Background: next to every interface instance 'intf ifs()', V3LinkCells
creates a companion variable 'ifs__Viftop' of type IfaceRefDType
referring to the instance, so the instantiating module can use the
interface as a value (in pin connections, virtual interface assignments,
arguments, ...) just like a module referring to it through an interface
port. For an array of instances 'intf ifs[N]()', this variable is an
unpacked array of IfaceRefDType, but an IfaceRefDType can only refer to
a single instance, so it must be split into a variable for each element,
and every use of the whole array replaced.

V3Param expands interface instance arrays like module instance arrays,
also splitting the __Viftop variable referencing the whole array into a
variable for each element cell ('ifs__BRA__i__KET____Viftop', the
companion of element cell 'ifs__BRA__i__KET__'), and splits each
interface array port into a variable for each element. The whole array
variables remain until all references to them are replaced, so V3LinkDot
can link hierarchical references to the correct specialization.

In V3Width, every reference to a whole interface array, including
hierarchical ones, is replaced by an AstInitArray of references to its
element variables, typed as the whole array, e.g. 'ifs' becomes
'{ifs[0], ifs[1], ...}. The AstInitArray keeps its own type, so its uses
are checked as those of the whole array. The whole array variables are
removed at the end of V3Width.

V3Width then treats a whole interface array replaced by an AstInitArray
as an ordinary unpacked array value:
- A constant select yields the element, a slice the selected elements.
- A pin of an element of a module instance array selects its part of an
  interface array connection like any other connection.
- A pin of an interface array port is split into a pin for each element
  port, connected left index to left index.
- A member of an element is referenced through the interface, as for
  any other interface.

This supports slices of interface arrays, and interface ports of
multi-dimensional module instance arrays connected to interface arrays.
2026-09-24 19:10:33 +01:00

94 lines
2.2 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
interface a_if;
int x;
endinterface
typedef virtual a_if va_t;
module sub;
a_if ifs[2] ();
for (genvar i = 0; i < 2; ++i) begin : g
initial ifs[i].x = 'h40 + i;
end
endmodule
class C;
va_t vif[2];
endclass
module t;
a_if asc[0:3] ();
a_if desc[3:0] ();
a_if a2d[1:0][0:2] ();
for (genvar i = 0; i < 4; ++i) begin : g_1d
initial begin
asc[i].x = 'h10 + i;
desc[i].x = 'h20 + i;
end
end
for (genvar i = 0; i < 2; ++i) begin : g_2d_i
for (genvar j = 0; j < 3; ++j) begin : g_2d_j
initial a2d[i][j].x = 'h30 + 3 * i + j;
end
end
va_t w[4];
va_t s[2];
va_t w2d[2][3];
C c;
sub i_sub ();
initial begin
#1;
// Whole array, left element to left element
w = asc;
for (int i = 0; i < 4; ++i) `checkh(w[i].x, 'h10 + i);
w = desc;
for (int i = 0; i < 4; ++i) `checkh(w[i].x, 'h20 + 3 - i);
// Slices
s = asc[1:2];
`checkh(s[0].x, 'h11);
`checkh(s[1].x, 'h12);
s = desc[2:1];
`checkh(s[0].x, 'h22);
`checkh(s[1].x, 'h21);
// Multi dimensional, a2d[1] is the left row
w2d = a2d;
for (int i = 0; i < 2; ++i) begin
for (int j = 0; j < 3; ++j) `checkh(w2d[i][j].x, 'h30 + 3 * (1 - i) + j);
end
// Hierarchical reference to a whole array
s = i_sub.ifs;
`checkh(s[0].x, 'h40);
`checkh(s[1].x, 'h41);
`checkh(i_sub.ifs[0].x, 'h40);
`checkh(i_sub.ifs[1].x, 'h41);
// Class member
c = new;
c.vif = asc[2:3];
`checkh(c.vif[0].x, 'h12);
`checkh(c.vif[1].x, 'h13);
// Writes through the virtual interfaces reach the instances
c.vif[1].x = 'h99;
w2d[0][2].x = 'h98;
#1;
`checkh(asc[3].x, 'h99);
`checkh(a2d[1][2].x, 'h98);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule