forked from github/verilator
Support non-ANSI interface port declarations (#3439).
This commit is contained in:
parent
1282548a1c
commit
530817191e
1
Changes
1
Changes
@ -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]
|
||||
|
@ -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()) {
|
||||
|
@ -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.
|
||||
|
21
test_regress/t/t_interface_nansi.pl
Executable file
21
test_regress/t/t_interface_nansi.pl
Executable 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;
|
37
test_regress/t/t_interface_nansi.v
Normal file
37
test_regress/t/t_interface_nansi.v
Normal 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
|
Loading…
Reference in New Issue
Block a user