Verilog format
This commit is contained in:
parent
13b1321985
commit
b0fdbff6eb
|
|
@ -1,5 +1,5 @@
|
|||
%Error-UNSUPPORTED: t/t_constraint_countbits_unsup.v:12:21: Unsupported: non-constant control in $countbits inside constraint
|
||||
12 | constraint cons { $countbits(value, ctrl) == 3; }
|
||||
| ^~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_countbits_unsup.v:12:20: Unsupported: non-constant control in $countbits inside constraint
|
||||
12 | constraint cons {$countbits(value, ctrl) == 3;}
|
||||
| ^~~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by PlanV GmbH.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test: non-constant control in $countbits inside constraint (unsupported)
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
class Packet;
|
||||
rand bit [7:0] value;
|
||||
bit ctrl;
|
||||
constraint cons { $countbits(value, ctrl) == 3; }
|
||||
constraint cons {$countbits(value, ctrl) == 3;}
|
||||
endclass
|
||||
|
||||
module t;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by PlanV GmbH.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test: Inline foreach constraints on dynamic arrays and queues of class objects
|
||||
|
|
@ -46,12 +46,12 @@ module t;
|
|||
od = new(3);
|
||||
|
||||
if (od.randomize() with {
|
||||
foreach (items[i]) {
|
||||
items[i].val > 10;
|
||||
items[i].val < 200;
|
||||
items[i].tag > 0;
|
||||
}
|
||||
} == 0) begin
|
||||
foreach (items[i]) {
|
||||
items[i].val > 10;
|
||||
items[i].val < 200;
|
||||
items[i].tag > 0;
|
||||
}
|
||||
} == 0) begin
|
||||
$display("FAIL: dyn randomize() returned 0");
|
||||
$stop;
|
||||
end
|
||||
|
|
@ -71,10 +71,10 @@ module t;
|
|||
od = new(0);
|
||||
|
||||
if (od.randomize() with {
|
||||
foreach (items[i]) {
|
||||
items[i].val > 10;
|
||||
}
|
||||
} == 0) begin
|
||||
foreach (items[i]) {
|
||||
items[i].val > 10;
|
||||
}
|
||||
} == 0) begin
|
||||
$display("FAIL: empty dyn randomize() returned 0");
|
||||
$stop;
|
||||
end
|
||||
|
|
@ -83,12 +83,12 @@ module t;
|
|||
oq = new(3);
|
||||
|
||||
if (oq.randomize() with {
|
||||
foreach (items[i]) {
|
||||
items[i].val > 50;
|
||||
items[i].val < 150;
|
||||
items[i].tag > 0;
|
||||
}
|
||||
} == 0) begin
|
||||
foreach (items[i]) {
|
||||
items[i].val > 50;
|
||||
items[i].val < 150;
|
||||
items[i].tag > 0;
|
||||
}
|
||||
} == 0) begin
|
||||
$display("FAIL: queue randomize() returned 0");
|
||||
$stop;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ class InnerClass;
|
|||
rand bit [7:0] inner_val2;
|
||||
|
||||
constraint inner_con {
|
||||
inner_val1 inside {[8'd10:8'd50]};
|
||||
inner_val2 inside {[8'd100:8'd200]};
|
||||
inner_val1 inside {[8'd10 : 8'd50]};
|
||||
inner_val2 inside {[8'd100 : 8'd200]};
|
||||
}
|
||||
|
||||
function new();
|
||||
|
|
@ -28,9 +28,7 @@ class OuterClass;
|
|||
rand InnerClass nested_obj;
|
||||
rand bit [7:0] outer_val;
|
||||
|
||||
constraint outer_con {
|
||||
outer_val inside {[8'd1:8'd20]};
|
||||
}
|
||||
constraint outer_con {outer_val inside {[8'd1 : 8'd20]};}
|
||||
|
||||
function new();
|
||||
nested_obj = new();
|
||||
|
|
|
|||
|
|
@ -9,8 +9,11 @@
|
|||
class ConstraintModeInCtor;
|
||||
rand bit [7:0] value;
|
||||
|
||||
constraint low_range_c { value < 50; };
|
||||
constraint high_range_c { value >= 50; value < 200; };
|
||||
constraint low_range_c {value < 50;}
|
||||
constraint high_range_c {
|
||||
value >= 50;
|
||||
value < 200;
|
||||
}
|
||||
|
||||
function new;
|
||||
// Disable high_range_c in constructor - only low_range_c should be active
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by PlanV GmbH.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test static constraint_mode() support per IEEE 1800-2017 Section 18.4, 18.8
|
||||
|
|
@ -11,14 +11,10 @@ class StaticConstraintTest;
|
|||
rand bit [7:0] value;
|
||||
|
||||
// Static constraint - shared across all instances
|
||||
static constraint static_con {
|
||||
value inside {[10:15]};
|
||||
}
|
||||
static constraint static_con {value inside {[10 : 15]};}
|
||||
|
||||
// Non-static constraint for comparison
|
||||
constraint instance_con {
|
||||
value > 5;
|
||||
}
|
||||
constraint instance_con {value > 5;}
|
||||
endclass
|
||||
|
||||
module t;
|
||||
|
|
@ -51,7 +47,7 @@ module t;
|
|||
obj1.instance_con.constraint_mode(1);
|
||||
for (int i = 0; i < 10; i++) begin
|
||||
void'(obj1.randomize());
|
||||
if (!(obj1.value inside {[10:15]})) $stop;
|
||||
if (!(obj1.value inside {[10 : 15]})) $stop;
|
||||
if (!(obj1.value > 5)) $stop;
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ endclass
|
|||
module t;
|
||||
B b;
|
||||
initial begin
|
||||
b = new;
|
||||
b = new;
|
||||
b.a = new;
|
||||
if (b.randomize() == 0) $stop;
|
||||
if (b.a.x != LEN) $stop;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by PlanV GmbH.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test: System functions ($onehot, $onehot0, $countbits, $clog2) inside
|
||||
|
|
@ -9,29 +9,29 @@
|
|||
|
||||
class test_onehot;
|
||||
rand bit [7:0] value;
|
||||
constraint c_hot { $onehot(value); }
|
||||
constraint c_hot {$onehot(value);}
|
||||
endclass
|
||||
|
||||
class test_onehot0;
|
||||
rand bit [7:0] value;
|
||||
constraint c_hot0 { $onehot0(value); }
|
||||
constraint c_hot0 {$onehot0(value);}
|
||||
endclass
|
||||
|
||||
class test_countbits_ones;
|
||||
rand bit [7:0] value;
|
||||
constraint c_bits { $countbits(value, '1) == 3; }
|
||||
constraint c_bits {$countbits(value, '1) == 3;}
|
||||
endclass
|
||||
|
||||
class test_countbits_zeros;
|
||||
rand bit [7:0] value;
|
||||
constraint c_bits { $countbits(value, '0) == 6; } // 6 zeros = 2 ones
|
||||
constraint c_bits {$countbits(value, '0) == 6;} // 6 zeros = 2 ones
|
||||
endclass
|
||||
|
||||
class test_clog2;
|
||||
rand bit [7:0] data_width;
|
||||
rand bit [7:0] addr_bits;
|
||||
constraint c_log { addr_bits == 8'($clog2(data_width)); }
|
||||
constraint c_nonzero { data_width > 0; }
|
||||
constraint c_log {addr_bits == 8'($clog2(data_width));}
|
||||
constraint c_nonzero {data_width > 0;}
|
||||
endclass
|
||||
|
||||
module t;
|
||||
|
|
@ -44,7 +44,7 @@ module t;
|
|||
automatic bit ok = 1'b1;
|
||||
|
||||
// Test $onehot: exactly one bit set
|
||||
repeat(20) begin
|
||||
repeat (20) begin
|
||||
if (oh.randomize() == 0) $fatal(1, "$onehot randomize failed");
|
||||
if ($onehot(oh.value) !== 1'b1) begin
|
||||
$display("FAIL: $onehot value=%08b, $onehot=%0b", oh.value, $onehot(oh.value));
|
||||
|
|
@ -53,7 +53,7 @@ module t;
|
|||
end
|
||||
|
||||
// Test $onehot0: zero or one bit set
|
||||
repeat(20) begin
|
||||
repeat (20) begin
|
||||
if (oh0.randomize() == 0) $fatal(1, "$onehot0 randomize failed");
|
||||
if ($onehot0(oh0.value) !== 1'b1) begin
|
||||
$display("FAIL: $onehot0 value=%08b, $onehot0=%0b", oh0.value, $onehot0(oh0.value));
|
||||
|
|
@ -62,31 +62,31 @@ module t;
|
|||
end
|
||||
|
||||
// Test $countbits counting ones: exactly 3 ones
|
||||
repeat(20) begin
|
||||
repeat (20) begin
|
||||
if (cb1.randomize() == 0) $fatal(1, "$countbits('1) randomize failed");
|
||||
if ($countbits(cb1.value, '1) != 3) begin
|
||||
$display("FAIL: $countbits('1) value=%08b, count=%0d",
|
||||
cb1.value, $countbits(cb1.value, '1));
|
||||
$display("FAIL: $countbits('1) value=%08b, count=%0d", cb1.value, $countbits(cb1.value,
|
||||
'1));
|
||||
ok = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// Test $countbits counting zeros: exactly 6 zeros (= 2 ones)
|
||||
repeat(20) begin
|
||||
repeat (20) begin
|
||||
if (cb0.randomize() == 0) $fatal(1, "$countbits('0) randomize failed");
|
||||
if ($countbits(cb0.value, '0) != 6) begin
|
||||
$display("FAIL: $countbits('0) value=%08b, zeros=%0d ones=%0d",
|
||||
cb0.value, $countbits(cb0.value, '0), $countbits(cb0.value, '1));
|
||||
$display("FAIL: $countbits('0) value=%08b, zeros=%0d ones=%0d", cb0.value,
|
||||
$countbits(cb0.value, '0), $countbits(cb0.value, '1));
|
||||
ok = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// Test $clog2: addr_bits == $clog2(data_width)
|
||||
repeat(20) begin
|
||||
repeat (20) begin
|
||||
if (cl.randomize() == 0) $fatal(1, "$clog2 randomize failed");
|
||||
if (cl.addr_bits != 8'($clog2(cl.data_width))) begin
|
||||
$display("FAIL: $clog2 data_width=%0d, addr_bits=%0d, expected=%0d",
|
||||
cl.data_width, cl.addr_bits, $clog2(cl.data_width));
|
||||
$display("FAIL: $clog2 data_width=%0d, addr_bits=%0d, expected=%0d", cl.data_width,
|
||||
cl.addr_bits, $clog2(cl.data_width));
|
||||
ok = 1'b0;
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
typedef enum bit [4:0] {
|
||||
ZERO = 5'b00000,
|
||||
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
|
||||
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
|
||||
} EnumType;
|
||||
// verilog_format: on
|
||||
|
||||
class Base;
|
||||
rand EnumType b_scratch_reg;
|
||||
|
|
@ -44,7 +46,7 @@ module t;
|
|||
Foo foo;
|
||||
initial begin
|
||||
foo = new;
|
||||
repeat(100) if (foo.randomize() != 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop;
|
||||
repeat (100) if (foo.randomize() != 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
%Warning-CONSTRAINTIGN: t/t_constraint_unq_arr_derived_inline_unsup.v:32:7: Unsupported: Unique constraint in randomize() with {}
|
||||
: ... note: In instance 't'
|
||||
32 | unique{foo.pmp_reg};
|
||||
| ^~~~~~
|
||||
%Warning-CONSTRAINTIGN: t/t_constraint_unq_arr_derived_inline_unsup.v:35:11: Unsupported: Unique constraint in randomize() with {}
|
||||
: ... note: In instance 't'
|
||||
35 | unique {foo.pmp_reg};
|
||||
| ^~~~~~
|
||||
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
|
||||
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
typedef enum bit [4:0] {
|
||||
ZERO = 5'b00000,
|
||||
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
|
||||
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
|
||||
} EnumType;
|
||||
// verilog_format: on
|
||||
|
||||
class Base;
|
||||
rand EnumType b_scratch_reg;
|
||||
|
|
@ -28,11 +30,13 @@ module t;
|
|||
Foo foo;
|
||||
initial begin
|
||||
foo = new;
|
||||
repeat(100) if (foo.randomize() with {
|
||||
unique{foo.pmp_reg};
|
||||
foo.pmp_reg[0] inside {1,2};
|
||||
foo.pmp_reg[1] inside {1,2};}
|
||||
!= 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop;
|
||||
repeat (100)
|
||||
if (foo.randomize() with {
|
||||
unique {foo.pmp_reg};
|
||||
foo.pmp_reg[0] inside {1, 2};
|
||||
foo.pmp_reg[1] inside {1, 2};
|
||||
} != 1 || foo.pmp_reg[0] == foo.pmp_reg[1])
|
||||
$stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by PlanV GmbH.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class Packet;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@
|
|||
// 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=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t;
|
||||
|
||||
|
|
@ -19,7 +21,7 @@ module t;
|
|||
// Generate variables
|
||||
for (genvar n = 0; n < N; ++n) begin : vars
|
||||
logic [n:0] tmp;
|
||||
logic out;
|
||||
logic out;
|
||||
end
|
||||
|
||||
// Generate logic
|
||||
|
|
@ -27,7 +29,8 @@ module t;
|
|||
if (n == 0) begin
|
||||
assign vars[n].tmp = ~crc[n];
|
||||
assign vars[n].out = vars[n].tmp[n];
|
||||
end else begin
|
||||
end
|
||||
else begin
|
||||
assign vars[n].tmp = {~crc[n], vars[n-1].tmp};
|
||||
assign vars[n].out = vars[n].tmp[n] ^ vars[n-1].out;
|
||||
end
|
||||
|
|
@ -41,7 +44,7 @@ module t;
|
|||
// Sink has no other sinks
|
||||
wire [3:0] noother_src = {crc[5:4], crc[2:1]};
|
||||
wire [1:0] noother_sel = noother_src[2:1];
|
||||
wire [7:0] noother_dst = {crc[9:6], noother_src}; // singal intentianally unused
|
||||
wire [7:0] noother_dst = {crc[9:6], noother_src}; // singal intentianally unused
|
||||
|
||||
int cyc;
|
||||
always @(posedge clk) begin
|
||||
|
|
@ -50,10 +53,10 @@ module t;
|
|||
//$display("%16b %16b", ~crc[N-1:0], vars[N-1].tmp);
|
||||
//$display("%16b %16b", ^(~crc[N-1:0]), vars[N-1].out);
|
||||
// Check halfway through, this prevents pushing sels past this point
|
||||
`checkh(vars[N/2].tmp, ~crc[N/2:0]);
|
||||
`checkh(vars[N/2].tmp, ~crc[N/2:0]);
|
||||
`checkh(vars[N/2].out, ^(~crc[N/2:0]));
|
||||
// Check final value
|
||||
`checkh(vars[N-1].tmp, ~crc[N-1:0]);
|
||||
`checkh(vars[N-1].tmp, ~crc[N-1:0]);
|
||||
`checkh(vars[N-1].out, ^(~crc[N-1:0]));
|
||||
if (cyc == 10) begin
|
||||
// Observe danger_dst so it's not eliminated
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module x;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module x;
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ interface simple_if;
|
|||
logic data;
|
||||
logic [7:0] value;
|
||||
|
||||
modport source (output data, output value);
|
||||
modport sink (input data, input value);
|
||||
modport source(output data, output value);
|
||||
modport sink(input data, input value);
|
||||
endinterface
|
||||
|
||||
// Test 6: Submodule with interface array as sink modport port
|
||||
module sub_sink (
|
||||
simple_if.sink ifaces [3:0],
|
||||
output logic [7:0] sum_out
|
||||
simple_if.sink ifaces[3:0],
|
||||
output logic [7:0] sum_out
|
||||
);
|
||||
always_comb begin
|
||||
sum_out = 8'b0;
|
||||
|
|
@ -27,7 +27,7 @@ endmodule
|
|||
|
||||
// Test 7: Submodule with interface array as source modport port
|
||||
module sub_source (
|
||||
simple_if.source ifaces [3:0]
|
||||
simple_if.source ifaces[3:0]
|
||||
);
|
||||
always_comb begin
|
||||
for (int i = 0; i < 4; i++) begin
|
||||
|
|
@ -39,7 +39,7 @@ endmodule
|
|||
|
||||
// Test 8: Submodule with interface array without modport
|
||||
module sub_generic (
|
||||
simple_if ifaces [3:0]
|
||||
simple_if ifaces[3:0]
|
||||
);
|
||||
always_comb begin
|
||||
for (int i = 0; i < 4; i++) begin
|
||||
|
|
@ -51,10 +51,10 @@ endmodule
|
|||
|
||||
// Test 11: Parameterized submodule with interface array size from parameter
|
||||
module l1_param_sub #(
|
||||
parameter NUM_IFACES = 4
|
||||
parameter NUM_IFACES = 4
|
||||
) (
|
||||
simple_if.sink l0_ifaces [NUM_IFACES-1:0],
|
||||
output logic [7:0] l0_sum
|
||||
simple_if.sink l0_ifaces[NUM_IFACES-1:0],
|
||||
output logic [7:0] l0_sum
|
||||
);
|
||||
always_comb begin
|
||||
l0_sum = 8'b0;
|
||||
|
|
@ -64,16 +64,16 @@ module l1_param_sub #(
|
|||
end
|
||||
endmodule
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
module t ( /*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
localparam N = 4;
|
||||
|
||||
simple_if ifaces [N-1:0] ();
|
||||
simple_if ifaces[N-1:0] ();
|
||||
|
||||
// Test 1: Simple for loop writing to interface array
|
||||
always_comb begin
|
||||
|
|
@ -92,7 +92,7 @@ module t (/*AUTOARG*/
|
|||
|
||||
// Test 3: For loop with expression in body
|
||||
always_comb begin
|
||||
for (int k = 0; k < N-1; k++) begin
|
||||
for (int k = 0; k < N - 1; k++) begin
|
||||
// Use k to index, accessing different member
|
||||
ifaces[k].value = 8'(k);
|
||||
end
|
||||
|
|
@ -102,7 +102,7 @@ module t (/*AUTOARG*/
|
|||
// Test 4: Descending loop with >= comparison
|
||||
logic [N-1:0] desc_data;
|
||||
always_comb begin
|
||||
for (int p = N-1; p >= 0; p--) begin
|
||||
for (int p = N - 1; p >= 0; p--) begin
|
||||
desc_data[p] = ifaces[p].data;
|
||||
end
|
||||
end
|
||||
|
|
@ -110,13 +110,13 @@ module t (/*AUTOARG*/
|
|||
// Test 4b: Ascending loop with <= comparison
|
||||
logic [N-1:0] lte_data;
|
||||
always_comb begin
|
||||
for (int m = 0; m <= N-1; m++) begin
|
||||
for (int m = 0; m <= N - 1; m++) begin
|
||||
lte_data[m] = ifaces[m].data;
|
||||
end
|
||||
end
|
||||
|
||||
// Test 4c: Descending loop with > comparison
|
||||
simple_if gt_ifaces [N-1:0] ();
|
||||
simple_if gt_ifaces[N-1:0] ();
|
||||
always_comb begin
|
||||
for (int n = N; n > 0; n--) begin
|
||||
gt_ifaces[n-1].data = 1'b1;
|
||||
|
|
@ -125,7 +125,7 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
// Test 5: Multiple interface arrays in same loop
|
||||
simple_if other_ifaces [N-1:0] ();
|
||||
simple_if other_ifaces[N-1:0] ();
|
||||
always_comb begin
|
||||
for (int q = 0; q < N; q++) begin
|
||||
other_ifaces[q].data = ifaces[q].data;
|
||||
|
|
@ -135,18 +135,21 @@ module t (/*AUTOARG*/
|
|||
|
||||
// Test 6: Interface array as sink modport port (read from ports in loop)
|
||||
logic [7:0] sink_sum;
|
||||
sub_sink u_sub_sink (.ifaces(ifaces), .sum_out(sink_sum));
|
||||
sub_sink u_sub_sink (
|
||||
.ifaces(ifaces),
|
||||
.sum_out(sink_sum)
|
||||
);
|
||||
|
||||
// Test 7: Interface array as source modport port (write to ports in loop)
|
||||
simple_if source_ifaces [N-1:0] ();
|
||||
simple_if source_ifaces[N-1:0] ();
|
||||
sub_source u_sub_source (.ifaces(source_ifaces));
|
||||
|
||||
// Test 8: Interface array without modport (read/write in loop)
|
||||
simple_if generic_ifaces [N-1:0] ();
|
||||
simple_if generic_ifaces[N-1:0] ();
|
||||
sub_generic u_sub_generic (.ifaces(generic_ifaces));
|
||||
|
||||
// Test 9: Ascending loop with step of 2
|
||||
simple_if step2_ifaces [7:0] ();
|
||||
simple_if step2_ifaces[7:0] ();
|
||||
always_comb begin
|
||||
for (int i = 0; i < 8; i += 2) begin
|
||||
step2_ifaces[i].data = 1'b1;
|
||||
|
|
@ -159,7 +162,7 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
// Test 10: Descending loop with step of -2
|
||||
simple_if step2d_ifaces [7:0] ();
|
||||
simple_if step2d_ifaces[7:0] ();
|
||||
always_comb begin
|
||||
for (int i = 6; i >= 0; i -= 2) begin
|
||||
step2d_ifaces[i].data = 1'b1;
|
||||
|
|
@ -174,7 +177,7 @@ module t (/*AUTOARG*/
|
|||
// Test 11: Parameterized submodule with interface array size from parameter
|
||||
// Override NUM_IFACES from default 4 to 6 to test that pre-unroll
|
||||
// uses the overridden parameter value (not the default)
|
||||
simple_if l0_param_ifaces [5:0] ();
|
||||
simple_if l0_param_ifaces[5:0] ();
|
||||
always_comb begin
|
||||
for (int i = 0; i < 6; i++) begin
|
||||
l0_param_ifaces[i].data = 1'b1;
|
||||
|
|
@ -182,13 +185,15 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
end
|
||||
logic [7:0] l0_param_sum;
|
||||
l1_param_sub #(.NUM_IFACES(6)) u_l1_param (
|
||||
.l0_ifaces(l0_param_ifaces),
|
||||
.l0_sum(l0_param_sum)
|
||||
l1_param_sub #(
|
||||
.NUM_IFACES(6)
|
||||
) u_l1_param (
|
||||
.l0_ifaces(l0_param_ifaces),
|
||||
.l0_sum(l0_param_sum)
|
||||
);
|
||||
|
||||
// Test 12: Complex index expression (N-1-i) - reversed assignment
|
||||
simple_if rev_ifaces [N-1:0] ();
|
||||
simple_if rev_ifaces[N-1:0] ();
|
||||
always_comb begin
|
||||
for (int i = 0; i < N; i++) begin
|
||||
rev_ifaces[N-1-i].data = 1'b1;
|
||||
|
|
@ -197,7 +202,7 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
// Test 13: Non-zero-based interface array range [2:5]
|
||||
simple_if nzb_ifaces [2:5] ();
|
||||
simple_if nzb_ifaces[2:5] ();
|
||||
always_comb begin
|
||||
for (int i = 2; i <= 5; i++) begin
|
||||
nzb_ifaces[i].data = 1'b1;
|
||||
|
|
@ -223,14 +228,14 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
// Check values
|
||||
for (int i = 0; i < N-1; i++) begin
|
||||
for (int i = 0; i < N - 1; i++) begin
|
||||
if (ifaces[i].value !== 8'(i)) begin
|
||||
$display("%%Error: ifaces[%0d].value should be %0d, got %0d", i, i, ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
if (ifaces[N-1].value !== 8'hFF) begin
|
||||
$display("%%Error: ifaces[%0d].value should be 0xFF, got %0d", N-1, ifaces[N-1].value);
|
||||
$display("%%Error: ifaces[%0d].value should be 0xFF, got %0d", N - 1, ifaces[N-1].value);
|
||||
$stop;
|
||||
end
|
||||
|
||||
|
|
@ -249,7 +254,8 @@ module t (/*AUTOARG*/
|
|||
$stop;
|
||||
end
|
||||
if (gt_ifaces[i].value !== 8'(i + 1)) begin
|
||||
$display("%%Error: gt_ifaces[%0d].value should be %0d, got %0d", i, i+1, gt_ifaces[i].value);
|
||||
$display("%%Error: gt_ifaces[%0d].value should be %0d, got %0d", i, i + 1,
|
||||
gt_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -263,11 +269,13 @@ module t (/*AUTOARG*/
|
|||
// Test 7: Check source_ifaces (written by sub_source with i+100)
|
||||
for (int i = 0; i < N; i++) begin
|
||||
if (source_ifaces[i].data !== 1'b1) begin
|
||||
$display("%%Error: source_ifaces[%0d].data should be 1, got %b", i, source_ifaces[i].data);
|
||||
$display("%%Error: source_ifaces[%0d].data should be 1, got %b", i,
|
||||
source_ifaces[i].data);
|
||||
$stop;
|
||||
end
|
||||
if (source_ifaces[i].value !== 8'(i + 100)) begin
|
||||
$display("%%Error: source_ifaces[%0d].value should be %0d, got %0d", i, i+100, source_ifaces[i].value);
|
||||
$display("%%Error: source_ifaces[%0d].value should be %0d, got %0d", i, i + 100,
|
||||
source_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -275,11 +283,13 @@ module t (/*AUTOARG*/
|
|||
// Test 8: Check generic_ifaces (written by sub_generic with i+50)
|
||||
for (int i = 0; i < N; i++) begin
|
||||
if (generic_ifaces[i].data !== 1'b0) begin
|
||||
$display("%%Error: generic_ifaces[%0d].data should be 0, got %b", i, generic_ifaces[i].data);
|
||||
$display("%%Error: generic_ifaces[%0d].data should be 0, got %b", i,
|
||||
generic_ifaces[i].data);
|
||||
$stop;
|
||||
end
|
||||
if (generic_ifaces[i].value !== 8'(i + 50)) begin
|
||||
$display("%%Error: generic_ifaces[%0d].value should be %0d, got %0d", i, i+50, generic_ifaces[i].value);
|
||||
$display("%%Error: generic_ifaces[%0d].value should be %0d, got %0d", i, i + 50,
|
||||
generic_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -288,20 +298,25 @@ module t (/*AUTOARG*/
|
|||
for (int i = 0; i < 8; i++) begin
|
||||
if (i % 2 == 0) begin
|
||||
if (step2_ifaces[i].data !== 1'b1) begin
|
||||
$display("%%Error: step2_ifaces[%0d].data should be 1, got %b", i, step2_ifaces[i].data);
|
||||
$display("%%Error: step2_ifaces[%0d].data should be 1, got %b", i,
|
||||
step2_ifaces[i].data);
|
||||
$stop;
|
||||
end
|
||||
if (step2_ifaces[i].value !== 8'(i)) begin
|
||||
$display("%%Error: step2_ifaces[%0d].value should be %0d, got %0d", i, i, step2_ifaces[i].value);
|
||||
$display("%%Error: step2_ifaces[%0d].value should be %0d, got %0d", i, i,
|
||||
step2_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
end
|
||||
else begin
|
||||
if (step2_ifaces[i].data !== 1'b0) begin
|
||||
$display("%%Error: step2_ifaces[%0d].data should be 0, got %b", i, step2_ifaces[i].data);
|
||||
$display("%%Error: step2_ifaces[%0d].data should be 0, got %b", i,
|
||||
step2_ifaces[i].data);
|
||||
$stop;
|
||||
end
|
||||
if (step2_ifaces[i].value !== 8'hAA) begin
|
||||
$display("%%Error: step2_ifaces[%0d].value should be 0xAA, got 0x%02x", i, step2_ifaces[i].value);
|
||||
$display("%%Error: step2_ifaces[%0d].value should be 0xAA, got 0x%02x", i,
|
||||
step2_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -311,20 +326,25 @@ module t (/*AUTOARG*/
|
|||
for (int i = 0; i < 8; i++) begin
|
||||
if (i % 2 == 0) begin
|
||||
if (step2d_ifaces[i].data !== 1'b1) begin
|
||||
$display("%%Error: step2d_ifaces[%0d].data should be 1, got %b", i, step2d_ifaces[i].data);
|
||||
$display("%%Error: step2d_ifaces[%0d].data should be 1, got %b", i,
|
||||
step2d_ifaces[i].data);
|
||||
$stop;
|
||||
end
|
||||
if (step2d_ifaces[i].value !== 8'(i)) begin
|
||||
$display("%%Error: step2d_ifaces[%0d].value should be %0d, got %0d", i, i, step2d_ifaces[i].value);
|
||||
$display("%%Error: step2d_ifaces[%0d].value should be %0d, got %0d", i, i,
|
||||
step2d_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
end
|
||||
else begin
|
||||
if (step2d_ifaces[i].data !== 1'b0) begin
|
||||
$display("%%Error: step2d_ifaces[%0d].data should be 0, got %b", i, step2d_ifaces[i].data);
|
||||
$display("%%Error: step2d_ifaces[%0d].data should be 0, got %b", i,
|
||||
step2d_ifaces[i].data);
|
||||
$stop;
|
||||
end
|
||||
if (step2d_ifaces[i].value !== 8'hBB) begin
|
||||
$display("%%Error: step2d_ifaces[%0d].value should be 0xBB, got 0x%02x", i, step2d_ifaces[i].value);
|
||||
$display("%%Error: step2d_ifaces[%0d].value should be 0xBB, got 0x%02x", i,
|
||||
step2d_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -344,7 +364,8 @@ module t (/*AUTOARG*/
|
|||
$stop;
|
||||
end
|
||||
if (rev_ifaces[i].value !== 8'(N - 1 - i)) begin
|
||||
$display("%%Error: rev_ifaces[%0d].value should be %0d, got %0d", i, N-1-i, rev_ifaces[i].value);
|
||||
$display("%%Error: rev_ifaces[%0d].value should be %0d, got %0d", i, N - 1 - i,
|
||||
rev_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -356,7 +377,8 @@ module t (/*AUTOARG*/
|
|||
$stop;
|
||||
end
|
||||
if (nzb_ifaces[i].value !== 8'(i)) begin
|
||||
$display("%%Error: nzb_ifaces[%0d].value should be %0d, got %0d", i, i, nzb_ifaces[i].value);
|
||||
$display("%%Error: nzb_ifaces[%0d].value should be %0d, got %0d", i, i,
|
||||
nzb_ifaces[i].value);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@ interface simple_bad_if;
|
|||
logic [7:0] value;
|
||||
endinterface
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
module t ( /*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
localparam N = 4;
|
||||
|
||||
simple_bad_if ifaces [N-1:0] ();
|
||||
simple_bad_if ifaces[N-1:0] ();
|
||||
|
||||
// BAD: Loop with runtime-variable bound - not unrollable, so the
|
||||
// interface array index cannot be resolved to a constant.
|
||||
|
|
|
|||
|
|
@ -1,43 +1,43 @@
|
|||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:26:13: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd),
|
||||
| ^~~~~~
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:26:15: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
26 | output .ch0_wr(ch[0].wr),
|
||||
| ^~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: t/t_interface_modport_expr_array.v:26:13: Modport item not found: 'ch0_wr'
|
||||
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd),
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:26:15: Modport item not found: 'ch0_wr'
|
||||
26 | output .ch0_wr(ch[0].wr),
|
||||
| ^~~~~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:26:38: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd),
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:26:38: Modport item not found: 'ch0_rd'
|
||||
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd),
|
||||
| ^~~~~~
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:27:13: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd)
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:27:13: Modport item not found: 'ch1_wr'
|
||||
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd)
|
||||
| ^~~~~~
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:27:38: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd)
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:27:38: Modport item not found: 'ch1_rd'
|
||||
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd)
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:33:29: Can't find definition of 'ch0_wr' in dotted variable/method: 'port.ch0_wr'
|
||||
33 | assign port.ch0_rd = port.ch0_wr + 8'h10;
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:27:14: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
27 | input .ch0_rd(ch[0].rd),
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:27:14: Modport item not found: 'ch0_rd'
|
||||
27 | input .ch0_rd(ch[0].rd),
|
||||
| ^~~~~~
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:28:15: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
28 | output .ch1_wr(ch[1].wr),
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:28:15: Modport item not found: 'ch1_wr'
|
||||
28 | output .ch1_wr(ch[1].wr),
|
||||
| ^~~~~~
|
||||
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:29:14: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
|
||||
29 | input .ch1_rd(ch[1].rd)
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:29:14: Modport item not found: 'ch1_rd'
|
||||
29 | input .ch1_rd(ch[1].rd)
|
||||
| ^~~~~~
|
||||
%Error: t/t_interface_modport_expr_array.v:37:29: Can't find definition of 'ch0_wr' in dotted variable/method: 'port.ch0_wr'
|
||||
37 | assign port.ch0_rd = port.ch0_wr + 8'h10;
|
||||
| ^~~~~~
|
||||
... Known scopes under 'port': <no instances found>
|
||||
%Error: t/t_interface_modport_expr_array.v:33:15: Can't find definition of 'ch0_rd' in dotted variable/method: 'port.ch0_rd'
|
||||
33 | assign port.ch0_rd = port.ch0_wr + 8'h10;
|
||||
%Error: t/t_interface_modport_expr_array.v:37:15: Can't find definition of 'ch0_rd' in dotted variable/method: 'port.ch0_rd'
|
||||
37 | assign port.ch0_rd = port.ch0_wr + 8'h10;
|
||||
| ^~~~~~
|
||||
... Known scopes under 'port': <no instances found>
|
||||
%Error: t/t_interface_modport_expr_array.v:34:29: Can't find definition of 'ch1_wr' in dotted variable/method: 'port.ch1_wr'
|
||||
34 | assign port.ch1_rd = port.ch1_wr + 8'h20;
|
||||
%Error: t/t_interface_modport_expr_array.v:38:29: Can't find definition of 'ch1_wr' in dotted variable/method: 'port.ch1_wr'
|
||||
38 | assign port.ch1_rd = port.ch1_wr + 8'h20;
|
||||
| ^~~~~~
|
||||
... Known scopes under 'port': <no instances found>
|
||||
%Error: t/t_interface_modport_expr_array.v:34:15: Can't find definition of 'ch1_rd' in dotted variable/method: 'port.ch1_rd'
|
||||
34 | assign port.ch1_rd = port.ch1_wr + 8'h20;
|
||||
%Error: t/t_interface_modport_expr_array.v:38:15: Can't find definition of 'ch1_rd' in dotted variable/method: 'port.ch1_rd'
|
||||
38 | assign port.ch1_rd = port.ch1_wr + 8'h20;
|
||||
| ^~~~~~
|
||||
... Known scopes under 'port': <no instances found>
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -19,25 +19,29 @@ interface base_if;
|
|||
endinterface
|
||||
|
||||
interface container_if;
|
||||
base_if ch[2]();
|
||||
base_if ch[2] ();
|
||||
|
||||
// Modport expressions accessing arrayed interface instances
|
||||
modport mp(
|
||||
output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd),
|
||||
output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd)
|
||||
output .ch0_wr(ch[0].wr),
|
||||
input .ch0_rd(ch[0].rd),
|
||||
output .ch1_wr(ch[1].wr),
|
||||
input .ch1_rd(ch[1].rd)
|
||||
);
|
||||
endinterface
|
||||
|
||||
module consumer(container_if.mp port);
|
||||
module consumer (
|
||||
container_if.mp port
|
||||
);
|
||||
// Access through modport expression virtual ports
|
||||
assign port.ch0_rd = port.ch0_wr + 8'h10;
|
||||
assign port.ch1_rd = port.ch1_wr + 8'h20;
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
container_if cont();
|
||||
container_if cont ();
|
||||
|
||||
consumer m_cons(.port(cont));
|
||||
consumer m_cons (.port(cont));
|
||||
|
||||
initial begin
|
||||
cont.ch[0].wr = 8'hA0;
|
||||
|
|
|
|||
|
|
@ -22,13 +22,17 @@ interface if_a;
|
|||
endinterface
|
||||
|
||||
// Leaf module: uses modport expression virtual ports
|
||||
module a_leaf(if_a.mp port);
|
||||
module a_leaf (
|
||||
if_a.mp port
|
||||
);
|
||||
assign port.data_out = port.data_in + 8'h10;
|
||||
endmodule
|
||||
|
||||
// Mid-level module: passes interface down
|
||||
module a_mid(if_a.mp port);
|
||||
a_leaf u_leaf(.port(port));
|
||||
module a_mid (
|
||||
if_a.mp port
|
||||
);
|
||||
a_leaf u_leaf (.port(port));
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -41,16 +45,22 @@ interface if_b;
|
|||
modport mp(input .alpha(x), output .beta(y));
|
||||
endinterface
|
||||
|
||||
module b_leaf(if_b.mp port);
|
||||
module b_leaf (
|
||||
if_b.mp port
|
||||
);
|
||||
assign port.beta = port.alpha ^ 16'hFFFF;
|
||||
endmodule
|
||||
|
||||
module b_mid(if_b.mp port);
|
||||
b_leaf u_leaf(.port(port));
|
||||
module b_mid (
|
||||
if_b.mp port
|
||||
);
|
||||
b_leaf u_leaf (.port(port));
|
||||
endmodule
|
||||
|
||||
module b_top_wrap(if_b.mp port);
|
||||
b_mid u_mid(.port(port));
|
||||
module b_top_wrap (
|
||||
if_b.mp port
|
||||
);
|
||||
b_mid u_mid (.port(port));
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -62,17 +72,21 @@ interface if_c_inner;
|
|||
endinterface
|
||||
|
||||
interface if_c_outer;
|
||||
if_c_inner inner();
|
||||
if_c_inner inner ();
|
||||
modport mp(output .w(inner.val), input .r(inner.val));
|
||||
endinterface
|
||||
|
||||
module c_leaf(if_c_outer.mp port);
|
||||
module c_leaf (
|
||||
if_c_outer.mp port
|
||||
);
|
||||
assign port.w = 8'hBE;
|
||||
wire [7:0] c_read = port.r;
|
||||
endmodule
|
||||
|
||||
module c_mid(if_c_outer.mp port);
|
||||
c_leaf u_leaf(.port(port));
|
||||
module c_mid (
|
||||
if_c_outer.mp port
|
||||
);
|
||||
c_leaf u_leaf (.port(port));
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -85,12 +99,16 @@ interface if_d;
|
|||
modport mp(input .vi(din), output .vo(dout));
|
||||
endinterface
|
||||
|
||||
module d_leaf(if_d.mp port);
|
||||
module d_leaf (
|
||||
if_d.mp port
|
||||
);
|
||||
assign port.vo = port.vi + 8'h01;
|
||||
endmodule
|
||||
|
||||
module d_mid(if_d.mp port);
|
||||
d_leaf u_leaf(.port(port));
|
||||
module d_mid (
|
||||
if_d.mp port
|
||||
);
|
||||
d_leaf u_leaf (.port(port));
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -100,20 +118,20 @@ endmodule
|
|||
module top;
|
||||
|
||||
// --- Scenario A ---
|
||||
if_a ifa();
|
||||
a_mid u_a(.port(ifa));
|
||||
if_a ifa ();
|
||||
a_mid u_a (.port(ifa));
|
||||
|
||||
// --- Scenario B ---
|
||||
if_b ifb();
|
||||
b_top_wrap u_b(.port(ifb));
|
||||
if_b ifb ();
|
||||
b_top_wrap u_b (.port(ifb));
|
||||
|
||||
// --- Scenario C ---
|
||||
if_c_outer ifc();
|
||||
c_mid u_c(.port(ifc));
|
||||
if_c_outer ifc ();
|
||||
c_mid u_c (.port(ifc));
|
||||
|
||||
// --- Scenario D ---
|
||||
if_d ifd();
|
||||
d_mid u_d(.port(ifd));
|
||||
if_d ifd ();
|
||||
d_mid u_d (.port(ifd));
|
||||
|
||||
initial begin
|
||||
// Scenario A: single-level hierarchy
|
||||
|
|
|
|||
|
|
@ -26,17 +26,21 @@ interface example_reg_if;
|
|||
endinterface
|
||||
|
||||
interface app_reg_if;
|
||||
base_reg_if base();
|
||||
example_reg_if example();
|
||||
base_reg_if base ();
|
||||
example_reg_if example ();
|
||||
|
||||
// Use modport expressions to expose nested interface signals
|
||||
modport host(
|
||||
output .base_wr(base.wr), input .base_rd(base.rd),
|
||||
output .example_wr(example.wr), input .example_rd(example.rd)
|
||||
output .base_wr(base.wr),
|
||||
input .base_rd(base.rd),
|
||||
output .example_wr(example.wr),
|
||||
input .example_rd(example.rd)
|
||||
);
|
||||
modport dev(
|
||||
input .base_wr(base.wr), output .base_rd(base.rd),
|
||||
input .example_wr(example.wr), output .example_rd(example.rd)
|
||||
input .base_wr(base.wr),
|
||||
output .base_rd(base.rd),
|
||||
input .example_wr(example.wr),
|
||||
output .example_rd(example.rd)
|
||||
);
|
||||
endinterface
|
||||
|
||||
|
|
@ -48,20 +52,19 @@ interface inner_if;
|
|||
endinterface
|
||||
|
||||
interface middle_if;
|
||||
inner_if inner();
|
||||
inner_if inner ();
|
||||
endinterface
|
||||
|
||||
interface outer_if;
|
||||
middle_if middle();
|
||||
middle_if middle ();
|
||||
|
||||
// 3-level deep modport expression
|
||||
modport mp(
|
||||
output .deep_out(middle.inner.data),
|
||||
input .deep_in(middle.inner.data)
|
||||
);
|
||||
modport mp(output .deep_out(middle.inner.data), input .deep_in(middle.inner.data));
|
||||
endinterface
|
||||
|
||||
module deep_consumer(outer_if.mp port);
|
||||
module deep_consumer (
|
||||
outer_if.mp port
|
||||
);
|
||||
assign port.deep_out = 8'hDE;
|
||||
// Verify reading through deep_in virtual port
|
||||
wire [7:0] deep_in_val = port.deep_in;
|
||||
|
|
@ -73,30 +76,29 @@ interface level1_if;
|
|||
endinterface
|
||||
|
||||
interface level2_if;
|
||||
level1_if l1();
|
||||
level1_if l1 ();
|
||||
endinterface
|
||||
|
||||
interface level3_if;
|
||||
level2_if l2();
|
||||
level2_if l2 ();
|
||||
endinterface
|
||||
|
||||
interface level4_if;
|
||||
level3_if l3();
|
||||
level3_if l3 ();
|
||||
|
||||
// 4-level deep modport expression
|
||||
modport mp(
|
||||
output .deep4_w(l3.l2.l1.val),
|
||||
input .deep4_r(l3.l2.l1.val)
|
||||
);
|
||||
modport mp(output .deep4_w(l3.l2.l1.val), input .deep4_r(l3.l2.l1.val));
|
||||
endinterface
|
||||
|
||||
module deep4_consumer(level4_if.mp port);
|
||||
module deep4_consumer (
|
||||
level4_if.mp port
|
||||
);
|
||||
assign port.deep4_w = 8'h4D;
|
||||
wire [7:0] deep4_read = port.deep4_r;
|
||||
endmodule
|
||||
|
||||
module app_consumer (
|
||||
app_reg_if.dev i_app_regs
|
||||
app_reg_if.dev i_app_regs
|
||||
);
|
||||
// Access through modport expression virtual ports
|
||||
assign i_app_regs.base_rd = i_app_regs.base_wr + 8'h1;
|
||||
|
|
@ -104,13 +106,13 @@ module app_consumer (
|
|||
endmodule
|
||||
|
||||
module top;
|
||||
app_reg_if app_regs();
|
||||
outer_if outer();
|
||||
level4_if lev4();
|
||||
app_reg_if app_regs ();
|
||||
outer_if outer ();
|
||||
level4_if lev4 ();
|
||||
|
||||
app_consumer m_app(.i_app_regs(app_regs));
|
||||
deep_consumer m_deep(.port(outer));
|
||||
deep4_consumer m_deep4(.port(lev4));
|
||||
app_consumer m_app (.i_app_regs(app_regs));
|
||||
deep_consumer m_deep (.port(outer));
|
||||
deep4_consumer m_deep4 (.port(lev4));
|
||||
|
||||
initial begin
|
||||
app_regs.base.wr = 8'hAB;
|
||||
|
|
|
|||
|
|
@ -10,45 +10,54 @@
|
|||
// - Multiple interface instances (same modport type, different data)
|
||||
// - Interface arrays
|
||||
|
||||
interface bus_if (input logic clk);
|
||||
interface bus_if (
|
||||
input logic clk
|
||||
);
|
||||
logic [7:0] data;
|
||||
modport slave (output data, input clk);
|
||||
modport slave(output data, input clk);
|
||||
endinterface
|
||||
|
||||
// l1 module with the actual logic
|
||||
module l1_mod (bus_if.slave bus);
|
||||
always_ff @(posedge bus.clk)
|
||||
bus.data <= 8'h5A;
|
||||
module l1_mod (
|
||||
bus_if.slave bus
|
||||
);
|
||||
always_ff @(posedge bus.clk) bus.data <= 8'h5A;
|
||||
endmodule
|
||||
|
||||
// l0 module wrapping l1 module
|
||||
module l0_mod (bus_if.slave bus);
|
||||
module l0_mod (
|
||||
bus_if.slave bus
|
||||
);
|
||||
l1_mod l1_inst (bus);
|
||||
endmodule
|
||||
|
||||
// Modules for testing multiple instances with same modport
|
||||
module mod_aa (bus_if.slave bus);
|
||||
module mod_aa (
|
||||
bus_if.slave bus
|
||||
);
|
||||
assign bus.data = 8'hAA;
|
||||
endmodule
|
||||
|
||||
module mod_bb (bus_if.slave bus);
|
||||
module mod_bb (
|
||||
bus_if.slave bus
|
||||
);
|
||||
assign bus.data = 8'hBB;
|
||||
endmodule
|
||||
|
||||
// Module for testing interface arrays
|
||||
module array_mod (bus_if.slave bus[2]);
|
||||
module array_mod (
|
||||
bus_if.slave bus[2]
|
||||
);
|
||||
always_ff @(posedge bus[0].clk) begin
|
||||
bus[0].data <= 8'hA0;
|
||||
bus[1].data <= 8'hA1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
module t (
|
||||
input clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
integer cyc = 0;
|
||||
|
||||
// Deep hierarchy test
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ function automatic void untouched_inout_unused_func(inout int untouched_inout_un
|
|||
endfunction
|
||||
|
||||
function automatic void driven_inout_unused_func(inout int driven_inout_unused_func_param);
|
||||
driven_inout_unused_func_param = 7;
|
||||
driven_inout_unused_func_param = 7;
|
||||
endfunction
|
||||
|
||||
function automatic void used_inout_unused_func(inout int used_inout_unused_func_param);
|
||||
$display(used_inout_unused_func_param);
|
||||
$display(used_inout_unused_func_param);
|
||||
endfunction
|
||||
|
||||
module t;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ endclass
|
|||
|
||||
class RandcSmall;
|
||||
randc bit [1:0] val; // 4 possible values: 0,1,2,3
|
||||
constraint c_exclude { val != 0; } // 3 valid values: 1,2,3
|
||||
constraint c_exclude {val != 0;} // 3 valid values: 1,2,3
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[4];
|
||||
|
|
@ -78,7 +78,7 @@ endclass
|
|||
// Test 3: Inheritance - parent randc with constraint, child inherits
|
||||
class RandcParent;
|
||||
randc bit [2:0] code; // 8 values: 0-7
|
||||
constraint c_positive { code > 0; } // 7 valid values: 1-7
|
||||
constraint c_positive {code > 0;} // 7 valid values: 1-7
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[8];
|
||||
|
|
@ -102,7 +102,7 @@ endclass
|
|||
|
||||
class RandcChild extends RandcParent;
|
||||
// Inherits randc code and c_positive constraint
|
||||
constraint c_upper { code <= 5; } // Further restrict: 1-5 (5 values)
|
||||
constraint c_upper {code <= 5;} // Further restrict: 1-5 (5 values)
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[8];
|
||||
|
|
@ -132,7 +132,7 @@ endclass
|
|||
// enforcement and that all valid values eventually appear rather than exact counts.
|
||||
class RandcModeSwitch;
|
||||
randc bit [1:0] x; // 4 values: 0-3
|
||||
constraint c_nonzero { x != 0; } // 3 valid values: 1,2,3
|
||||
constraint c_nonzero {x != 0;} // 3 valid values: 1,2,3
|
||||
|
||||
function void test_mode_switch;
|
||||
automatic int randomize_result;
|
||||
|
|
@ -182,14 +182,14 @@ endclass
|
|||
// so the solver domain matches the enum domain exactly.
|
||||
class RandcEnumConstrained;
|
||||
typedef enum bit [1:0] {
|
||||
RED = 0,
|
||||
RED = 0,
|
||||
GREEN = 1,
|
||||
BLUE = 2,
|
||||
BLUE = 2,
|
||||
WHITE = 3
|
||||
} color_t;
|
||||
|
||||
randc color_t color;
|
||||
constraint c_no_white { color != WHITE; } // 3 valid: RED, GREEN, BLUE
|
||||
constraint c_no_white {color != WHITE;} // 3 valid: RED, GREEN, BLUE
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[4] = '{0, 0, 0, 0};
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test: pre/post_randomize callbacks on nested rand class objects and inherited methods
|
||||
// Covers: IEEE 1800-2017 Section 18.4.1 recursive callback invocation
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
// Test: pre/post_randomize callbacks on nested rand class objects and inherited methods
|
||||
// Covers: IEEE 1800-2017 Section 18.4.1 recursive callback invocation
|
||||
|
||||
// --- Inherited callbacks (no override) ---
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ class Level3;
|
|||
int pre_count;
|
||||
int post_count;
|
||||
|
||||
constraint c_val { val inside {[10:200]}; }
|
||||
constraint c_val {val inside {[10 : 200]};}
|
||||
|
||||
function new();
|
||||
pre_count = 0;
|
||||
|
|
@ -122,7 +124,7 @@ class Level2;
|
|||
int pre_count;
|
||||
int post_count;
|
||||
|
||||
constraint c_val { val inside {[1:100]}; }
|
||||
constraint c_val {val inside {[1 : 100]};}
|
||||
|
||||
function new();
|
||||
l3 = new();
|
||||
|
|
@ -145,7 +147,7 @@ class Level1;
|
|||
int pre_count;
|
||||
int post_count;
|
||||
|
||||
constraint c_val { val inside {[50:150]}; }
|
||||
constraint c_val {val inside {[50 : 150]};}
|
||||
|
||||
function new();
|
||||
l2 = new();
|
||||
|
|
@ -193,7 +195,7 @@ module t;
|
|||
`checkd(r, 1);
|
||||
`checkd(obj.derived_pre_count, 1);
|
||||
`checkd(obj.derived_post_count, 1);
|
||||
`checkd(obj.pre_count, 0); // base NOT called (no super)
|
||||
`checkd(obj.pre_count, 0); // base NOT called (no super)
|
||||
`checkd(obj.post_count, 0); // base NOT called (no super)
|
||||
end
|
||||
|
||||
|
|
@ -202,9 +204,9 @@ module t;
|
|||
automatic DerivedOverridePostOnly obj = new;
|
||||
r = obj.randomize();
|
||||
`checkd(r, 1);
|
||||
`checkd(obj.pre_count, 1); // inherited pre_randomize called
|
||||
`checkd(obj.pre_count, 1); // inherited pre_randomize called
|
||||
`checkd(obj.derived_post_count, 1); // overridden post called
|
||||
`checkd(obj.post_count, 0); // base post NOT called (no super)
|
||||
`checkd(obj.post_count, 0); // base post NOT called (no super)
|
||||
end
|
||||
|
||||
// Test 5: Nested callbacks (3-level)
|
||||
|
|
@ -223,7 +225,7 @@ module t;
|
|||
// Test 6: Multiple randomizations
|
||||
begin
|
||||
automatic Level1 l1 = new;
|
||||
repeat(5) begin
|
||||
repeat (5) begin
|
||||
r = l1.randomize();
|
||||
`checkd(r, 1);
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@ class RandModeClass;
|
|||
rand int x;
|
||||
rand int y;
|
||||
|
||||
constraint c { x inside {[1:255]}; y inside {[1:255]}; }
|
||||
constraint c {
|
||||
x inside {[1 : 255]};
|
||||
y inside {[1 : 255]};
|
||||
}
|
||||
|
||||
task check_mode(string name, int actual, int expected);
|
||||
if (actual !== expected) begin
|
||||
|
|
|
|||
|
|
@ -1,25 +1,27 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module x;
|
||||
bit val = 0;
|
||||
bit ok = 0;
|
||||
|
||||
initial #1 begin
|
||||
val = 1;
|
||||
@(val);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
initial
|
||||
#1 begin
|
||||
val = 1;
|
||||
@(val);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial @(posedge val) begin
|
||||
val = 0;
|
||||
ok = 1;
|
||||
@(edge val);
|
||||
$stop;
|
||||
end
|
||||
initial
|
||||
@(posedge val) begin
|
||||
val = 0;
|
||||
ok = 1;
|
||||
@(edge val);
|
||||
$stop;
|
||||
end
|
||||
initial #10 $stop;
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -4,16 +4,18 @@
|
|||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test std::randomize() with associative array variables
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop;
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
// Test std::randomize() with associative array variables
|
||||
|
||||
module t_std_randomize_assoc;
|
||||
|
||||
// Associative array variables
|
||||
int assoc_int [int];
|
||||
bit [7:0] assoc_byte [string];
|
||||
int assoc_int[int];
|
||||
bit [7:0] assoc_byte[string];
|
||||
|
||||
initial begin
|
||||
// Test 1: std::randomize with int-keyed associative array (no constraints)
|
||||
|
|
|
|||
|
|
@ -4,19 +4,21 @@
|
|||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test std::randomize() with queue and dynamic array variables
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop;
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
// Test std::randomize() with queue and dynamic array variables
|
||||
|
||||
module t_std_randomize_queue;
|
||||
|
||||
// Queue variables
|
||||
bit [7:0] q8 [$];
|
||||
bit [31:0] q32 [$];
|
||||
bit [7:0] q8[$];
|
||||
bit [31:0] q32[$];
|
||||
|
||||
// Dynamic array variables
|
||||
bit [7:0] dyn8 [];
|
||||
bit [7:0] dyn8[];
|
||||
|
||||
int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
%Warning-CONSTRAINTIGN: t/t_std_randomize_unsup_unq_arr.v:10:39: Unsupported: Unique constraint in std::randomize() with {}
|
||||
: ... note: In instance 't'
|
||||
10 | if (!bit'(std::randomize(x) with {unique{x};}) || x[0] == x[1]) $stop;
|
||||
10 | if (!bit'(std::randomize(x) with {unique {x};}) || x[0] == x[1]) $stop;
|
||||
| ^~~~~~
|
||||
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
|
||||
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
module t;
|
||||
initial begin
|
||||
bit x[2];
|
||||
if (!bit'(std::randomize(x) with {unique{x};}) || x[0] == x[1]) $stop;
|
||||
if (!bit'(std::randomize(x) with {unique {x};}) || x[0] == x[1]) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro Ltd
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface sys_if;
|
||||
|
|
@ -13,12 +13,12 @@ interface axi_if;
|
|||
endinterface
|
||||
|
||||
class sys_config;
|
||||
virtual sys_if sys_vi;
|
||||
virtual sys_if sys_vi;
|
||||
endclass
|
||||
|
||||
class axi_agent_config;
|
||||
virtual axi_if axi_vi;
|
||||
sys_config cfg;
|
||||
virtual axi_if axi_vi;
|
||||
sys_config cfg;
|
||||
task start_clk();
|
||||
fork
|
||||
forever begin
|
||||
|
|
@ -38,8 +38,8 @@ class axi_agent_config;
|
|||
endclass
|
||||
|
||||
module axi_tb_top;
|
||||
sys_if sys_vi();
|
||||
axi_if axi_vi();
|
||||
sys_if sys_vi ();
|
||||
axi_if axi_vi ();
|
||||
assign axi_vi.clk = sys_vi.clk;
|
||||
sys_config a;
|
||||
axi_agent_config b;
|
||||
|
|
|
|||
Loading…
Reference in New Issue