Support `unconnected_drive
This commit is contained in:
parent
343db78c03
commit
15b40a97d9
|
|
@ -2420,6 +2420,7 @@ private:
|
|||
int m_level; // 1=top module, 2=cell off top module, ...
|
||||
int m_varNum; // Incrementing variable number
|
||||
int m_typeNum; // Incrementing implicit type number
|
||||
VOptionBool m_unconnectedDrive; // State of `unconnected_drive
|
||||
public:
|
||||
AstNodeModule(AstType t, FileLine* fl, const string& name)
|
||||
: AstNode(t, fl)
|
||||
|
|
@ -2461,6 +2462,8 @@ public:
|
|||
bool recursive() const { return m_recursive; }
|
||||
void recursiveClone(bool flag) { m_recursiveClone = flag; }
|
||||
bool recursiveClone() const { return m_recursiveClone; }
|
||||
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }
|
||||
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
|
||||
};
|
||||
|
||||
class AstNodeRange : public AstNode {
|
||||
|
|
|
|||
|
|
@ -547,7 +547,6 @@ private:
|
|||
// we'll save work, and we can't call pinReconnectSimple in
|
||||
// this loop as it clone()s itself.
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
|
||||
if (!pinp->exprp()) continue;
|
||||
V3Inst::pinReconnectSimple(pinp, nodep, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,13 +62,15 @@ private:
|
|||
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
|
||||
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
|
||||
UINFO(4," PIN "<<nodep<<endl);
|
||||
if (!nodep->user1()) {
|
||||
// Simplify it
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||
}
|
||||
if (!nodep->exprp()) return; // No-connect
|
||||
if (debug()>=9) nodep->dumpTree(cout, " Pin_oldb: ");
|
||||
V3Inst::checkOutputShort(nodep);
|
||||
// Use user1p on the PIN to indicate we created an assign for this pin
|
||||
if (!nodep->user1SetOnce()) {
|
||||
// Simplify it
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||
// Make an ASSIGNW (expr, pin)
|
||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||
UASSERT_OBJ(exprp->width() == nodep->modVarp()->width(), nodep,
|
||||
|
|
@ -481,8 +483,20 @@ public:
|
|||
// Else create a intermediate wire to perform the interconnect
|
||||
// Return the new assignment, if one was made
|
||||
// Note this module calles cloneTree() via new AstVar
|
||||
|
||||
AstVar* pinVarp = pinp->modVarp();
|
||||
if (!pinp->exprp()) {
|
||||
// No-connect, perhaps promote based on `unconnected_drive,
|
||||
// otherwise done
|
||||
if (pinVarp->direction() == VDirection::INPUT
|
||||
&& cellp->modp()->unconnectedDrive().isSetTrue()) {
|
||||
pinp->exprp(new AstConst(pinp->fileline(), AstConst::StringToParse(), "'1"));
|
||||
} else if (pinVarp->direction() == VDirection::INPUT
|
||||
&& cellp->modp()->unconnectedDrive().isSetFalse()) {
|
||||
pinp->exprp(new AstConst(pinp->fileline(), AstConst::StringToParse(), "'0"));
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
AstVarRef* connectRefp = VN_CAST(pinp->exprp(), VarRef);
|
||||
AstVarXRef* connectXRefp = VN_CAST(pinp->exprp(), VarXRef);
|
||||
AstBasicDType* pinBasicp = VN_CAST(pinVarp->dtypep(), BasicDType); // Maybe NULL
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ public:
|
|||
bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; }
|
||||
bool isTrue() const { return m_e == OPT_TRUE || m_e == OPT_DEFAULT_TRUE; }
|
||||
bool isFalse() const { return m_e == OPT_FALSE || m_e == OPT_DEFAULT_FALSE; }
|
||||
bool isSetTrue() const { return m_e == OPT_TRUE; }
|
||||
bool isSetFalse() const { return m_e == OPT_FALSE; }
|
||||
void setTrueOrFalse(bool flag) { m_e = flag ? OPT_TRUE : OPT_FALSE; }
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ class V3ParseImp {
|
|||
bool m_inLibrary; // Currently reading a library vs. regular file
|
||||
int m_inBeginKwd; // Inside a `begin_keywords
|
||||
int m_lastVerilogState; // Last LEX state in `begin_keywords
|
||||
VOptionBool m_unconnectedDrive; // Last unconnected drive
|
||||
|
||||
int m_prevLexToken; // previous parsed token (for lexer)
|
||||
bool m_ahead; // aheadval is valid
|
||||
|
|
@ -199,6 +200,8 @@ public:
|
|||
bool inCellDefine() const { return m_inCellDefine; }
|
||||
void inCellDefine(bool flag) { m_inCellDefine = flag; }
|
||||
bool inLibrary() const { return m_inLibrary; }
|
||||
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
|
||||
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }
|
||||
|
||||
// Interactions with parser
|
||||
int bisonParse();
|
||||
|
|
|
|||
|
|
@ -1087,10 +1087,8 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||
// Find child module's new variables.
|
||||
AstVar* enModVarp = static_cast<AstVar*>(nodep->modVarp()->user1p());
|
||||
if (!enModVarp) {
|
||||
if (nodep->exprp()) {
|
||||
// May have an output only that later connects to a tristate, so simplify now.
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||
}
|
||||
// May have an output only that later connects to a tristate, so simplify now.
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||
iteratePinGuts(nodep);
|
||||
return; // No __en signals on this pin
|
||||
}
|
||||
|
|
|
|||
|
|
@ -966,7 +966,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"`noremove_gatenames" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
|
||||
"`noremove_netnames" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
|
||||
"`nosuppress_faults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
|
||||
"`nounconnected_drive" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
|
||||
"`nounconnected_drive" { FL_FWD; PARSEP->unconnectedDrive(VOptionBool::OPT_DEFAULT_FALSE); FL_BRK; }
|
||||
"`portcoerce" { FL_FWD; FL_BRK; }
|
||||
"`pragma"{ws}*[^\n\r]* { FL_FWD; FL_BRK; } // Verilog 2005
|
||||
"`protect" { FL_FWD; FL_BRK; }
|
||||
|
|
@ -976,6 +976,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
return yaT_RESETALL; } // Rest handled by preproc
|
||||
"`suppress_faults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
|
||||
"`timescale"{ws}+[^\n\r]* { FL_FWD; FL_BRK; } // Verilog spec - not supported
|
||||
"`unconnected_drive"{ws}+"pull0" { FL_FWD; PARSEP->unconnectedDrive(VOptionBool::OPT_FALSE); FL_BRK; }
|
||||
"`unconnected_drive"{ws}+"pull1" { FL_FWD; PARSEP->unconnectedDrive(VOptionBool::OPT_TRUE); FL_BRK; }
|
||||
"`unconnected_drive" { FL_FWD; yyerrorf("Bad `unconnected_drive syntax"); FL_BRK; }
|
||||
"`uselib"{ws}+[^\n\r]* { FL_FWD; FL_BRK; } // Verilog-XL compatibility
|
||||
|
||||
/* See also setLanguage below */
|
||||
|
|
|
|||
|
|
@ -953,6 +953,7 @@ modFront<modulep>:
|
|||
{ $$ = new AstModule($<fl>3,*$3);
|
||||
$$->inLibrary(PARSEP->inLibrary() || PARSEP->inCellDefine());
|
||||
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
|
||||
$$->unconnectedDrive(PARSEP->unconnectedDrive());
|
||||
PARSEP->rootp()->addModulep($$);
|
||||
SYMP->pushNew($$); }
|
||||
;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2004 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;
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
wire o_n;
|
||||
wire o_0;
|
||||
wire o_1;
|
||||
|
||||
// verilator lint_off PINMISSING
|
||||
sub_0 sub_0(.o_0);
|
||||
sub_1 sub_1(.o_1);
|
||||
sub_n sub_n(.o_n);
|
||||
// verilator lint_on PINMISSING
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (o_0 !== 1'b0) $stop;
|
||||
if (o_1 !== 1'b1) $stop;
|
||||
//4-state if (o_n !== 1'bz) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`unconnected_drive pull0
|
||||
module sub_0 (input i, output wire o_0);
|
||||
assign o_0 = i;
|
||||
endmodule
|
||||
|
||||
`unconnected_drive pull1
|
||||
module sub_1 (input i, output wire o_1);
|
||||
assign o_1 = i;
|
||||
endmodule
|
||||
|
||||
`nounconnected_drive
|
||||
module sub_n (input i, output wire o_n);
|
||||
assign o_n = i;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
%Error: t/t_unconnected_bad.v:7:1: Bad `unconnected_drive syntax
|
||||
7 | `unconnected_drive
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
%Error: t/t_unconnected_bad.v:9:1: Bad `unconnected_drive syntax
|
||||
9 | `unconnected_drive pull2
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
%Error: t/t_unconnected_bad.v:9:20: syntax error, unexpected IDENTIFIER
|
||||
9 | `unconnected_drive pull2
|
||||
| ^~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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(linter => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2018 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`unconnected_drive
|
||||
|
||||
`unconnected_drive pull2
|
||||
|
||||
module t;
|
||||
endmodule
|
||||
Loading…
Reference in New Issue