Fix interface functions returning wrong parameters, bug996.

This commit is contained in:
Wilson Snyder 2017-05-18 22:49:17 -04:00
parent b032fce962
commit 7fb29621c3
3 changed files with 77 additions and 14 deletions

View File

@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Add warning on mis-sized literal, bug1156. [Todd Strader]
**** Fix interface functions returning wrong parameters, bug996. [Todd Strader]
**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson]
**** Fix --assert with complex case statements, bug1164. [Enzo Chi]

View File

@ -283,7 +283,59 @@ private:
virtual void visit(AstVarRef* nodep) {
if (nodep->varp()) nodep->varp()->iterate(*this);
}
bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) {
for (; candp; candp = candp->nextp()) {
if (nodep->name() == candp->name()) {
if (AstVar* varp = candp->castVar()) {
UINFO(9,"Found interface parameter: "<<varp<<endl);
nodep->varp(varp);
return true;
} else if (AstPin* pinp = candp->castPin()) {
UINFO(9,"Found interface parameter: "<<pinp<<endl);
if (!pinp->exprp()) pinp->v3fatalSrc("Interface parameter pin missing expression");
nodep->replaceWith(pinp->exprp()->cloneTree(false)); VL_DANGLING(nodep);
return true;
}
}
}
return false;
}
virtual void visit(AstVarXRef* nodep) {
// Check to see if the scope is just an interface because interfaces are special
string dotted = nodep->dotted();
if (!dotted.empty() && nodep->varp() && nodep->varp()->isParam()) {
AstNode* backp = nodep;
while ((backp = backp->backp())) {
if (backp->castNodeModule()) {
UINFO(9,"Hit module boundary, done looking for interface"<<endl);
break;
}
if (backp->castVar()
&& backp->castVar()->isIfaceRef()
&& backp->castVar()->childDTypep()
&& backp->castVar()->childDTypep()->castIfaceRefDType()) {
AstIfaceRefDType* ifacerefp = backp->castVar()->childDTypep()->castIfaceRefDType();
// Interfaces passed in on the port map have ifaces
if (AstIface* ifacep = ifacerefp->ifacep()) {
if (dotted == backp->name()) {
UINFO(9,"Iface matching scope: "<<ifacep<<endl);
if (ifaceParamReplace(nodep, ifacep->stmtsp())) {
return;
}
}
}
// Interfaces declared in this module have cells
else if (AstCell* cellp = ifacerefp->cellp()) {
if (dotted == cellp->name()) {
UINFO(9,"Iface matching scope: "<<cellp<<endl);
if (ifaceParamReplace(nodep, cellp->paramsp())) {
return;
}
}
}
}
}
}
nodep->varp(NULL); // Needs relink, as may remove pointed-to var
}

View File

@ -22,6 +22,10 @@ interface test_if #(parameter integer FOO = 1);
endinterface // test_if
function integer identity (input integer x);
return x;
endfunction
module t (/*AUTOARG*/
// Inputs
@ -29,13 +33,22 @@ module t (/*AUTOARG*/
);
input clk;
test_if #( .FOO (5) ) the_interface ();
test_if #( .FOO (identity(5)) ) the_interface ();
testmod testmod_i (.clk (clk),
.intf (the_interface),
.intf_no_mp (the_interface)
);
localparam THE_TOP_FOO = the_interface.FOO;
initial begin
if (THE_TOP_FOO != 5) begin
$display("%%Error: THE_TOP_FOO = %0d", THE_TOP_FOO);
$stop;
end
end
endmodule
@ -46,30 +59,26 @@ module testmod
test_if intf_no_mp
);
`ifdef ELAB_TIME
localparam THE_FOO = intf.FOO;
// localparam THE_OTHER_FOO = intf_no_mp.FOO;
`endif
localparam THE_OTHER_FOO = intf_no_mp.FOO;
always @(posedge clk) begin
`ifdef ELAB_TIME
if (THE_FOO != 5) begin
$display("%%Error: THE_FOO = %0d", THE_FOO);
$stop;
end
// if (THE_OTHER_FOO != 5) begin
// $display("%%Error: THE_OTHER_FOO = %0d", THE_OTHER_FOO);
// $stop;
// end
`endif
if (THE_OTHER_FOO != 5) begin
$display("%%Error: THE_OTHER_FOO = %0d", THE_OTHER_FOO);
$stop;
end
if (intf.FOO != 5) begin
$display("%%Error: intf.FOO = %0d", intf.FOO);
$stop;
end
// if (intf_no_mp.FOO != 5) begin
// $display("%%Error: intf_no_mp.FOO = %0d", intf_no_mp.FOO);
// $stop;
// end
if (intf_no_mp.FOO != 5) begin
$display("%%Error: intf_no_mp.FOO = %0d", intf_no_mp.FOO);
$stop;
end
// if (i.getFoo() != 5) begin
// $display("%%Error: i.getFoo() = %0d", i.getFoo());
// $stop;