Commit 2b377cef by Zachary Snow

interface and instance array support

- support for interface instance arrays
- support for interface-using module instance arrays
- support for modport array bindings
- fix modport bindings shadowed in nested instances
parent 8eac9b01
interface Interface(i);
input i;
logic v;
logic o;
task tick;
$display("I i = %b, v = %b, o = %b", i, v, o);
endtask
initial $display("Hello I'm Interface!");
modport ModportA(
input .i(i ^ 1'b1),
output v
);
modport ModportB(
input .i(i),
output .v(o)
);
endinterface
module ModuleA(i);
parameter flip = 0;
Interface i;
assign i.v = i.i ^ 1'(flip);
task tick;
$display("A i.v = %b", i.v);
endtask
initial $display("Hello I'm ModuleA %0d!", flip);
endmodule
module ModuleASet(is);
parameter flip2 = 0;
parameter flip1 = 0;
parameter flip0 = 0;
Interface is [2:0];
assign is[2].v = is[2].i ^ 1'(flip2);
assign is[1].v = is[1].i ^ 1'(flip1);
assign is[0].v = is[0].i ^ 1'(flip0);
task tick;
$display("AS i.v = %b", is[2].v);
$display("AS i.v = %b", is[1].v);
$display("AS i.v = %b", is[0].v);
endtask
initial begin
$display("Hello I'm ModuleASet %0d %0d %0d!", flip2, flip1, flip0);
end
endmodule
module ModuleCSet(is);
parameter flip2 = 0;
parameter flip1 = 0;
parameter flip0 = 0;
Interface.ModportB is [2:0];
assign is[2].v = is[2].i ^ 1'(flip2);
assign is[1].v = is[1].i ^ 1'(flip1);
assign is[0].v = is[0].i ^ 1'(flip0);
task tick;
$display("CS i.v = %b", is[2].v);
$display("CS i.v = %b", is[1].v);
$display("CS i.v = %b", is[0].v);
endtask
initial begin
$display("Hello I'm ModuleCSet %0d %0d %0d!", flip2, flip1, flip0);
end
endmodule
module ModuleB(is);
parameter WIDTH = 1;
Interface is [WIDTH-1:0];
logic [WIDTH-1:0] i_concat;
logic [WIDTH-1:0] v_concat;
for (genvar i = WIDTH - 1; i >= 0; i = i - 1) begin
assign i_concat[i] = is[i].i;
assign v_concat[i] = is[i].v;
end
task tick;
$display("B i_concat = %b, v_concat = %b", i_concat, v_concat);
bn.tick;
endtask
initial $display("Hello I'm ModuleB %0d!", WIDTH);
ModuleBNested #(WIDTH) bn(is);
endmodule
module ModuleBNested(is);
parameter WIDTH = 1;
Interface is [WIDTH-1:0];
logic [WIDTH-1:0] i_concat;
logic [WIDTH-1:0] v_concat;
for (genvar i = WIDTH - 1; i >= 0; i = i - 1) begin
assign i_concat[i] = is[i].i;
assign v_concat[i] = is[i].v;
end
task tick;
$display("BN i_concat = %b, v_concat = %b", i_concat, v_concat);
endtask
endmodule
module top;
logic inp;
Interface intfX[2:0](inp);
ModuleA #(0) xa2(intfX[2]);
ModuleA #(1) xa1(intfX[1]);
ModuleA #(1) xa0(intfX[0]);
ModuleB #(3) xb20(intfX[2:0]);
ModuleB #(2) xb21(intfX[2:1]);
ModuleB #(1) xb22(intfX[2:2]);
ModuleB #(1) xb11(intfX[1:1]);
ModuleB #(1) xb00(intfX[0:0]);
ModuleB #(3) xbf(intfX);
ModuleASet #(1, 1, 0) xs(intfX[2:0].ModportB);
Interface intfY[2:0](inp);
ModuleA #(0) ya2(intfY[2].ModportA);
ModuleA #(1) ya1(intfY[1].ModportA);
ModuleA #(1) ya0(intfY[0].ModportA);
ModuleB #(3) yb20(intfY[2:0].ModportA);
ModuleB #(2) yb21(intfY[2:1].ModportA);
ModuleB #(1) yb22(intfY[2:2].ModportA);
ModuleB #(1) yb11(intfY[1:1].ModportA);
ModuleB #(1) yb00(intfY[0:0].ModportA);
ModuleB #(3) ybf(intfY.ModportA);
ModuleCSet #(0, 0, 1) ys(intfY[2:0]);
initial begin
inp = 0; tick;
inp = 1; tick;
inp = 0; tick;
inp = 1; tick;
end
task tick;
#1;
intfX[2].tick;
intfX[1].tick;
intfX[0].tick;
xa2.tick;
xa1.tick;
xa0.tick;
xb20.tick;
xb21.tick;
xb22.tick;
xb11.tick;
xb00.tick;
xbf.tick;
xs.tick;
intfY[2].tick;
intfY[1].tick;
intfY[0].tick;
ya2.tick;
ya1.tick;
ya0.tick;
yb20.tick;
yb21.tick;
yb22.tick;
yb11.tick;
yb00.tick;
ybf.tick;
ys.tick;
endtask
endmodule
module top;
reg inp;
initial begin
$display("Hello I'm Interface!");
$display("Hello I'm Interface!");
$display("Hello I'm Interface!");
$display("Hello I'm ModuleA 0!");
$display("Hello I'm ModuleA 1!");
$display("Hello I'm ModuleA 1!");
$display("Hello I'm ModuleB 3!");
$display("Hello I'm ModuleB 2!");
$display("Hello I'm ModuleB 1!");
$display("Hello I'm ModuleB 1!");
$display("Hello I'm ModuleB 1!");
$display("Hello I'm ModuleB 3!");
$display("Hello I'm ModuleASet 1 1 0!");
$display("Hello I'm Interface!");
$display("Hello I'm Interface!");
$display("Hello I'm Interface!");
$display("Hello I'm ModuleA 0!");
$display("Hello I'm ModuleA 1!");
$display("Hello I'm ModuleA 1!");
$display("Hello I'm ModuleB 3!");
$display("Hello I'm ModuleB 2!");
$display("Hello I'm ModuleB 1!");
$display("Hello I'm ModuleB 1!");
$display("Hello I'm ModuleB 1!");
$display("Hello I'm ModuleB 3!");
$display("Hello I'm ModuleCSet 0 0 1!");
inp = 0; tick;
inp = 1; tick;
inp = 0; tick;
inp = 1; tick;
end
task tick; begin
#1;
$display("I i = %b, v = %b, o = %b", inp, inp, inp ^ 1'b1);
$display("I i = %b, v = %b, o = %b", inp, inp ^ 1'b1, inp ^ 1'b1);
$display("I i = %b, v = %b, o = %b", inp, inp ^ 1'b1, inp);
$display("A i.v = %b", inp);
$display("A i.v = %b", inp ^ 1'b1);
$display("A i.v = %b", inp ^ 1'b1);
$display("B i_concat = %b, v_concat = %b", {3 {inp}}, {inp, inp ^ 1'b1, inp ^ 1'b1});
$display("BN i_concat = %b, v_concat = %b", {3 {inp}}, {inp, inp ^ 1'b1, inp ^ 1'b1});
$display("B i_concat = %b, v_concat = %b", {2 {inp}}, {inp, inp ^ 1'b1});
$display("BN i_concat = %b, v_concat = %b", {2 {inp}}, {inp, inp ^ 1'b1});
$display("B i_concat = %b, v_concat = %b", {1 {inp}}, inp);
$display("BN i_concat = %b, v_concat = %b", {1 {inp}}, inp);
$display("B i_concat = %b, v_concat = %b", {1 {inp}}, inp ^ 1'b1);
$display("BN i_concat = %b, v_concat = %b", {1 {inp}}, inp ^ 1'b1);
$display("B i_concat = %b, v_concat = %b", {1 {inp}}, inp ^ 1'b1);
$display("BN i_concat = %b, v_concat = %b", {1 {inp}}, inp ^ 1'b1);
$display("B i_concat = %b, v_concat = %b", {3 {inp}}, {inp, inp ^ 1'b1, inp ^ 1'b1});
$display("BN i_concat = %b, v_concat = %b", {3 {inp}}, {inp, inp ^ 1'b1, inp ^ 1'b1});
$display("AS i.v = %b", inp ^ 1'b1);
$display("AS i.v = %b", inp ^ 1'b1);
$display("AS i.v = %b", inp);
$display("I i = %b, v = %b, o = %b", inp, inp ^ 1'b1, inp);
$display("I i = %b, v = %b, o = %b", inp, inp, inp);
$display("I i = %b, v = %b, o = %b", inp, inp, inp ^ 1'b1);
$display("A i.v = %b", inp ^ 1'b1);
$display("A i.v = %b", inp);
$display("A i.v = %b", inp);
$display("B i_concat = %b, v_concat = %b", {3 {~inp}}, {inp ^ 1'b1, inp, inp});
$display("BN i_concat = %b, v_concat = %b", {3 {~inp}}, {inp ^ 1'b1, inp, inp});
$display("B i_concat = %b, v_concat = %b", {2 {~inp}}, {inp ^ 1'b1, inp});
$display("BN i_concat = %b, v_concat = %b", {2 {~inp}}, {inp ^ 1'b1, inp});
$display("B i_concat = %b, v_concat = %b", {1 {~inp}}, inp ^ 1'b1);
$display("BN i_concat = %b, v_concat = %b", {1 {~inp}}, inp ^ 1'b1);
$display("B i_concat = %b, v_concat = %b", {1 {~inp}}, inp);
$display("BN i_concat = %b, v_concat = %b", {1 {~inp}}, inp);
$display("B i_concat = %b, v_concat = %b", {1 {~inp}}, inp);
$display("BN i_concat = %b, v_concat = %b", {1 {~inp}}, inp);
$display("B i_concat = %b, v_concat = %b", {3 {~inp}}, {inp ^ 1'b1, inp, inp});
$display("BN i_concat = %b, v_concat = %b", {3 {~inp}}, {inp ^ 1'b1, inp, inp});
$display("CS i.v = %b", inp);
$display("CS i.v = %b", inp);
$display("CS i.v = %b", inp ^ 1'b1);
end
endtask
endmodule
interface Interface;
logic x;
endinterface
module top;
Interface intfs[3:2][8:5]();
for (genvar x = 2; x <= 3; x = x + 1)
for (genvar y = 5; y <= 8; y = y + 1)
assign intfs[x][y].x = '1;
endmodule
module top;
generate
if (1) begin : block
wire [3:2][8:5] xs;
genvar x, y;
for (x = 2; x <= 3; x = x + 1)
for (y = 5; y <= 8; y = y + 1)
assign xs[x][y] = 1'b1;
end
endgenerate
endmodule
`define SHADOW \
integer i; \
Interface intfs[1:0]();
interface Interface;
integer x;
modport ModportA(input .x(x + 1));
modport ModportB(input .x(x + 2));
endinterface
module ModuleA(intf);
Interface intf;
`SHADOW
initial #1 $display("ModuleA got %0d", intf.x);
ModuleN n(intf);
endmodule
module ModuleB(intf);
Interface.ModportA intf;
`SHADOW
initial #1 $display("ModuleB got %0d", intf.x);
ModuleN n(intf);
endmodule
module ModuleC(intf);
Interface.ModportB intf;
`SHADOW
initial #1 $display("ModuleC got %0d", intf.x);
ModuleN n(intf);
endmodule
module ModuleN(intf);
Interface intf;
`SHADOW
initial #1 $display("ModuleN got %0d", intf.x);
endmodule
module top;
Interface intfs[4:8]();
`define LOOP for (genvar i = 4; i <= 8; ++i)
`LOOP initial intfs[i].x = i ** 2;
`LOOP ModuleA a1(intfs[i]);
`LOOP ModuleA a2(intfs[i].ModportA);
`LOOP ModuleA a3(intfs[i].ModportB);
`LOOP ModuleB b1(intfs[i]);
`LOOP ModuleB b2(intfs[i].ModportA);
`LOOP ModuleC c1(intfs[i]);
`LOOP ModuleC c2(intfs[i].ModportB);
endmodule
module top;
genvar i;
generate
initial #1;
`define PRINT(X, offset) \
for (i = 4; i <= 8; i = i + 1) \
initial begin \
$display(`"Module``X got %0d`", i ** 2 + offset); \
$display("ModuleN got %0d", i ** 2 + offset); \
end
`PRINT(A, 0)
`PRINT(A, 1)
`PRINT(A, 2)
`PRINT(B, 1)
`PRINT(B, 1)
`PRINT(C, 2)
`PRINT(C, 2)
endgenerate
endmodule
interface Interface;
logic x;
endinterface
module Module(intfs);
parameter LEFT = 0;
parameter RIGHT = 0;
Interface intfs[LEFT:RIGHT];
logic [LEFT:RIGHT] xs;
localparam LO = LEFT > RIGHT ? RIGHT : LEFT;
localparam HI = LEFT > RIGHT ? LEFT : RIGHT;
for (genvar i = LO; i <= HI; i = i + 1) begin
// intentional shadowing of dimension constants
localparam LEFT = 0;
localparam RIGHT = 0;
assign xs[i] = intfs[i].x;
end
endmodule
module Instance();
parameter LEFT = 0;
parameter RIGHT = 0;
parameter INNER_LEFT = 0;
parameter INNER_RIGHT = 0;
parameter INNER_OFFSET = 0;
reg [LEFT:RIGHT] xs;
localparam DIR = LEFT >= RIGHT ? -1 : 1;
Interface intfs[LEFT:RIGHT]();
generate
genvar i;
for (i = LEFT; i <= RIGHT; i = i + DIR)
assign intfs[i].x = xs[i];
endgenerate
// intentional name collision with localparams in the module
localparam LO = INNER_LEFT >= INNER_RIGHT ? INNER_RIGHT : INNER_LEFT;
localparam HI = INNER_LEFT >= INNER_RIGHT ? INNER_LEFT : INNER_RIGHT;
localparam LEN = HI - LO + 1;
Module #(INNER_LEFT + INNER_OFFSET, INNER_RIGHT + INNER_OFFSET)
l(intfs[INNER_LEFT:INNER_RIGHT]);
Module #(INNER_LEFT + INNER_OFFSET, INNER_RIGHT + INNER_OFFSET)
m(intfs[LO+:LEN]);
Module #(INNER_LEFT + INNER_OFFSET, INNER_RIGHT + INNER_OFFSET)
n(intfs[HI-:LEN]);
endmodule
module Module(xs);
parameter LEFT = 0;
parameter RIGHT = 0;
input wire [LEFT:RIGHT] xs;
endmodule
module Instance();
parameter LEFT = 0;
parameter RIGHT = 0;
parameter INNER_LEFT = 0;
parameter INNER_RIGHT = 0;
parameter INNER_OFFSET = 0;
reg [LEFT:RIGHT] xs;
localparam LO = INNER_LEFT >= INNER_RIGHT ? INNER_RIGHT : INNER_LEFT;
localparam HI = INNER_LEFT >= INNER_RIGHT ? INNER_LEFT : INNER_RIGHT;
localparam LEN = HI - LO + 1;
Module #(INNER_LEFT + INNER_OFFSET, INNER_RIGHT + INNER_OFFSET)
l(xs[INNER_LEFT:INNER_RIGHT]);
Module #(INNER_LEFT + INNER_OFFSET, INNER_RIGHT + INNER_OFFSET)
m(xs[LO+:LEN]);
Module #(INNER_LEFT + INNER_OFFSET, INNER_RIGHT + INNER_OFFSET)
n(xs[HI-:LEN]);
endmodule
module Test();
parameter BASE = 0;
parameter SIZE = 0;
parameter DIR = 0;
localparam LEFT = BASE;
localparam RIGHT = BASE + DIR * (SIZE - 1);
genvar left, right, offset;
generate
for (left = LEFT + SIZE; left <= RIGHT + SIZE; left = left + 1)
for (right = LEFT + SIZE; right <= RIGHT + SIZE; right = right + 1)
if ((left - right) * DIR <= 0)
for (offset = -2 + SIZE; offset <= 2 + SIZE; offset = offset + 1)
begin
Instance #(
LEFT, RIGHT,
left - SIZE, right - SIZE, offset - SIZE
) i();
initial begin
i.xs = 1;
while (i.xs != 0) begin
#1;
$display("LEFT=%2d RIGHT=%2d INNER_LEFT=%2d INNER_RIGHT=%2d INNER_OFFSET=%2d i.xs=%b i.l.xs=%b i.m.xs=%b i.n.xs=%b",
LEFT, RIGHT,
left - SIZE, right - SIZE, offset - SIZE,
i.xs, i.l.xs, i.m.xs, i.n.xs);
i.xs = i.xs + 1;
end
end
end
endgenerate
endmodule
module Suite();
parameter SIZE = 0;
genvar base;
generate
for (base = -2 + SIZE; base <= 2 + SIZE; base = base + 1) begin
Test #(base - SIZE, SIZE, -1) b();
Test #(base - SIZE, SIZE, 1) f();
end
endgenerate
endmodule
module top;
Suite #(2) s2();
Suite #(3) s3();
Suite #(4) s4();
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment