Support non-ANSI interface port declarations (#3439).

This commit is contained in:
Wilson Snyder 2022-05-25 00:50:50 -04:00
parent 1282548a1c
commit 530817191e
5 changed files with 92 additions and 17 deletions

View File

@ -16,6 +16,7 @@ Verilator 4.223 devel
* Support compile time trace signal selection with tracing_on/off (#3323). [Shunyao CAD]
* Add assert when VerilatedContext is mis-deleted (#3121). [Rupert Swarbrick]
* Define VM_TRACE_VCD when tracing in VCD format. [Geza Lore, Shunyao CAD]
* Support non-ANSI interface port declarations (#3439). [Geza Lore, Shunyao CAD]
* Fix hang with large case statement optimization (#3405). [Mike Urbach]
* Fix 'with' operator with type casting (#3387). [xiak95]
* Fix incorrect conditional merging (#3409). [Raynard Qiao]

View File

@ -1478,11 +1478,11 @@ private:
// Need to set pin numbers after varnames are created
// But before we do the final resolution based on names
VSymEnt* const foundp = m_statep->getNodeSym(m_modp)->findIdFlat(nodep->name());
AstVar* const refp = foundp ? VN_AS(foundp->nodep(), Var) : nullptr;
if (!refp) {
AstVar* const refp = foundp ? VN_CAST(foundp->nodep(), Var) : nullptr;
if (!foundp) {
nodep->v3error(
"Input/output/inout declaration not found for port: " << nodep->prettyNameQ());
} else if (!refp->isIO() && !refp->isIfaceRef()) {
} else if (!refp || (!refp->isIO() && !refp->isIfaceRef())) {
nodep->v3error("Pin is not an in/out/inout/interface: " << nodep->prettyNameQ());
} else {
if (refp->user4()) {

View File

@ -104,6 +104,27 @@ public:
string newtext = deQuote(fileline, text);
return new AstText(fileline, newtext);
}
AstNode* createCellOrIfaceRef(FileLine* fileline, const string& name, AstPin* pinlistp, AstNodeRange* rangelistp) {
// Must clone m_instParamp as may be comma'ed list of instances
VSymEnt* const foundp = SYMP->symCurrentp()->findIdFallback(name);
if (foundp && VN_IS(foundp->nodep(), Port)) {
// It's a non-ANSI interface, not a cell declaration
m_varAttrp = nullptr;
m_varDecl = VVarType::IFACEREF;
m_varIO = VDirection::NONE;
m_varLifetime = VLifetime::NONE;
setDType(new AstIfaceRefDType{fileline, "", GRAMMARP->m_instModule});
m_varDeclTyped = true;
AstVar* const nodep = createVariable(fileline, name, rangelistp, nullptr);
return nodep;
}
AstCell* const nodep = new AstCell{fileline, GRAMMARP->m_instModuleFl,
name, GRAMMARP->m_instModule, pinlistp,
AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true),
GRAMMARP->scrubRange(rangelistp)};
nodep->trace(GRAMMARP->allTracingOn(fileline));
return nodep;
}
AstDisplay* createDisplayError(FileLine* fileline) {
AstDisplay* nodep = new AstDisplay(fileline, VDisplayType::DT_ERROR, "", nullptr, nullptr);
nodep->addNext(new AstStop(fileline, true));
@ -1418,8 +1439,10 @@ port_declNetE: // IEEE: part of port_declaration, optional net
;
portSig<nodep>:
id/*port*/ { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
| idSVKwd { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
id/*port*/
{ $$ = new AstPort{$<fl>1, PINNUMINC(), *$1}; SYMP->reinsert($$); }
| idSVKwd
{ $$ = new AstPort{$<fl>1, PINNUMINC(), *$1}; SYMP->reinsert($$); }
;
//**********************************************************************
@ -2869,18 +2892,11 @@ instnameList<nodep>:
| instnameList ',' instnameParen { $$ = $1->addNext($3); }
;
instnameParen<cellp>:
// // Must clone m_instParamp as may be comma'ed list of instances
id instRangeListE '(' cellpinList ')' { $$ = new AstCell($<fl>1, GRAMMARP->m_instModuleFl,
*$1, GRAMMARP->m_instModule, $4,
AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true),
GRAMMARP->scrubRange($2));
$$->trace(GRAMMARP->allTracingOn($<fl>1)); }
| id instRangeListE { $$ = new AstCell($<fl>1, GRAMMARP->m_instModuleFl,
*$1, GRAMMARP->m_instModule, nullptr,
AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true),
GRAMMARP->scrubRange($2));
$$->trace(GRAMMARP->allTracingOn($<fl>1)); }
instnameParen<nodep>:
id instRangeListE '(' cellpinList ')'
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, $4, $2); }
| id instRangeListE
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, nullptr, $2); }
//UNSUP instRangeListE '(' cellpinList ')' { UNSUP } // UDP
// // Adding above and switching to the Verilog-Perl syntax
// // causes a shift conflict due to use of idClassSel inside exprScope.

View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
interface iface(input logic clk);
logic [31:0] d = 0;
logic [31:0] q = 0;
endinterface
module mod(a);
iface a; // This is not a CELL, it is a port declaration
always @(posedge a.clk) a.q <= a.d;
endmodule
module t(clk);
input clk;
iface iface_inst(clk);
mod mod_inst(iface_inst);
int cyc = 0;
always @(posedge clk) begin
iface_inst.d <= cyc;
if (cyc > 1 && iface_inst.q != cyc - 2) $stop;
end
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 100) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule