forked from github/verilator
* Tests: Add a test to reproduce #3399 * Fix #3399. When reading an inout port in a module, it should refer the original inout port, not the generated MODTEMP.
This commit is contained in:
parent
f4fe10844b
commit
d20f22beb1
@ -385,7 +385,15 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
return newp;
|
||||
}
|
||||
AstNode* getEnp(AstNode* nodep) {
|
||||
if (!nodep->user1p()) {
|
||||
if (nodep->user1p()) {
|
||||
if (AstVarRef* const refp = VN_CAST(nodep, VarRef)) {
|
||||
if (refp->varp()->isIO()) {
|
||||
// When reading a tri-state port, we can always use the value
|
||||
// because such port will have resolution logic in upper module.
|
||||
return newAllZerosOrOnes(nodep, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// There's no select being built yet, so add what will become a
|
||||
// constant output enable driver of all 1's
|
||||
nodep->user1p(newAllZerosOrOnes(nodep, true));
|
||||
|
@ -47,6 +47,16 @@ int main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
tb->SEL = tb->A = tb->B = 0;
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
tb->clk = 0;
|
||||
tb->eval();
|
||||
tb->clk = 1;
|
||||
tb->eval();
|
||||
if (tb->done) break;
|
||||
if (i + 1 == 256) pass = false;
|
||||
}
|
||||
|
||||
if (pass) {
|
||||
VL_PRINTF("*-* All Finished *-*\n");
|
||||
|
@ -4,10 +4,12 @@
|
||||
// without warranty, 2008 by Lane Brooks.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module top (input A, input B, input SEL, output Y1, output Y2, output Z);
|
||||
module top (input A, input B, input SEL, input clk, output Y1, output Y2, output Z, output done);
|
||||
io io1(.A(A), .OE( SEL), .Z(Z), .Y(Y1));
|
||||
pass io2(.A(B), .OE(!SEL), .Z(Z), .Y(Y2));
|
||||
assign Z = 1'bz;
|
||||
|
||||
pad_checker u_pad_checker(.clk(clk), .done(done));
|
||||
endmodule
|
||||
|
||||
module pass (input A, input OE, inout Z, output Y);
|
||||
@ -27,3 +29,84 @@ module io_noinline (input A, input OE, inout Z, output Y);
|
||||
assign Y = Z;
|
||||
assign Z = 1'bz;
|
||||
endmodule
|
||||
|
||||
|
||||
module pad_checker(input wire clk, output wire done);
|
||||
wire tri_pad;
|
||||
reg [1:0] ie = '0;
|
||||
reg [1:0] oe = '0;
|
||||
reg [1:0] in = '0;
|
||||
wire out_0, out_1;
|
||||
|
||||
pad u_pad0(.pad(tri_pad), .ie(ie[0]), .oe(oe[0]), .to_pad(in[0]), .from_pad(out_0));
|
||||
pad u_pad1(.pad(tri_pad), .ie(ie[1]), .oe(oe[1]), .to_pad(in[1]), .from_pad(out_1));
|
||||
|
||||
wire bin_pad_in_0, bin_pad_in_1;
|
||||
wire bin_pad_01, bin_pad_10;
|
||||
wire bin_pad_en_01, bin_pad_en_10;
|
||||
wire bin_from_pad_out_0, bin_from_pad_out_1;
|
||||
wire bin_from_pad_en_0, bin_from_pad_en_1;
|
||||
|
||||
// Expectation model that simulates how Verilator solves tri-state
|
||||
pad_binary u_pad_bin_0(.pad_in(bin_pad_in_0),
|
||||
.pad_out(bin_pad_01),
|
||||
.pad_en(bin_pad_en_01),
|
||||
.ie(ie[0]), .oe(oe[0]),
|
||||
.to_pad(in[0]),
|
||||
.from_pad_out(bin_from_pad_out_0),
|
||||
.from_pad_en(bin_from_pad_en_0));
|
||||
|
||||
pad_binary u_pad_bin_1(.pad_in(bin_pad_in_1),
|
||||
.pad_out(bin_pad_10),
|
||||
.pad_en(bin_pad_en_10),
|
||||
.ie(ie[1]),
|
||||
.oe(oe[1]),
|
||||
.to_pad(in[1]),
|
||||
.from_pad_out(bin_from_pad_out_1),
|
||||
.from_pad_en(bin_from_pad_en_1));
|
||||
|
||||
assign bin_pad_in_0 = (bin_pad_en_10 & bin_pad_10) | (bin_pad_en_01 & bin_pad_01);
|
||||
assign bin_pad_in_1 = (bin_pad_en_01 & bin_pad_01) | (bin_pad_en_10 & bin_pad_10);
|
||||
|
||||
|
||||
logic done_reg = 0;
|
||||
assign done = done_reg;
|
||||
always @(posedge clk) begin
|
||||
if ({ie, oe, in} == 6'b111111) begin
|
||||
done_reg <= 1'b1;
|
||||
end else begin
|
||||
if (out_0 != bin_from_pad_out_0) begin
|
||||
$display("ie:%b oe:%b in:%b out0 act:%b exp:%b", ie[0], oe[0], in[0], out_0, bin_from_pad_out_0);
|
||||
$stop;
|
||||
end
|
||||
if (out_1 != bin_from_pad_out_1) begin
|
||||
$display("ie:%b oe:%b in:%b out1 act:%b exp:%b", ie[1], oe[1], in[1], out_1, bin_from_pad_out_1);
|
||||
$stop;
|
||||
end
|
||||
// Let's try all combination
|
||||
{ie, oe, in} <= {ie, oe, in} + 1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module pad(inout wire pad, input wire ie, input wire oe, input wire to_pad, output wire from_pad);
|
||||
|
||||
assign pad = oe ? to_pad : 1'bz;
|
||||
assign from_pad = ie ? pad : 1'bz;
|
||||
endmodule
|
||||
|
||||
module pad_binary(input wire pad_in,
|
||||
output wire pad_out,
|
||||
output wire pad_en,
|
||||
input wire ie,
|
||||
input wire oe,
|
||||
input wire to_pad,
|
||||
output from_pad_out,
|
||||
output wire from_pad_en);
|
||||
|
||||
assign pad_out = oe & to_pad;
|
||||
assign pad_en = oe;
|
||||
assign from_pad_out = ie & ((oe & to_pad) | pad_in);
|
||||
assign from_pad_en = ie;
|
||||
endmodule
|
||||
|
Loading…
Reference in New Issue
Block a user